commit 2f9d26fd7eef30c3a96475ae2c5756fddac7b711 Author: oujunhui <313127320@qq.com> Date: Thu Apr 2 10:43:40 2020 +0800 66陪玩-origin diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a8eac4d02 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +*.DS_Store +/build +/captures +.externalNativeBuild +.idea +.settings \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 000000000..4566050a4 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + Qx_Andriod_Client + Project Qx_Andriod_Client created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/agora-ktv-kit-release/.gitignore b/agora-ktv-kit-release/.gitignore new file mode 100644 index 000000000..36af4938d --- /dev/null +++ b/agora-ktv-kit-release/.gitignore @@ -0,0 +1,3 @@ +/build +*.iml +*.DS_Store \ No newline at end of file diff --git a/agora-ktv-kit-release/agora-ktv-kit-release.aar b/agora-ktv-kit-release/agora-ktv-kit-release.aar new file mode 100644 index 000000000..a3a1b801c Binary files /dev/null and b/agora-ktv-kit-release/agora-ktv-kit-release.aar differ diff --git a/agora-ktv-kit-release/build.gradle b/agora-ktv-kit-release/build.gradle new file mode 100644 index 000000000..5e82351ab --- /dev/null +++ b/agora-ktv-kit-release/build.gradle @@ -0,0 +1,2 @@ +configurations.maybeCreate("default") +artifacts.add("default", file('agora-ktv-kit-release.aar')) diff --git a/android_crop_lib/.gitignore b/android_crop_lib/.gitignore new file mode 100644 index 000000000..36af4938d --- /dev/null +++ b/android_crop_lib/.gitignore @@ -0,0 +1,3 @@ +/build +*.iml +*.DS_Store \ No newline at end of file diff --git a/android_crop_lib/build.gradle b/android_crop_lib/build.gradle new file mode 100644 index 000000000..8ce5670aa --- /dev/null +++ b/android_crop_lib/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 26 + + defaultConfig { + minSdkVersion 19 + targetSdkVersion 26 + + testApplicationId 'com.soundcloud.android.crop.test' + testInstrumentationRunner 'android.test.InstrumentationTestRunner' + } + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + api 'com.android.support:support-annotations:23.0.1' + api 'com.android.support:support-v4:26.0.1' +} + diff --git a/android_crop_lib/src/main/AndroidManifest.xml b/android_crop_lib/src/main/AndroidManifest.xml new file mode 100644 index 000000000..0cb62bb6e --- /dev/null +++ b/android_crop_lib/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/Crop.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/Crop.java new file mode 100644 index 000000000..3ce06d618 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/Crop.java @@ -0,0 +1,266 @@ +package com.soundcloud.android.crop; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.Fragment; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.MediaStore; +import android.widget.Toast; + +/** + * Builder for crop Intents and utils for handling result + */ +public class Crop { + + public static final int REQUEST_CROP = 6709; + public static final int REQUEST_PICK = 9162; + public static final int RESULT_ERROR = 404; + + interface Extra { + String ASPECT_X = "aspect_x"; + String ASPECT_Y = "aspect_y"; + String MAX_X = "max_x"; + String MAX_Y = "max_y"; + String AS_PNG = "as_png"; + String ERROR = "error"; + } + + private Intent cropIntent; + + /** + * Create a crop Intent builder with source and destination image Uris + * + * @param source Uri for image to crop + * @param destination Uri for saving the cropped image + */ + public static Crop of(Uri source, Uri destination) { + return new Crop(source, destination); + } + + private Crop(Uri source, Uri destination) { + cropIntent = new Intent(); + cropIntent.setData(source); + cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, destination); + } + + /** + * Set fixed aspect ratio for crop area + * + * @param x Aspect X + * @param y Aspect Y + */ + public Crop withAspect(int x, int y) { + cropIntent.putExtra(Extra.ASPECT_X, x); + cropIntent.putExtra(Extra.ASPECT_Y, y); + return this; + } + + /** + * Crop area with fixed 1:1 aspect ratio + */ + public Crop asSquare() { + cropIntent.putExtra(Extra.ASPECT_X, 1); + cropIntent.putExtra(Extra.ASPECT_Y, 1); + return this; + } + + /** + * Set maximum crop size + * + * @param width Max width + * @param height Max height + */ + public Crop withMaxSize(int width, int height) { + cropIntent.putExtra(Extra.MAX_X, width); + cropIntent.putExtra(Extra.MAX_Y, height); + return this; + } + + /** + * Set whether to save the result as a PNG or not. Helpful to preserve alpha. + * @param asPng whether to save the result as a PNG or not + */ + public Crop asPng(boolean asPng) { + cropIntent.putExtra(Extra.AS_PNG, asPng); + return this; + } + + /** + * Send the crop Intent from an Activity + * + * @param activity Activity to receive result + */ + public void start(Activity activity) { + start(activity, REQUEST_CROP); + } + + /** + * Send the crop Intent from an Activity with a custom request code + * + * @param activity Activity to receive result + * @param requestCode requestCode for result + */ + public void start(Activity activity, int requestCode) { + activity.startActivityForResult(getIntent(activity), requestCode); + } + + /** + * Send the crop Intent from a Fragment + * + * @param context Context + * @param fragment Fragment to receive result + */ + public void start(Context context, Fragment fragment) { + start(context, fragment, REQUEST_CROP); + } + + /** + * Send the crop Intent from a support library Fragment + * + * @param context Context + * @param fragment Fragment to receive result + */ + public void start(Context context, android.support.v4.app.Fragment fragment) { + start(context, fragment, REQUEST_CROP); + } + + /** + * Send the crop Intent with a custom request code + * + * @param context Context + * @param fragment Fragment to receive result + * @param requestCode requestCode for result + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void start(Context context, Fragment fragment, int requestCode) { + fragment.startActivityForResult(getIntent(context), requestCode); + } + + /** + * Send the crop Intent with a custom request code + * + * @param context Context + * @param fragment Fragment to receive result + * @param requestCode requestCode for result + */ + public void start(Context context, android.support.v4.app.Fragment fragment, int requestCode) { + fragment.startActivityForResult(getIntent(context), requestCode); + } + + /** + * Get Intent to start crop Activity + * + * @param context Context + * @return Intent for CropImageActivity + */ + public Intent getIntent(Context context) { + cropIntent.setClass(context, CropImageActivity.class); + return cropIntent; + } + + /** + * Retrieve URI for cropped image, as set in the Intent builder + * + * @param result Output Image URI + */ + public static Uri getOutput(Intent result) { + return result.getParcelableExtra(MediaStore.EXTRA_OUTPUT); + } + + /** + * Retrieve error that caused crop to fail + * + * @param result Result Intent + * @return Throwable handled in CropImageActivity + */ + public static Throwable getError(Intent result) { + return (Throwable) result.getSerializableExtra(Extra.ERROR); + } + + /** + * Pick image from an Activity + * + * @param activity Activity to receive result + */ + public static void pickImage(Activity activity) { + pickImage(activity, REQUEST_PICK); + } + + /** + * Pick image from a Fragment + * + * @param context Context + * @param fragment Fragment to receive result + */ + public static void pickImage(Context context, Fragment fragment) { + pickImage(context, fragment, REQUEST_PICK); + } + + /** + * Pick image from a support library Fragment + * + * @param context Context + * @param fragment Fragment to receive result + */ + public static void pickImage(Context context, android.support.v4.app.Fragment fragment) { + pickImage(context, fragment, REQUEST_PICK); + } + + /** + * Pick image from an Activity with a custom request code + * + * @param activity Activity to receive result + * @param requestCode requestCode for result + */ + public static void pickImage(Activity activity, int requestCode) { + try { + activity.startActivityForResult(getImagePicker(), requestCode); + } catch (ActivityNotFoundException e) { + showImagePickerError(activity); + } + } + + /** + * Pick image from a Fragment with a custom request code + * + * @param context Context + * @param fragment Fragment to receive result + * @param requestCode requestCode for result + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static void pickImage(Context context, Fragment fragment, int requestCode) { + try { + fragment.startActivityForResult(getImagePicker(), requestCode); + } catch (ActivityNotFoundException e) { + showImagePickerError(context); + } + } + + /** + * Pick image from a support library Fragment with a custom request code + * + * @param context Context + * @param fragment Fragment to receive result + * @param requestCode requestCode for result + */ + public static void pickImage(Context context, android.support.v4.app.Fragment fragment, int requestCode) { + try { + fragment.startActivityForResult(getImagePicker(), requestCode); + } catch (ActivityNotFoundException e) { + showImagePickerError(context); + } + } + + private static Intent getImagePicker() { + return new Intent(Intent.ACTION_GET_CONTENT).setType("image/*"); + } + + private static void showImagePickerError(Context context) { + Toast.makeText(context.getApplicationContext(), R.string.crop__pick_error, Toast.LENGTH_SHORT).show(); + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java new file mode 100644 index 000000000..1cb31d04e --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageActivity.java @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.RectF; +import android.net.Uri; +import android.opengl.GLES10; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.provider.MediaStore; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.CountDownLatch; + +/* + * Modified from original in AOSP. + */ +public class CropImageActivity extends MonitoredActivity { + + private static final int SIZE_DEFAULT = 2048; + private static final int SIZE_LIMIT = 4096; + + private final Handler handler = new Handler(); + + private int aspectX; + private int aspectY; + + // Output image + private int maxX; + private int maxY; + private int exifRotation; + private boolean saveAsPng; + + private Uri sourceUri; + private Uri saveUri; + + private boolean isSaving; + + private int sampleSize; + private RotateBitmap rotateBitmap; + private CropImageView imageView; + private HighlightView cropView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setupWindowFlags(); + setupViews(); + + loadInput(); + if (rotateBitmap == null) { + finish(); + return; + } + startCrop(); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + private void setupWindowFlags() { + requestWindowFeature(Window.FEATURE_NO_TITLE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + } + + private void setupViews() { + setContentView(R.layout.crop__activity_crop); + + imageView = (CropImageView) findViewById(R.id.crop_image); + imageView.context = this; + imageView.setRecycler(new ImageViewTouchBase.Recycler() { + @Override + public void recycle(Bitmap b) { + b.recycle(); + System.gc(); + } + }); + + findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + setResult(RESULT_CANCELED); + finish(); + } + }); + + findViewById(R.id.btn_done).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + onSaveClicked(); + } + }); + } + + private void loadInput() { + Intent intent = getIntent(); + Bundle extras = intent.getExtras(); + + if (extras != null) { + aspectX = extras.getInt(Crop.Extra.ASPECT_X); + aspectY = extras.getInt(Crop.Extra.ASPECT_Y); + maxX = extras.getInt(Crop.Extra.MAX_X); + maxY = extras.getInt(Crop.Extra.MAX_Y); + saveAsPng = extras.getBoolean(Crop.Extra.AS_PNG, false); + saveUri = extras.getParcelable(MediaStore.EXTRA_OUTPUT); + } + + sourceUri = intent.getData(); + if (sourceUri != null) { + exifRotation = CropUtil.getExifRotation(CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri)); + + InputStream is = null; + try { + sampleSize = calculateBitmapSampleSize(sourceUri); + is = getContentResolver().openInputStream(sourceUri); + BitmapFactory.Options option = new BitmapFactory.Options(); + option.inSampleSize = sampleSize; + rotateBitmap = new RotateBitmap(BitmapFactory.decodeStream(is, null, option), exifRotation); + } catch (IOException e) { + Log.e("Error reading image: " + e.getMessage(), e); + setResultException(e); + } catch (OutOfMemoryError e) { + Log.e("OOM reading image: " + e.getMessage(), e); + setResultException(e); + } finally { + CropUtil.closeSilently(is); + } + } + } + + private int calculateBitmapSampleSize(Uri bitmapUri) throws IOException { + InputStream is = null; + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + try { + is = getContentResolver().openInputStream(bitmapUri); + BitmapFactory.decodeStream(is, null, options); // Just get image size + } finally { + CropUtil.closeSilently(is); + } + + int maxSize = getMaxImageSize(); + int sampleSize = 1; + while (options.outHeight / sampleSize > maxSize || options.outWidth / sampleSize > maxSize) { + sampleSize = sampleSize << 1; + } + return sampleSize; + } + + private int getMaxImageSize() { + int textureLimit = getMaxTextureSize(); + if (textureLimit == 0) { + return SIZE_DEFAULT; + } else { + return Math.min(textureLimit, SIZE_LIMIT); + } + } + + private int getMaxTextureSize() { + // The OpenGL texture size is the maximum size that can be drawn in an ImageView + int[] maxSize = new int[1]; + GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0); + return maxSize[0]; + } + + private void startCrop() { + if (isFinishing()) { + return; + } + imageView.setImageRotateBitmapResetBase(rotateBitmap, true); + CropUtil.startBackgroundJob(this, null, getResources().getString(R.string.crop__wait), + new Runnable() { + public void run() { + final CountDownLatch latch = new CountDownLatch(1); + handler.post(new Runnable() { + public void run() { + if (imageView.getScale() == 1F) { + imageView.center(); + } + latch.countDown(); + } + }); + try { + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + new Cropper().crop(); + } + }, handler + ); + } + + private class Cropper { + + private void makeDefault() { + if (rotateBitmap == null) { + return; + } + + HighlightView hv = new HighlightView(imageView); + final int width = rotateBitmap.getWidth(); + final int height = rotateBitmap.getHeight(); + + Rect imageRect = new Rect(0, 0, width, height); + + // Make the default size about 4/5 of the width or height + int cropWidth = Math.min(width, height) * 4 / 5; + @SuppressWarnings("SuspiciousNameCombination") + int cropHeight = cropWidth; + + if (aspectX != 0 && aspectY != 0) { + if (aspectX > aspectY) { + cropHeight = cropWidth * aspectY / aspectX; + } else { + cropWidth = cropHeight * aspectX / aspectY; + } + } + + int x = (width - cropWidth) / 2; + int y = (height - cropHeight) / 2; + + RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight); + hv.setup(imageView.getUnrotatedMatrix(), imageRect, cropRect, aspectX != 0 && aspectY != 0); + imageView.add(hv); + } + + public void crop() { + handler.post(new Runnable() { + public void run() { + makeDefault(); + imageView.invalidate(); + if (imageView.highlightViews.size() == 1) { + cropView = imageView.highlightViews.get(0); + cropView.setFocus(true); + } + } + }); + } + } + + private void onSaveClicked() { + if (cropView == null || isSaving) { + return; + } + isSaving = true; + + Bitmap croppedImage; + Rect r = cropView.getScaledCropRect(sampleSize); + int width = r.width(); + int height = r.height(); + + int outWidth = width; + int outHeight = height; + if (maxX > 0 && maxY > 0 && (width > maxX || height > maxY)) { + float ratio = (float) width / (float) height; + if ((float) maxX / (float) maxY > ratio) { + outHeight = maxY; + outWidth = (int) ((float) maxY * ratio + .5f); + } else { + outWidth = maxX; + outHeight = (int) ((float) maxX / ratio + .5f); + } + } + + try { + croppedImage = decodeRegionCrop(r, outWidth, outHeight); + } catch (IllegalArgumentException e) { + setResultException(e); + finish(); + return; + } + + if (croppedImage != null) { + imageView.setImageRotateBitmapResetBase(new RotateBitmap(croppedImage, exifRotation), true); + imageView.center(); + imageView.highlightViews.clear(); + } + saveImage(croppedImage); + } + + private void saveImage(Bitmap croppedImage) { + if (croppedImage != null) { + final Bitmap b = croppedImage; + CropUtil.startBackgroundJob(this, null, getResources().getString(R.string.crop__saving), + new Runnable() { + public void run() { + saveOutput(b); + } + }, handler + ); + } else { + finish(); + } + } + + private Bitmap decodeRegionCrop(Rect rect, int outWidth, int outHeight) { + // Release memory now + clearImageView(); + + InputStream is = null; + Bitmap croppedImage = null; + try { + is = getContentResolver().openInputStream(sourceUri); + BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); + final int width = decoder.getWidth(); + final int height = decoder.getHeight(); + + if (exifRotation != 0) { + // Adjust crop area to account for image rotation + Matrix matrix = new Matrix(); + matrix.setRotate(-exifRotation); + + RectF adjusted = new RectF(); + matrix.mapRect(adjusted, new RectF(rect)); + + // Adjust to account for origin at 0,0 + adjusted.offset(adjusted.left < 0 ? width : 0, adjusted.top < 0 ? height : 0); + rect = new Rect((int) adjusted.left, (int) adjusted.top, (int) adjusted.right, (int) adjusted.bottom); + } + + try { + croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options()); + if (croppedImage != null && (rect.width() > outWidth || rect.height() > outHeight)) { + Matrix matrix = new Matrix(); + matrix.postScale((float) outWidth / rect.width(), (float) outHeight / rect.height()); + croppedImage = Bitmap.createBitmap(croppedImage, 0, 0, croppedImage.getWidth(), croppedImage.getHeight(), matrix, true); + } + } catch (IllegalArgumentException e) { + // Rethrow with some extra information + throw new IllegalArgumentException("Rectangle " + rect + " is outside of the image (" + + width + "," + height + "," + exifRotation + ")", e); + } + + } catch (IOException e) { + Log.e("Error cropping image: " + e.getMessage(), e); + setResultException(e); + } catch (OutOfMemoryError e) { + Log.e("OOM cropping image: " + e.getMessage(), e); + setResultException(e); + } finally { + CropUtil.closeSilently(is); + } + return croppedImage; + } + + private void clearImageView() { + imageView.clear(); + if (rotateBitmap != null) { + rotateBitmap.recycle(); + } + System.gc(); + } + + private void saveOutput(Bitmap croppedImage) { + if (saveUri != null) { + OutputStream outputStream = null; + try { + outputStream = getContentResolver().openOutputStream(saveUri); + if (outputStream != null) { + croppedImage.compress(saveAsPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, + 90, // note: quality is ignored when using PNG + outputStream); + } + } catch (IOException e) { + setResultException(e); + Log.e("Cannot open file: " + saveUri, e); + } finally { + CropUtil.closeSilently(outputStream); + } + + CropUtil.copyExifRotation( + CropUtil.getFromMediaUri(this, getContentResolver(), sourceUri), + CropUtil.getFromMediaUri(this, getContentResolver(), saveUri) + ); + + setResultUri(saveUri); + } + + final Bitmap b = croppedImage; + handler.post(new Runnable() { + public void run() { + imageView.clear(); + b.recycle(); + } + }); + + finish(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (rotateBitmap != null) { + rotateBitmap.recycle(); + } + } + + @Override + public boolean onSearchRequested() { + return false; + } + + public boolean isSaving() { + return isSaving; + } + + private void setResultUri(Uri uri) { + setResult(RESULT_OK, new Intent().putExtra(MediaStore.EXTRA_OUTPUT, uri)); + } + + private void setResultException(Throwable throwable) { + setResult(Crop.RESULT_ERROR, new Intent().putExtra(Crop.Extra.ERROR, throwable)); + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageView.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageView.java new file mode 100644 index 000000000..f6350cc55 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropImageView.java @@ -0,0 +1,195 @@ +package com.soundcloud.android.crop; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import java.util.ArrayList; + +public class CropImageView extends ImageViewTouchBase { + + ArrayList highlightViews = new ArrayList(); + HighlightView motionHighlightView; + Context context; + + private float lastX; + private float lastY; + private int motionEdge; + private int validPointerId; + + public CropImageView(Context context) { + super(context); + } + + public CropImageView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CropImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (bitmapDisplayed.getBitmap() != null) { + for (HighlightView hv : highlightViews) { + + hv.matrix.set(getUnrotatedMatrix()); + hv.invalidate(); + if (hv.hasFocus()) { + centerBasedOnHighlightView(hv); + } + } + } + } + + @Override + protected void zoomTo(float scale, float centerX, float centerY) { + super.zoomTo(scale, centerX, centerY); + for (HighlightView hv : highlightViews) { + hv.matrix.set(getUnrotatedMatrix()); + hv.invalidate(); + } + } + + @Override + protected void zoomIn() { + super.zoomIn(); + for (HighlightView hv : highlightViews) { + hv.matrix.set(getUnrotatedMatrix()); + hv.invalidate(); + } + } + + @Override + protected void zoomOut() { + super.zoomOut(); + for (HighlightView hv : highlightViews) { + hv.matrix.set(getUnrotatedMatrix()); + hv.invalidate(); + } + } + + @Override + protected void postTranslate(float deltaX, float deltaY) { + super.postTranslate(deltaX, deltaY); + for (HighlightView hv : highlightViews) { + hv.matrix.postTranslate(deltaX, deltaY); + hv.invalidate(); + } + } + + @Override + public boolean onTouchEvent(@NonNull MotionEvent event) { + CropImageActivity cropImageActivity = (CropImageActivity) context; + if (cropImageActivity.isSaving()) { + return false; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + for (HighlightView hv : highlightViews) { + int edge = hv.getHit(event.getX(), event.getY()); + if (edge != HighlightView.GROW_NONE) { + motionEdge = edge; + motionHighlightView = hv; + lastX = event.getX(); + lastY = event.getY(); + // Prevent multiple touches from interfering with crop area re-sizing + validPointerId = event.getPointerId(event.getActionIndex()); + motionHighlightView.setMode((edge == HighlightView.MOVE) + ? HighlightView.ModifyMode.Move + : HighlightView.ModifyMode.Grow); + break; + } + } + break; + case MotionEvent.ACTION_UP: + if (motionHighlightView != null) { + centerBasedOnHighlightView(motionHighlightView); + motionHighlightView.setMode(HighlightView.ModifyMode.None); + } + motionHighlightView = null; + center(); + break; + case MotionEvent.ACTION_MOVE: + if (motionHighlightView != null && event.getPointerId(event.getActionIndex()) == validPointerId) { + motionHighlightView.handleMotion(motionEdge, event.getX() + - lastX, event.getY() - lastY); + lastX = event.getX(); + lastY = event.getY(); + } + + // If we're not zoomed then there's no point in even allowing the user to move the image around. + // This call to center puts it back to the normalized location. + if (getScale() == 1F) { + center(); + } + break; + } + + return true; + } + + // Pan the displayed image to make sure the cropping rectangle is visible. + private void ensureVisible(HighlightView hv) { + Rect r = hv.drawRect; + + int panDeltaX1 = Math.max(0, getLeft() - r.left); + int panDeltaX2 = Math.min(0, getRight() - r.right); + + int panDeltaY1 = Math.max(0, getTop() - r.top); + int panDeltaY2 = Math.min(0, getBottom() - r.bottom); + + int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2; + int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2; + + if (panDeltaX != 0 || panDeltaY != 0) { + panBy(panDeltaX, panDeltaY); + } + } + + // If the cropping rectangle's size changed significantly, change the + // view's center and scale according to the cropping rectangle. + private void centerBasedOnHighlightView(HighlightView hv) { + Rect drawRect = hv.drawRect; + + float width = drawRect.width(); + float height = drawRect.height(); + + float thisWidth = getWidth(); + float thisHeight = getHeight(); + + float z1 = thisWidth / width * .6F; + float z2 = thisHeight / height * .6F; + + float zoom = Math.min(z1, z2); + zoom = zoom * this.getScale(); + zoom = Math.max(1F, zoom); + + if ((Math.abs(zoom - getScale()) / zoom) > .1) { + float[] coordinates = new float[] { hv.cropRect.centerX(), hv.cropRect.centerY() }; + getUnrotatedMatrix().mapPoints(coordinates); + zoomTo(zoom, coordinates[0], coordinates[1], 300F); + } + + ensureVisible(hv); + } + + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); + for (HighlightView highlightView : highlightViews) { + highlightView.draw(canvas); + } + } + + public void add(HighlightView hv) { + highlightViews.add(hv); + invalidate(); + } +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropUtil.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropUtil.java new file mode 100644 index 000000000..0bd878f61 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/CropUtil.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.app.ProgressDialog; +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.media.ExifInterface; +import android.net.Uri; +import android.os.Handler; +import android.os.ParcelFileDescriptor; +import android.provider.MediaStore; +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import java.io.Closeable; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/* + * Modified from original in AOSP. + */ +class CropUtil { + + private static final String SCHEME_FILE = "file"; + private static final String SCHEME_CONTENT = "content"; + + public static void closeSilently(@Nullable Closeable c) { + if (c == null) return; + try { + c.close(); + } catch (Throwable t) { + // Do nothing + } + } + + public static int getExifRotation(File imageFile) { + if (imageFile == null) return 0; + try { + ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath()); + // We only recognize a subset of orientation tag values + switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) { + case ExifInterface.ORIENTATION_ROTATE_90: + return 90; + case ExifInterface.ORIENTATION_ROTATE_180: + return 180; + case ExifInterface.ORIENTATION_ROTATE_270: + return 270; + default: + return ExifInterface.ORIENTATION_UNDEFINED; + } + } catch (IOException e) { + Log.e("Error getting Exif data", e); + return 0; + } + } + + public static boolean copyExifRotation(File sourceFile, File destFile) { + if (sourceFile == null || destFile == null) return false; + try { + ExifInterface exifSource = new ExifInterface(sourceFile.getAbsolutePath()); + ExifInterface exifDest = new ExifInterface(destFile.getAbsolutePath()); + exifDest.setAttribute(ExifInterface.TAG_ORIENTATION, exifSource.getAttribute(ExifInterface.TAG_ORIENTATION)); + exifDest.saveAttributes(); + return true; + } catch (IOException e) { + Log.e("Error copying Exif data", e); + return false; + } + } + + @Nullable + public static File getFromMediaUri(Context context, ContentResolver resolver, Uri uri) { + if (uri == null) return null; + + if (SCHEME_FILE.equals(uri.getScheme())) { + return new File(uri.getPath()); + } else if (SCHEME_CONTENT.equals(uri.getScheme())) { + final String[] filePathColumn = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME }; + Cursor cursor = null; + try { + cursor = resolver.query(uri, filePathColumn, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + final int columnIndex = (uri.toString().startsWith("content://com.google.android.gallery3d")) ? + cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME) : + cursor.getColumnIndex(MediaStore.MediaColumns.DATA); + // Picasa images on API 13+ + if (columnIndex != -1) { + String filePath = cursor.getString(columnIndex); + if (!TextUtils.isEmpty(filePath)) { + return new File(filePath); + } + } else if (TextUtils.equals(uri.getAuthority(), UriUtil.getFileProviderName(context))) { + //这里修复拍照自定义的uri获取路径失败的问题 + String path = UriUtil.parseOwnUri(context, uri); + if (!TextUtils.isEmpty(path)) { + File file = new File(path); + if (file.exists()) { + return file; + } + } + } + } + } catch (IllegalArgumentException e) { + // Google Drive images + return getFromMediaUriPfd(context, resolver, uri); + } catch (SecurityException ignored) { + // Nothing we can do + } finally { + if (cursor != null) cursor.close(); + } + } + return null; + } + + private static String getTempFilename(Context context) throws IOException { + File outputDir = context.getCacheDir(); + File outputFile = File.createTempFile("image", "tmp", outputDir); + return outputFile.getAbsolutePath(); + } + + @Nullable + private static File getFromMediaUriPfd(Context context, ContentResolver resolver, Uri uri) { + if (uri == null) return null; + + FileInputStream input = null; + FileOutputStream output = null; + try { + ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r"); + FileDescriptor fd = pfd.getFileDescriptor(); + input = new FileInputStream(fd); + + String tempFilename = getTempFilename(context); + output = new FileOutputStream(tempFilename); + + int read; + byte[] bytes = new byte[4096]; + while ((read = input.read(bytes)) != -1) { + output.write(bytes, 0, read); + } + return new File(tempFilename); + } catch (IOException ignored) { + // Nothing we can do + } finally { + closeSilently(input); + closeSilently(output); + } + return null; + } + + public static void startBackgroundJob(MonitoredActivity activity, + String title, String message, Runnable job, Handler handler) { + // Make the progress dialog uncancelable, so that we can guarantee + // the thread will be done before the activity getting destroyed + ProgressDialog dialog = ProgressDialog.show( + activity, title, message, true, false); + new Thread(new BackgroundJob(activity, job, dialog, handler)).start(); + } + + private static class BackgroundJob extends MonitoredActivity.LifeCycleAdapter implements Runnable { + + private final MonitoredActivity activity; + private final ProgressDialog dialog; + private final Runnable job; + private final Handler handler; + private final Runnable cleanupRunner = new Runnable() { + public void run() { + activity.removeLifeCycleListener(BackgroundJob.this); + if (dialog.getWindow() != null) dialog.dismiss(); + } + }; + + public BackgroundJob(MonitoredActivity activity, Runnable job, + ProgressDialog dialog, Handler handler) { + this.activity = activity; + this.dialog = dialog; + this.job = job; + this.activity.addLifeCycleListener(this); + this.handler = handler; + } + + public void run() { + try { + job.run(); + } finally { + handler.post(cleanupRunner); + } + } + + @Override + public void onActivityDestroyed(MonitoredActivity activity) { + // We get here only when the onDestroyed being called before + // the cleanupRunner. So, run it now and remove it from the queue + cleanupRunner.run(); + handler.removeCallbacks(cleanupRunner); + } + + @Override + public void onActivityStopped(MonitoredActivity activity) { + dialog.hide(); + } + + @Override + public void onActivityStarted(MonitoredActivity activity) { + dialog.show(); + } + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/HighlightView.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/HighlightView.java new file mode 100644 index 000000000..27cc10da5 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/HighlightView.java @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.os.Build; +import android.util.TypedValue; +import android.view.View; + +/* + * Modified from version in AOSP. + * + * This class is used to display a highlighted cropping rectangle + * overlayed on the image. There are two coordinate spaces in use. One is + * image, another is screen. computeLayout() uses matrix to map from image + * space to screen space. + */ +class HighlightView { + + public static final int GROW_NONE = (1 << 0); + public static final int GROW_LEFT_EDGE = (1 << 1); + public static final int GROW_RIGHT_EDGE = (1 << 2); + public static final int GROW_TOP_EDGE = (1 << 3); + public static final int GROW_BOTTOM_EDGE = (1 << 4); + public static final int MOVE = (1 << 5); + + private static final int DEFAULT_HIGHLIGHT_COLOR = 0xFF33B5E5; + private static final float HANDLE_RADIUS_DP = 12f; + private static final float OUTLINE_DP = 2f; + + enum ModifyMode { None, Move, Grow } + enum HandleMode { Changing, Always, Never } + + RectF cropRect; // Image space + Rect drawRect; // Screen space + Matrix matrix; + private RectF imageRect; // Image space + + private final Paint outsidePaint = new Paint(); + private final Paint outlinePaint = new Paint(); + private final Paint handlePaint = new Paint(); + + private View viewContext; // View displaying image + private boolean showThirds; + private boolean showCircle; + private int highlightColor; + + private ModifyMode modifyMode = ModifyMode.None; + private HandleMode handleMode = HandleMode.Changing; + private boolean maintainAspectRatio; + private float initialAspectRatio; + private float handleRadius; + private float outlineWidth; + private boolean isFocused; + + public HighlightView(View context) { + viewContext = context; + initStyles(context.getContext()); + } + + private void initStyles(Context context) { + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(R.attr.cropImageStyle, outValue, true); + TypedArray attributes = context.obtainStyledAttributes(outValue.resourceId, R.styleable.CropImageView); + try { + showThirds = attributes.getBoolean(R.styleable.CropImageView_showThirds, false); + showCircle = attributes.getBoolean(R.styleable.CropImageView_showCircle, false); + highlightColor = attributes.getColor(R.styleable.CropImageView_highlightColor, + DEFAULT_HIGHLIGHT_COLOR); + handleMode = HandleMode.values()[attributes.getInt(R.styleable.CropImageView_showHandles, 0)]; + } finally { + attributes.recycle(); + } + } + + public void setup(Matrix m, Rect imageRect, RectF cropRect, boolean maintainAspectRatio) { + matrix = new Matrix(m); + + this.cropRect = cropRect; + this.imageRect = new RectF(imageRect); + this.maintainAspectRatio = maintainAspectRatio; + + initialAspectRatio = this.cropRect.width() / this.cropRect.height(); + drawRect = computeLayout(); + + outsidePaint.setARGB(125, 50, 50, 50); + outlinePaint.setStyle(Paint.Style.STROKE); + outlinePaint.setAntiAlias(true); + outlineWidth = dpToPx(OUTLINE_DP); + + handlePaint.setColor(highlightColor); + handlePaint.setStyle(Paint.Style.FILL); + handlePaint.setAntiAlias(true); + handleRadius = dpToPx(HANDLE_RADIUS_DP); + + modifyMode = ModifyMode.None; + } + + private float dpToPx(float dp) { + return dp * viewContext.getResources().getDisplayMetrics().density; + } + + protected void draw(Canvas canvas) { + canvas.save(); + Path path = new Path(); + outlinePaint.setStrokeWidth(outlineWidth); + if (!hasFocus()) { + outlinePaint.setColor(Color.BLACK); + canvas.drawRect(drawRect, outlinePaint); + } else { + Rect viewDrawingRect = new Rect(); + viewContext.getDrawingRect(viewDrawingRect); + + path.addRect(new RectF(drawRect), Path.Direction.CW); + outlinePaint.setColor(highlightColor); + + if (isClipPathSupported(canvas)) { + canvas.clipPath(path, Region.Op.DIFFERENCE); + canvas.drawRect(viewDrawingRect, outsidePaint); + } else { + drawOutsideFallback(canvas); + } + + canvas.restore(); + canvas.drawPath(path, outlinePaint); + + if (showThirds) { + drawThirds(canvas); + } + + if (showCircle) { + drawCircle(canvas); + } + + if (handleMode == HandleMode.Always || + (handleMode == HandleMode.Changing && modifyMode == ModifyMode.Grow)) { + drawHandles(canvas); + } + } + } + + /* + * Fall back to naive method for darkening outside crop area + */ + private void drawOutsideFallback(Canvas canvas) { + canvas.drawRect(0, 0, canvas.getWidth(), drawRect.top, outsidePaint); + canvas.drawRect(0, drawRect.bottom, canvas.getWidth(), canvas.getHeight(), outsidePaint); + canvas.drawRect(0, drawRect.top, drawRect.left, drawRect.bottom, outsidePaint); + canvas.drawRect(drawRect.right, drawRect.top, canvas.getWidth(), drawRect.bottom, outsidePaint); + } + + /* + * Clip path is broken, unreliable or not supported on: + * - JellyBean MR1 + * - ICS & ICS MR1 with hardware acceleration turned on + */ + @SuppressLint("NewApi") + private boolean isClipPathSupported(Canvas canvas) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) { + return false; + } else if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) + || Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + return true; + } else { + return !canvas.isHardwareAccelerated(); + } + } + + private void drawHandles(Canvas canvas) { + int xMiddle = drawRect.left + ((drawRect.right - drawRect.left) / 2); + int yMiddle = drawRect.top + ((drawRect.bottom - drawRect.top) / 2); + + canvas.drawCircle(drawRect.left, yMiddle, handleRadius, handlePaint); + canvas.drawCircle(xMiddle, drawRect.top, handleRadius, handlePaint); + canvas.drawCircle(drawRect.right, yMiddle, handleRadius, handlePaint); + canvas.drawCircle(xMiddle, drawRect.bottom, handleRadius, handlePaint); + } + + private void drawThirds(Canvas canvas) { + outlinePaint.setStrokeWidth(1); + float xThird = (drawRect.right - drawRect.left) / 3; + float yThird = (drawRect.bottom - drawRect.top) / 3; + + canvas.drawLine(drawRect.left + xThird, drawRect.top, + drawRect.left + xThird, drawRect.bottom, outlinePaint); + canvas.drawLine(drawRect.left + xThird * 2, drawRect.top, + drawRect.left + xThird * 2, drawRect.bottom, outlinePaint); + canvas.drawLine(drawRect.left, drawRect.top + yThird, + drawRect.right, drawRect.top + yThird, outlinePaint); + canvas.drawLine(drawRect.left, drawRect.top + yThird * 2, + drawRect.right, drawRect.top + yThird * 2, outlinePaint); + } + + private void drawCircle(Canvas canvas) { + outlinePaint.setStrokeWidth(1); + canvas.drawOval(new RectF(drawRect), outlinePaint); + } + + public void setMode(ModifyMode mode) { + if (mode != modifyMode) { + modifyMode = mode; + viewContext.invalidate(); + } + } + + // Determines which edges are hit by touching at (x, y) + public int getHit(float x, float y) { + Rect r = computeLayout(); + final float hysteresis = 20F; + int retval = GROW_NONE; + + // verticalCheck makes sure the position is between the top and + // the bottom edge (with some tolerance). Similar for horizCheck. + boolean verticalCheck = (y >= r.top - hysteresis) + && (y < r.bottom + hysteresis); + boolean horizCheck = (x >= r.left - hysteresis) + && (x < r.right + hysteresis); + + // Check whether the position is near some edge(s) + if ((Math.abs(r.left - x) < hysteresis) && verticalCheck) { + retval |= GROW_LEFT_EDGE; + } + if ((Math.abs(r.right - x) < hysteresis) && verticalCheck) { + retval |= GROW_RIGHT_EDGE; + } + if ((Math.abs(r.top - y) < hysteresis) && horizCheck) { + retval |= GROW_TOP_EDGE; + } + if ((Math.abs(r.bottom - y) < hysteresis) && horizCheck) { + retval |= GROW_BOTTOM_EDGE; + } + + // Not near any edge but inside the rectangle: move + if (retval == GROW_NONE && r.contains((int) x, (int) y)) { + retval = MOVE; + } + return retval; + } + + // Handles motion (dx, dy) in screen space. + // The "edge" parameter specifies which edges the user is dragging. + void handleMotion(int edge, float dx, float dy) { + Rect r = computeLayout(); + if (edge == MOVE) { + // Convert to image space before sending to moveBy() + moveBy(dx * (cropRect.width() / r.width()), + dy * (cropRect.height() / r.height())); + } else { + if (((GROW_LEFT_EDGE | GROW_RIGHT_EDGE) & edge) == 0) { + dx = 0; + } + + if (((GROW_TOP_EDGE | GROW_BOTTOM_EDGE) & edge) == 0) { + dy = 0; + } + + // Convert to image space before sending to growBy() + float xDelta = dx * (cropRect.width() / r.width()); + float yDelta = dy * (cropRect.height() / r.height()); + growBy((((edge & GROW_LEFT_EDGE) != 0) ? -1 : 1) * xDelta, + (((edge & GROW_TOP_EDGE) != 0) ? -1 : 1) * yDelta); + } + } + + // Grows the cropping rectangle by (dx, dy) in image space + void moveBy(float dx, float dy) { + Rect invalRect = new Rect(drawRect); + + cropRect.offset(dx, dy); + + // Put the cropping rectangle inside image rectangle + cropRect.offset( + Math.max(0, imageRect.left - cropRect.left), + Math.max(0, imageRect.top - cropRect.top)); + + cropRect.offset( + Math.min(0, imageRect.right - cropRect.right), + Math.min(0, imageRect.bottom - cropRect.bottom)); + + drawRect = computeLayout(); + invalRect.union(drawRect); + invalRect.inset(-(int) handleRadius, -(int) handleRadius); + viewContext.invalidate(invalRect); + } + + // Grows the cropping rectangle by (dx, dy) in image space. + void growBy(float dx, float dy) { + if (maintainAspectRatio) { + if (dx != 0) { + dy = dx / initialAspectRatio; + } else if (dy != 0) { + dx = dy * initialAspectRatio; + } + } + + // Don't let the cropping rectangle grow too fast. + // Grow at most half of the difference between the image rectangle and + // the cropping rectangle. + RectF r = new RectF(cropRect); + if (dx > 0F && r.width() + 2 * dx > imageRect.width()) { + dx = (imageRect.width() - r.width()) / 2F; + if (maintainAspectRatio) { + dy = dx / initialAspectRatio; + } + } + if (dy > 0F && r.height() + 2 * dy > imageRect.height()) { + dy = (imageRect.height() - r.height()) / 2F; + if (maintainAspectRatio) { + dx = dy * initialAspectRatio; + } + } + + r.inset(-dx, -dy); + + // Don't let the cropping rectangle shrink too fast + final float widthCap = 25F; + if (r.width() < widthCap) { + r.inset(-(widthCap - r.width()) / 2F, 0F); + } + float heightCap = maintainAspectRatio + ? (widthCap / initialAspectRatio) + : widthCap; + if (r.height() < heightCap) { + r.inset(0F, -(heightCap - r.height()) / 2F); + } + + // Put the cropping rectangle inside the image rectangle + if (r.left < imageRect.left) { + r.offset(imageRect.left - r.left, 0F); + } else if (r.right > imageRect.right) { + r.offset(-(r.right - imageRect.right), 0F); + } + if (r.top < imageRect.top) { + r.offset(0F, imageRect.top - r.top); + } else if (r.bottom > imageRect.bottom) { + r.offset(0F, -(r.bottom - imageRect.bottom)); + } + + cropRect.set(r); + drawRect = computeLayout(); + viewContext.invalidate(); + } + + // Returns the cropping rectangle in image space with specified scale + public Rect getScaledCropRect(float scale) { + return new Rect((int) (cropRect.left * scale), (int) (cropRect.top * scale), + (int) (cropRect.right * scale), (int) (cropRect.bottom * scale)); + } + + // Maps the cropping rectangle from image space to screen space + private Rect computeLayout() { + RectF r = new RectF(cropRect.left, cropRect.top, + cropRect.right, cropRect.bottom); + matrix.mapRect(r); + return new Rect(Math.round(r.left), Math.round(r.top), + Math.round(r.right), Math.round(r.bottom)); + } + + public void invalidate() { + drawRect = computeLayout(); + } + + public boolean hasFocus() { + return isFocused; + } + + public void setFocus(boolean isFocused) { + this.isFocused = isFocused; + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/ImageViewTouchBase.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/ImageViewTouchBase.java new file mode 100644 index 000000000..5e0d05f09 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/ImageViewTouchBase.java @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.widget.ImageView; + +/* + * Modified from original in AOSP. + */ +abstract class ImageViewTouchBase extends ImageView { + + private static final float SCALE_RATE = 1.25F; + + // This is the base transformation which is used to show the image + // initially. The current computation for this shows the image in + // it's entirety, letterboxing as needed. One could choose to + // show the image as cropped instead. + // + // This matrix is recomputed when we go from the thumbnail image to + // the full size image. + protected Matrix baseMatrix = new Matrix(); + + // This is the supplementary transformation which reflects what + // the user has done in terms of zooming and panning. + // + // This matrix remains the same when we go from the thumbnail image + // to the full size image. + protected Matrix suppMatrix = new Matrix(); + + // This is the final matrix which is computed as the concatentation + // of the base matrix and the supplementary matrix. + private final Matrix displayMatrix = new Matrix(); + + // Temporary buffer used for getting the values out of a matrix. + private final float[] matrixValues = new float[9]; + + // The current bitmap being displayed. + protected final RotateBitmap bitmapDisplayed = new RotateBitmap(null, 0); + + int thisWidth = -1; + int thisHeight = -1; + + float maxZoom; + + private Runnable onLayoutRunnable; + + protected Handler handler = new Handler(); + + // ImageViewTouchBase will pass a Bitmap to the Recycler if it has finished + // its use of that Bitmap + public interface Recycler { + public void recycle(Bitmap b); + } + + private Recycler recycler; + + public ImageViewTouchBase(Context context) { + super(context); + init(); + } + + public ImageViewTouchBase(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ImageViewTouchBase(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + public void setRecycler(Recycler recycler) { + this.recycler = recycler; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + thisWidth = right - left; + thisHeight = bottom - top; + Runnable r = onLayoutRunnable; + if (r != null) { + onLayoutRunnable = null; + r.run(); + } + if (bitmapDisplayed.getBitmap() != null) { + getProperBaseMatrix(bitmapDisplayed, baseMatrix, true); + setImageMatrix(getImageViewMatrix()); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { + event.startTracking(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) { + if (getScale() > 1.0f) { + // If we're zoomed in, pressing Back jumps out to show the + // entire image, otherwise Back returns the user to the gallery + zoomTo(1.0f); + return true; + } + } + return super.onKeyUp(keyCode, event); + } + + @Override + public void setImageBitmap(Bitmap bitmap) { + setImageBitmap(bitmap, 0); + } + + private void setImageBitmap(Bitmap bitmap, int rotation) { + super.setImageBitmap(bitmap); + Drawable d = getDrawable(); + if (d != null) { + d.setDither(true); + } + + Bitmap old = bitmapDisplayed.getBitmap(); + bitmapDisplayed.setBitmap(bitmap); + bitmapDisplayed.setRotation(rotation); + + if (old != null && old != bitmap && recycler != null) { + recycler.recycle(old); + } + } + + public void clear() { + setImageBitmapResetBase(null, true); + } + + + // This function changes bitmap, reset base matrix according to the size + // of the bitmap, and optionally reset the supplementary matrix + public void setImageBitmapResetBase(final Bitmap bitmap, final boolean resetSupp) { + setImageRotateBitmapResetBase(new RotateBitmap(bitmap, 0), resetSupp); + } + + public void setImageRotateBitmapResetBase(final RotateBitmap bitmap, final boolean resetSupp) { + final int viewWidth = getWidth(); + + if (viewWidth <= 0) { + onLayoutRunnable = new Runnable() { + public void run() { + setImageRotateBitmapResetBase(bitmap, resetSupp); + } + }; + return; + } + + if (bitmap.getBitmap() != null) { + getProperBaseMatrix(bitmap, baseMatrix, true); + setImageBitmap(bitmap.getBitmap(), bitmap.getRotation()); + } else { + baseMatrix.reset(); + setImageBitmap(null); + } + + if (resetSupp) { + suppMatrix.reset(); + } + setImageMatrix(getImageViewMatrix()); + maxZoom = calculateMaxZoom(); + } + + // Center as much as possible in one or both axis. Centering is defined as follows: + // * If the image is scaled down below the view's dimensions then center it. + // * If the image is scaled larger than the view and is translated out of view then translate it back into view. + protected void center() { + final Bitmap bitmap = bitmapDisplayed.getBitmap(); + if (bitmap == null) { + return; + } + Matrix m = getImageViewMatrix(); + + RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); + m.mapRect(rect); + + float height = rect.height(); + float width = rect.width(); + + float deltaX = 0, deltaY = 0; + + deltaY = centerVertical(rect, height, deltaY); + deltaX = centerHorizontal(rect, width, deltaX); + + postTranslate(deltaX, deltaY); + setImageMatrix(getImageViewMatrix()); + } + + private float centerVertical(RectF rect, float height, float deltaY) { + int viewHeight = getHeight(); + if (height < viewHeight) { + deltaY = (viewHeight - height) / 2 - rect.top; + } else if (rect.top > 0) { + deltaY = -rect.top; + } else if (rect.bottom < viewHeight) { + deltaY = getHeight() - rect.bottom; + } + return deltaY; + } + + private float centerHorizontal(RectF rect, float width, float deltaX) { + int viewWidth = getWidth(); + if (width < viewWidth) { + deltaX = (viewWidth - width) / 2 - rect.left; + } else if (rect.left > 0) { + deltaX = -rect.left; + } else if (rect.right < viewWidth) { + deltaX = viewWidth - rect.right; + } + return deltaX; + } + + private void init() { + setScaleType(ImageView.ScaleType.MATRIX); + } + + protected float getValue(Matrix matrix, int whichValue) { + matrix.getValues(matrixValues); + return matrixValues[whichValue]; + } + + // Get the scale factor out of the matrix. + protected float getScale(Matrix matrix) { + return getValue(matrix, Matrix.MSCALE_X); + } + + protected float getScale() { + return getScale(suppMatrix); + } + + // Setup the base matrix so that the image is centered and scaled properly. + private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix, boolean includeRotation) { + float viewWidth = getWidth(); + float viewHeight = getHeight(); + + float w = bitmap.getWidth(); + float h = bitmap.getHeight(); + matrix.reset(); + + // We limit up-scaling to 3x otherwise the result may look bad if it's a small icon + float widthScale = Math.min(viewWidth / w, 3.0f); + float heightScale = Math.min(viewHeight / h, 3.0f); + float scale = Math.min(widthScale, heightScale); + + if (includeRotation) { + matrix.postConcat(bitmap.getRotateMatrix()); + } + matrix.postScale(scale, scale); + matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F); + } + + // Combine the base matrix and the supp matrix to make the final matrix + protected Matrix getImageViewMatrix() { + // The final matrix is computed as the concatentation of the base matrix + // and the supplementary matrix + displayMatrix.set(baseMatrix); + displayMatrix.postConcat(suppMatrix); + return displayMatrix; + } + + public Matrix getUnrotatedMatrix(){ + Matrix unrotated = new Matrix(); + getProperBaseMatrix(bitmapDisplayed, unrotated, false); + unrotated.postConcat(suppMatrix); + return unrotated; + } + + protected float calculateMaxZoom() { + if (bitmapDisplayed.getBitmap() == null) { + return 1F; + } + + float fw = (float) bitmapDisplayed.getWidth() / (float) thisWidth; + float fh = (float) bitmapDisplayed.getHeight() / (float) thisHeight; + return Math.max(fw, fh) * 4; // 400% + } + + protected void zoomTo(float scale, float centerX, float centerY) { + if (scale > maxZoom) { + scale = maxZoom; + } + + float oldScale = getScale(); + float deltaScale = scale / oldScale; + + suppMatrix.postScale(deltaScale, deltaScale, centerX, centerY); + setImageMatrix(getImageViewMatrix()); + center(); + } + + protected void zoomTo(final float scale, final float centerX, + final float centerY, final float durationMs) { + final float incrementPerMs = (scale - getScale()) / durationMs; + final float oldScale = getScale(); + final long startTime = System.currentTimeMillis(); + + handler.post(new Runnable() { + public void run() { + long now = System.currentTimeMillis(); + float currentMs = Math.min(durationMs, now - startTime); + float target = oldScale + (incrementPerMs * currentMs); + zoomTo(target, centerX, centerY); + + if (currentMs < durationMs) { + handler.post(this); + } + } + }); + } + + protected void zoomTo(float scale) { + float cx = getWidth() / 2F; + float cy = getHeight() / 2F; + zoomTo(scale, cx, cy); + } + + protected void zoomIn() { + zoomIn(SCALE_RATE); + } + + protected void zoomOut() { + zoomOut(SCALE_RATE); + } + + protected void zoomIn(float rate) { + if (getScale() >= maxZoom) { + return; // Don't let the user zoom into the molecular level + } + if (bitmapDisplayed.getBitmap() == null) { + return; + } + + float cx = getWidth() / 2F; + float cy = getHeight() / 2F; + + suppMatrix.postScale(rate, rate, cx, cy); + setImageMatrix(getImageViewMatrix()); + } + + protected void zoomOut(float rate) { + if (bitmapDisplayed.getBitmap() == null) { + return; + } + + float cx = getWidth() / 2F; + float cy = getHeight() / 2F; + + // Zoom out to at most 1x + Matrix tmp = new Matrix(suppMatrix); + tmp.postScale(1F / rate, 1F / rate, cx, cy); + + if (getScale(tmp) < 1F) { + suppMatrix.setScale(1F, 1F, cx, cy); + } else { + suppMatrix.postScale(1F / rate, 1F / rate, cx, cy); + } + setImageMatrix(getImageViewMatrix()); + center(); + } + + protected void postTranslate(float dx, float dy) { + suppMatrix.postTranslate(dx, dy); + } + + protected void panBy(float dx, float dy) { + postTranslate(dx, dy); + setImageMatrix(getImageViewMatrix()); + } +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/Log.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/Log.java new file mode 100644 index 000000000..e5be72c55 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/Log.java @@ -0,0 +1,15 @@ +package com.soundcloud.android.crop; + +class Log { + + private static final String TAG = "android-crop"; + + public static void e(String msg) { + android.util.Log.e(TAG, msg); + } + + public static void e(String msg, Throwable e) { + android.util.Log.e(TAG, msg, e); + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/MonitoredActivity.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/MonitoredActivity.java new file mode 100644 index 000000000..8cdee5538 --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/MonitoredActivity.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.app.Activity; +import android.os.Bundle; + +import java.util.ArrayList; + +/* + * Modified from original in AOSP. + */ +abstract class MonitoredActivity extends Activity { + + private final ArrayList listeners = new ArrayList(); + + public static interface LifeCycleListener { + public void onActivityCreated(MonitoredActivity activity); + public void onActivityDestroyed(MonitoredActivity activity); + public void onActivityStarted(MonitoredActivity activity); + public void onActivityStopped(MonitoredActivity activity); + } + + public static class LifeCycleAdapter implements LifeCycleListener { + public void onActivityCreated(MonitoredActivity activity) {} + public void onActivityDestroyed(MonitoredActivity activity) {} + public void onActivityStarted(MonitoredActivity activity) {} + public void onActivityStopped(MonitoredActivity activity) {} + } + + public void addLifeCycleListener(LifeCycleListener listener) { + if (listeners.contains(listener)) return; + listeners.add(listener); + } + + public void removeLifeCycleListener(LifeCycleListener listener) { + listeners.remove(listener); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + for (LifeCycleListener listener : listeners) { + listener.onActivityCreated(this); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + for (LifeCycleListener listener : listeners) { + listener.onActivityDestroyed(this); + } + } + + @Override + protected void onStart() { + super.onStart(); + for (LifeCycleListener listener : listeners) { + listener.onActivityStarted(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + for (LifeCycleListener listener : listeners) { + listener.onActivityStopped(this); + } + } + +} diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/RotateBitmap.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/RotateBitmap.java new file mode 100644 index 000000000..22ef2b49d --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/RotateBitmap.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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.soundcloud.android.crop; + +import android.graphics.Bitmap; +import android.graphics.Matrix; + +/* + * Modified from original in AOSP. + */ +class RotateBitmap { + + private Bitmap bitmap; + private int rotation; + + public RotateBitmap(Bitmap bitmap, int rotation) { + this.bitmap = bitmap; + this.rotation = rotation % 360; + } + + public void setRotation(int rotation) { + this.rotation = rotation; + } + + public int getRotation() { + return rotation; + } + + public Bitmap getBitmap() { + return bitmap; + } + + public void setBitmap(Bitmap bitmap) { + this.bitmap = bitmap; + } + + public Matrix getRotateMatrix() { + // By default this is an identity matrix + Matrix matrix = new Matrix(); + if (bitmap != null && rotation != 0) { + // We want to do the rotation at origin, but since the bounding + // rectangle will be changed after rotation, so the delta values + // are based on old & new width/height respectively. + int cx = bitmap.getWidth() / 2; + int cy = bitmap.getHeight() / 2; + matrix.preTranslate(-cx, -cy); + matrix.postRotate(rotation); + matrix.postTranslate(getWidth() / 2, getHeight() / 2); + } + return matrix; + } + + public boolean isOrientationChanged() { + return (rotation / 90) % 2 != 0; + } + + public int getHeight() { + if (bitmap == null) return 0; + if (isOrientationChanged()) { + return bitmap.getWidth(); + } else { + return bitmap.getHeight(); + } + } + + public int getWidth() { + if (bitmap == null) return 0; + if (isOrientationChanged()) { + return bitmap.getHeight(); + } else { + return bitmap.getWidth(); + } + } + + public void recycle() { + if (bitmap != null) { + bitmap.recycle(); + bitmap = null; + } + } +} + diff --git a/android_crop_lib/src/main/java/com/soundcloud/android/crop/UriUtil.java b/android_crop_lib/src/main/java/com/soundcloud/android/crop/UriUtil.java new file mode 100644 index 000000000..dd673834e --- /dev/null +++ b/android_crop_lib/src/main/java/com/soundcloud/android/crop/UriUtil.java @@ -0,0 +1,48 @@ +package com.soundcloud.android.crop; + +import android.content.Context; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; + +import java.io.File; + +public class UriUtil { + + public final static String getFileProviderName(Context context){ + return context.getPackageName()+".fileprovider"; + } + + /** + * 将TakePhoto 提供的Uri 解析出文件绝对路径 + * + * @param uri + * @return + */ + public static String parseOwnUri(Context context, Uri uri) { + if (uri == null) return null; + String path; + if (TextUtils.equals(uri.getAuthority(), getFileProviderName(context))) { + String target_text_camera_photos = "camera_photos/"; + if (uri.getPath() != null && uri.getPath().contains(target_text_camera_photos)) { + path = new File(uri.getPath().replace(target_text_camera_photos, "")) + .getAbsolutePath(); + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + path = new File(Environment.getExternalStorageDirectory(), + uri.getPath()) + .getAbsolutePath(); + } else { + path = uri.getPath(); + } + } + + } else { + path = uri.getPath(); + } + return path; + } + +} diff --git a/android_crop_lib/src/main/res/drawable-hdpi/crop__divider.9.png b/android_crop_lib/src/main/res/drawable-hdpi/crop__divider.9.png new file mode 100644 index 000000000..0279e17a1 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-hdpi/crop__divider.9.png differ diff --git a/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_cancel.png b/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_cancel.png new file mode 100644 index 000000000..cde36e1fa Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_cancel.png differ diff --git a/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_done.png b/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_done.png new file mode 100644 index 000000000..58bf97217 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-hdpi/crop__ic_done.png differ diff --git a/android_crop_lib/src/main/res/drawable-mdpi/crop__divider.9.png b/android_crop_lib/src/main/res/drawable-mdpi/crop__divider.9.png new file mode 100644 index 000000000..0279e17a1 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-mdpi/crop__divider.9.png differ diff --git a/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_cancel.png b/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_cancel.png new file mode 100644 index 000000000..9f4c3d6a2 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_cancel.png differ diff --git a/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_done.png b/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_done.png new file mode 100644 index 000000000..cf5fab3ad Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-mdpi/crop__ic_done.png differ diff --git a/android_crop_lib/src/main/res/drawable-v21/crop__selectable_background.xml b/android_crop_lib/src/main/res/drawable-v21/crop__selectable_background.xml new file mode 100644 index 000000000..2b2560979 --- /dev/null +++ b/android_crop_lib/src/main/res/drawable-v21/crop__selectable_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android_crop_lib/src/main/res/drawable-xhdpi/crop__divider.9.png b/android_crop_lib/src/main/res/drawable-xhdpi/crop__divider.9.png new file mode 100644 index 000000000..65061c0f4 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-xhdpi/crop__divider.9.png differ diff --git a/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_cancel.png b/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_cancel.png new file mode 100644 index 000000000..ca7d159fd Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_cancel.png differ diff --git a/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_done.png b/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_done.png new file mode 100644 index 000000000..b8915716e Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-xhdpi/crop__ic_done.png differ diff --git a/android_crop_lib/src/main/res/drawable-xhdpi/crop__tile.png b/android_crop_lib/src/main/res/drawable-xhdpi/crop__tile.png new file mode 100644 index 000000000..b0b004404 Binary files /dev/null and b/android_crop_lib/src/main/res/drawable-xhdpi/crop__tile.png differ diff --git a/android_crop_lib/src/main/res/drawable/crop__selectable_background.xml b/android_crop_lib/src/main/res/drawable/crop__selectable_background.xml new file mode 100644 index 000000000..83c4a7de3 --- /dev/null +++ b/android_crop_lib/src/main/res/drawable/crop__selectable_background.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/drawable/crop__texture.xml b/android_crop_lib/src/main/res/drawable/crop__texture.xml new file mode 100644 index 000000000..23ec46945 --- /dev/null +++ b/android_crop_lib/src/main/res/drawable/crop__texture.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/layout/crop__activity_crop.xml b/android_crop_lib/src/main/res/layout/crop__activity_crop.xml new file mode 100644 index 000000000..b42483d5c --- /dev/null +++ b/android_crop_lib/src/main/res/layout/crop__activity_crop.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/layout/crop__layout_done_cancel.xml b/android_crop_lib/src/main/res/layout/crop__layout_done_cancel.xml new file mode 100644 index 000000000..fe070636c --- /dev/null +++ b/android_crop_lib/src/main/res/layout/crop__layout_done_cancel.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/android_crop_lib/src/main/res/values-ar/strings.xml b/android_crop_lib/src/main/res/values-ar/strings.xml new file mode 100644 index 000000000..6fb015740 --- /dev/null +++ b/android_crop_lib/src/main/res/values-ar/strings.xml @@ -0,0 +1,10 @@ + + + جارى حفظ الصورة … + رجاء الأنتظار … + الصورة غير متاحة + + تم + الغاء + + diff --git a/android_crop_lib/src/main/res/values-ca/strings.xml b/android_crop_lib/src/main/res/values-ca/strings.xml new file mode 100644 index 000000000..38471d63f --- /dev/null +++ b/android_crop_lib/src/main/res/values-ca/strings.xml @@ -0,0 +1,10 @@ + + + Guardant imatge… + Si us plau esperi… + No hi ha imatges disponibles + + ACCEPTAR + CANCEL·LAR + + diff --git a/android_crop_lib/src/main/res/values-de/strings.xml b/android_crop_lib/src/main/res/values-de/strings.xml new file mode 100644 index 000000000..d89e2a6fa --- /dev/null +++ b/android_crop_lib/src/main/res/values-de/strings.xml @@ -0,0 +1,10 @@ + + + Bild speichern… + Bitte warten… + Keine Bildquellen verfügbar + + übernehmen + abbrechen + + diff --git a/android_crop_lib/src/main/res/values-es/strings.xml b/android_crop_lib/src/main/res/values-es/strings.xml new file mode 100644 index 000000000..e6792bd1d --- /dev/null +++ b/android_crop_lib/src/main/res/values-es/strings.xml @@ -0,0 +1,10 @@ + + + Guardando imagen… + Por favor espere… + No hay imágenes disponibles + + ACEPTAR + CANCELAR + + diff --git a/android_crop_lib/src/main/res/values-fa/strings.xml b/android_crop_lib/src/main/res/values-fa/strings.xml new file mode 100644 index 000000000..a4f3d6cf5 --- /dev/null +++ b/android_crop_lib/src/main/res/values-fa/strings.xml @@ -0,0 +1,10 @@ + + + در حال ذخیره سازی + لطفاً صبر کنید ... + تصویری در دسترس نیست + + تأیید + انصراف + + diff --git a/android_crop_lib/src/main/res/values-fr/strings.xml b/android_crop_lib/src/main/res/values-fr/strings.xml new file mode 100644 index 000000000..40213cf65 --- /dev/null +++ b/android_crop_lib/src/main/res/values-fr/strings.xml @@ -0,0 +1,10 @@ + + + Enregistrement de l\'image… + Veuillez patienter… + Aucune image disponible + + ACCEPTER + ANNULER + + diff --git a/android_crop_lib/src/main/res/values-in/strings.xml b/android_crop_lib/src/main/res/values-in/strings.xml new file mode 100644 index 000000000..6cee600dc --- /dev/null +++ b/android_crop_lib/src/main/res/values-in/strings.xml @@ -0,0 +1,10 @@ + + + Menyimpan gambar… + Silakan tunggu… + Tidak ada sumber gambar yang tersedia + + SELESAI + BATAL + + diff --git a/android_crop_lib/src/main/res/values-it/strings.xml b/android_crop_lib/src/main/res/values-it/strings.xml new file mode 100644 index 000000000..f09bb7129 --- /dev/null +++ b/android_crop_lib/src/main/res/values-it/strings.xml @@ -0,0 +1,10 @@ + + + Salvataggio immagine… + Attendere prego… + Nessuna immagine disponibile + + ACCETTA + ANNULLA + + diff --git a/android_crop_lib/src/main/res/values-ja/strings.xml b/android_crop_lib/src/main/res/values-ja/strings.xml new file mode 100644 index 000000000..53ef9447f --- /dev/null +++ b/android_crop_lib/src/main/res/values-ja/strings.xml @@ -0,0 +1,10 @@ + + + 保存中… + お待ちください… + 画像が見つかりません + + 決定 + キャンセル + + diff --git a/android_crop_lib/src/main/res/values-ko/strings.xml b/android_crop_lib/src/main/res/values-ko/strings.xml new file mode 100644 index 000000000..b7e73177c --- /dev/null +++ b/android_crop_lib/src/main/res/values-ko/strings.xml @@ -0,0 +1,10 @@ + + + 사진을 저장중입니다… + 잠시만 기다려주세요… + 이미지가 존재하지 않습니다. + + 확인 + 취소 + + diff --git a/android_crop_lib/src/main/res/values-land/dimens.xml b/android_crop_lib/src/main/res/values-land/dimens.xml new file mode 100644 index 000000000..13b5b9fa6 --- /dev/null +++ b/android_crop_lib/src/main/res/values-land/dimens.xml @@ -0,0 +1,5 @@ + + + 48dp + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values-large/dimens.xml b/android_crop_lib/src/main/res/values-large/dimens.xml new file mode 100644 index 000000000..4b7027250 --- /dev/null +++ b/android_crop_lib/src/main/res/values-large/dimens.xml @@ -0,0 +1,5 @@ + + + 64dp + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values-pt/strings.xml b/android_crop_lib/src/main/res/values-pt/strings.xml new file mode 100644 index 000000000..3316a5904 --- /dev/null +++ b/android_crop_lib/src/main/res/values-pt/strings.xml @@ -0,0 +1,10 @@ + + + Salvando imagem… + Por favor, aguarde… + Sem fontes de imagem disponíveis + + FINALIZADO + CANCELAR + + diff --git a/android_crop_lib/src/main/res/values-ru/strings.xml b/android_crop_lib/src/main/res/values-ru/strings.xml new file mode 100644 index 000000000..404a5894a --- /dev/null +++ b/android_crop_lib/src/main/res/values-ru/strings.xml @@ -0,0 +1,10 @@ + + + Изображение сохраняется… + Пожалуйста, подождите… + Нет доступных изображений + + ГОТОВО + ОТМЕНА + + diff --git a/android_crop_lib/src/main/res/values-sv/strings.xml b/android_crop_lib/src/main/res/values-sv/strings.xml new file mode 100644 index 000000000..69b3aa927 --- /dev/null +++ b/android_crop_lib/src/main/res/values-sv/strings.xml @@ -0,0 +1,10 @@ + + + Sparar bild… + Var god vänta… + Inga bildkällor tillgängliga + + KLAR + AVBRYT + + diff --git a/android_crop_lib/src/main/res/values-tr/strings.xml b/android_crop_lib/src/main/res/values-tr/strings.xml new file mode 100644 index 000000000..a5365e746 --- /dev/null +++ b/android_crop_lib/src/main/res/values-tr/strings.xml @@ -0,0 +1,10 @@ + + + Fotoğraf kaydediliyor… + Lütfen bekleyin… + Fotoğraf bulunamadı + + TAMAM + ÇIKIŞ + + diff --git a/android_crop_lib/src/main/res/values-v21/colors.xml b/android_crop_lib/src/main/res/values-v21/colors.xml new file mode 100644 index 000000000..55a535059 --- /dev/null +++ b/android_crop_lib/src/main/res/values-v21/colors.xml @@ -0,0 +1,5 @@ + + + #aaaaaa + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values-zh-rCN/strings.xml b/android_crop_lib/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..2290bc38d --- /dev/null +++ b/android_crop_lib/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,10 @@ + + + 正在保存照片… + 请等待… + 无效的图片 + + 完成 + 取消 + + diff --git a/android_crop_lib/src/main/res/values-zh-rTW/strings.xml b/android_crop_lib/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..904459494 --- /dev/null +++ b/android_crop_lib/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,10 @@ + + + 正在儲存相片… + 請稍候… + 沒有可用的圖片來源 + + 完成 + 取消 + + diff --git a/android_crop_lib/src/main/res/values/attrs.xml b/android_crop_lib/src/main/res/values/attrs.xml new file mode 100644 index 000000000..86fed3526 --- /dev/null +++ b/android_crop_lib/src/main/res/values/attrs.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values/colors.xml b/android_crop_lib/src/main/res/values/colors.xml new file mode 100644 index 000000000..455f448a0 --- /dev/null +++ b/android_crop_lib/src/main/res/values/colors.xml @@ -0,0 +1,8 @@ + + + #f3f3f3 + #666666 + #1a000000 + #77000000 + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values/dimens.xml b/android_crop_lib/src/main/res/values/dimens.xml new file mode 100644 index 000000000..9051a35fe --- /dev/null +++ b/android_crop_lib/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 56dp + + \ No newline at end of file diff --git a/android_crop_lib/src/main/res/values/strings.xml b/android_crop_lib/src/main/res/values/strings.xml new file mode 100644 index 000000000..cc310bbe5 --- /dev/null +++ b/android_crop_lib/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + + Saving picture… + Please wait… + No image sources available + + DONE + CANCEL + + diff --git a/android_crop_lib/src/main/res/values/styles.xml b/android_crop_lib/src/main/res/values/styles.xml new file mode 100644 index 000000000..5b161c8f0 --- /dev/null +++ b/android_crop_lib/src/main/res/values/styles.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apkinfo.py b/apkinfo.py new file mode 100644 index 000000000..f99f72208 --- /dev/null +++ b/apkinfo.py @@ -0,0 +1,998 @@ +# This file is part of Androguard. +# +# Copyright (C) 2012, Anthony Desnos +# All rights reserved. +# +# 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. + +import StringIO +from struct import pack, unpack +from xml.sax.saxutils import escape +from zlib import crc32 +import re +import collections +import sys +import os +import logging +import types +import random +import string +import imp + +from xml.dom import minidom + +NS_ANDROID_URI = 'http://schemas.android.com/apk/res/android' + +ZIPMODULE = 1 + + +def read(filename, binary=True): + with open(filename, 'rb' if binary else 'r') as f: + return f.read() + + +def sign_apk(filename, keystore, storepass): + from subprocess import Popen, PIPE, STDOUT + compile = Popen([CONF["PATH_JARSIGNER"], "-sigalg", "MD5withRSA", + "-digestalg", "SHA1", "-storepass", storepass, "-keystore", + keystore, filename, "alias_name"], + stdout=PIPE, + stderr=STDOUT) + stdout, stderr = compile.communicate() + + +class Error(Exception): + """Base class for exceptions in this module.""" + pass + + +class FileNotPresent(Error): + pass + + +######################################################## APK FORMAT ######################################################## +class APK(object): + """ + This class can access to all elements in an APK file + + :param filename: specify the path of the file, or raw data + :param raw: specify if the filename is a path or raw data (optional) + :param mode: specify the mode to open the file (optional) + :param magic_file: specify the magic file (optional) + :param zipmodule: specify the type of zip module to use (0:chilkat, 1:zipfile, 2:patch zipfile) + + :type filename: string + :type raw: boolean + :type mode: string + :type magic_file: string + :type zipmodule: int + + :Example: + APK("myfile.apk") + APK(read("myfile.apk"), raw=True) + """ + + def __init__(self, + filename, + raw=False, + mode="r", + magic_file=None, + zipmodule=ZIPMODULE): + self.filename = filename + + self.xml = {} + self.axml = {} + self.arsc = {} + + self.package = "" + self.androidversion = {} + self.permissions = [] + self.declared_permissions = {} + self.valid_apk = False + + self.files = {} + self.files_crc32 = {} + + self.magic_file = magic_file + + if raw is True: + self.__raw = filename + else: + self.__raw = read(filename) + + self.zipmodule = zipmodule + + if zipmodule == 0: + self.zip = ChilkatZip(self.__raw) + elif zipmodule == 2: + from androguard.patch import zipfile + self.zip = zipfile.ZipFile(StringIO.StringIO(self.__raw), mode=mode) + else: + import zipfile + self.zip = zipfile.ZipFile(StringIO.StringIO(self.__raw), mode=mode) + + for i in self.zip.namelist(): + if i == "AndroidManifest.xml": + self.axml[i] = AXMLPrinter(self.zip.read(i)) + try: + self.xml[i] = minidom.parseString(self.axml[i].get_buff()) + except: + self.xml[i] = None + + if self.xml[i] != None: + self.package = self.xml[i].documentElement.getAttribute( + "package") + self.androidversion[ + "Code" + ] = self.xml[i].documentElement.getAttributeNS( + NS_ANDROID_URI, "versionCode") + self.androidversion[ + "Name" + ] = self.xml[i].documentElement.getAttributeNS( + NS_ANDROID_URI, "versionName") + + self.valid_apk = True + + def get_AndroidManifest(self): + """ + Return the Android Manifest XML file + + :rtype: xml object + """ + return self.xml["AndroidManifest.xml"] + + def is_valid_APK(self): + """ + Return true if the APK is valid, false otherwise + + :rtype: boolean + """ + return self.valid_apk + + def get_filename(self): + """ + Return the filename of the APK + + :rtype: string + """ + return self.filename + + def get_package(self): + """ + Return the name of the package + + :rtype: string + """ + return self.package + + def get_version_code(self): + """ + Return the android version code + + :rtype: string + """ + return self.androidversion["Code"] + + def get_version_name(self): + """ + Return the android version name + + :rtype: string + """ + return self.androidversion["Name"] + + def get_raw(self): + """ + Return raw bytes of the APK + + :rtype: string + """ + return self.__raw + + def get_elements(self, tag_name, attribute): + """ + Return elements in xml files which match with the tag name and the specific attribute + + :param tag_name: a string which specify the tag name + :param attribute: a string which specify the attribute + """ + l = [] + for i in self.xml: + for item in self.xml[i].getElementsByTagName(tag_name): + value = item.getAttributeNS(NS_ANDROID_URI, attribute) + value = self.format_value(value) + + l.append(str(value)) + return l + + def format_value(self, value): + if len(value) > 0: + if value[0] == ".": + value = self.package + value + else: + v_dot = value.find(".") + if v_dot == 0: + value = self.package + "." + value + elif v_dot == -1: + value = self.package + "." + value + return value + + def get_element(self, tag_name, attribute, **attribute_filter): + """ + Return element in xml files which match with the tag name and the specific attribute + + :param tag_name: specify the tag name + :type tag_name: string + :param attribute: specify the attribute + :type attribute: string + + :rtype: string + """ + for i in self.xml: + for item in self.xml[i].getElementsByTagName(tag_name): + skip_this_item = False + for attr, val in attribute_filter.items(): + attr_val = item.getAttributeNS(NS_ANDROID_URI, attr) + if attr_val != val: + skip_this_item = True + break + + if skip_this_item: + continue + + value = item.getAttributeNS(NS_ANDROID_URI, attribute) + + if len(value) > 0: + return value + return None + + def get_max_sdk_version(self): + """ + Return the android:maxSdkVersion attribute + + :rtype: string + """ + return self.get_element("uses-sdk", "maxSdkVersion") + + def get_min_sdk_version(self): + """ + Return the android:minSdkVersion attribute + + :rtype: string + """ + return self.get_element("uses-sdk", "minSdkVersion") + + def get_target_sdk_version(self): + """ + Return the android:targetSdkVersion attribute + + :rtype: string + """ + return self.get_element("uses-sdk", "targetSdkVersion") + + def get_android_manifest_axml(self): + """ + Return the :class:`AXMLPrinter` object which corresponds to the AndroidManifest.xml file + + :rtype: :class:`AXMLPrinter` + """ + try: + return self.axml["AndroidManifest.xml"] + except KeyError: + return None + + def get_android_manifest_xml(self): + """ + Return the xml object which corresponds to the AndroidManifest.xml file + + :rtype: object + """ + try: + return self.xml["AndroidManifest.xml"] + except KeyError: + return None + + def show(self): + + print "PACKAGE: ", self.get_package() + print "VERSION NAME:", self.get_version_name() + print "VERSION CODE:", self.get_version_code() + +################################## AXML FORMAT ######################################## +# Translated from +# http://code.google.com/p/android4me/source/browse/src/android/content/res/AXmlResourceParser.java + +UTF8_FLAG = 0x00000100 +CHUNK_STRINGPOOL_TYPE = 0x001C0001 +CHUNK_NULL_TYPE = 0x00000000 + + +class StringBlock(object): + + def __init__(self, buff): + self.start = buff.get_idx() + self._cache = {} + self.header_size, self.header = self.skipNullPadding(buff) + + self.chunkSize = unpack('> 8, header & 0xFF + + def getString(self, idx): + if idx in self._cache: + return self._cache[idx] + + if idx < 0 or not self.m_stringOffsets or idx >= len( + self.m_stringOffsets): + return "" + + offset = self.m_stringOffsets[idx] + + if self.m_isUTF8: + self._cache[idx] = self.decode8(offset) + else: + self._cache[idx] = self.decode16(offset) + + return self._cache[idx] + + def getStyle(self, idx): + # FIXME + return self.m_styles[idx] + + def decode8(self, offset): + str_len, skip = self.decodeLength(offset, 1) + offset += skip + + encoded_bytes, skip = self.decodeLength(offset, 1) + offset += skip + + data = self.m_charbuff[offset: offset + encoded_bytes] + + return self.decode_bytes(data, 'utf-8', str_len) + + def decode16(self, offset): + str_len, skip = self.decodeLength(offset, 2) + offset += skip + + encoded_bytes = str_len * 2 + + data = self.m_charbuff[offset: offset + encoded_bytes] + + return self.decode_bytes(data, 'utf-16', str_len) + + def decode_bytes(self, data, encoding, str_len): + string = data.decode(encoding, 'replace') + if len(string) != str_len: + warning("invalid decoded string length") + return string + + def decodeLength(self, offset, sizeof_char): + length = ord(self.m_charbuff[offset]) + + sizeof_2chars = sizeof_char << 1 + fmt_chr = 'B' if sizeof_char == 1 else 'H' + fmt = "<2" + fmt_chr + + length1, length2 = unpack(fmt, self.m_charbuff[offset:(offset + sizeof_2chars)]) + + highbit = 0x80 << (8 * (sizeof_char - 1)) + + if (length & highbit) != 0: + return ((length1 & ~highbit) << (8 * sizeof_char)) | length2, sizeof_2chars + else: + return length1, sizeof_char + + def show(self): + print "StringBlock(%x, %x, %x, %x, %x, %x" % ( + self.start, + self.header, + self.header_size, + self.chunkSize, + self.stringsOffset, + self.flags) + for i in range(0, len(self.m_stringOffsets)): + print i, repr(self.getString(i)) + +START_DOCUMENT = 0 +END_DOCUMENT = 1 +START_TAG = 2 +END_TAG = 3 +TEXT = 4 + +ATTRIBUTE_IX_NAMESPACE_URI = 0 +ATTRIBUTE_IX_NAME = 1 +ATTRIBUTE_IX_VALUE_STRING = 2 +ATTRIBUTE_IX_VALUE_TYPE = 3 +ATTRIBUTE_IX_VALUE_DATA = 4 +ATTRIBUTE_LENGHT = 5 + +CHUNK_AXML_FILE = 0x00080003 +CHUNK_RESOURCEIDS = 0x00080180 +CHUNK_XML_FIRST = 0x00100100 +CHUNK_XML_START_NAMESPACE = 0x00100100 +CHUNK_XML_END_NAMESPACE = 0x00100101 +CHUNK_XML_START_TAG = 0x00100102 +CHUNK_XML_END_TAG = 0x00100103 +CHUNK_XML_TEXT = 0x00100104 +CHUNK_XML_LAST = 0x00100104 + + +class AXMLParser(object): + + def __init__(self, raw_buff): + self.reset() + + self.valid_axml = True + self.buff = BuffHandle(raw_buff) + + axml_file = unpack(' CHUNK_XML_LAST: + warning("invalid chunk type") + + # Fake START_DOCUMENT event. + if chunkType == CHUNK_XML_START_TAG and event == -1: + self.m_event = START_DOCUMENT + break + + self.buff.read(4) # /*chunkSize*/ + lineNumber = unpack('> 16) - 1 + attributeCount = attributeCount & 0xFFFF + self.m_classAttribute = unpack('> 16) - 1 + + self.m_classAttribute = (self.m_classAttribute & 0xFFFF) - 1 + + for i in range(0, attributeCount * ATTRIBUTE_LENGHT): + self.m_attributes.append(unpack('> 24 + + self.m_event = START_TAG + break + + if chunkType == CHUNK_XML_END_TAG: + self.m_namespaceUri = unpack('= len(self.m_attributes): + warning("Invalid attribute index") + + return offset + + def getAttributeCount(self): + if self.m_event != START_TAG: + return -1 + + return len(self.m_attributes) / ATTRIBUTE_LENGHT + + def getAttributePrefix(self, index): + offset = self.getAttributeOffset(index) + uri = self.m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI] + + prefix = self.getPrefixByUri(uri) + + if prefix == -1: + return "" + + return self.sb.getString(prefix) + + def getAttributeName(self, index): + offset = self.getAttributeOffset(index) + name = self.m_attributes[offset + ATTRIBUTE_IX_NAME] + + if name == -1: + return "" + + res = self.sb.getString(name) + if not res: + attr = self.m_resourceIDs[name] + if attr in SYSTEM_RESOURCES['attributes']['inverse']: + res = 'android:' + SYSTEM_RESOURCES['attributes']['inverse'][ + attr + ] + + return res + + def getAttributeValueType(self, index): + offset = self.getAttributeOffset(index) + return self.m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE] + + def getAttributeValueData(self, index): + offset = self.getAttributeOffset(index) + return self.m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA] + + def getAttributeValue(self, index): + offset = self.getAttributeOffset(index) + valueType = self.m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE] + if valueType == TYPE_STRING: + valueString = self.m_attributes[offset + ATTRIBUTE_IX_VALUE_STRING] + return self.sb.getString(valueString) + # WIP + return "" + +# resource constants + +TYPE_ATTRIBUTE = 2 +TYPE_DIMENSION = 5 +TYPE_FIRST_COLOR_INT = 28 +TYPE_FIRST_INT = 16 +TYPE_FLOAT = 4 +TYPE_FRACTION = 6 +TYPE_INT_BOOLEAN = 18 +TYPE_INT_DEC = 16 +TYPE_INT_HEX = 17 +TYPE_LAST_COLOR_INT = 31 +TYPE_LAST_INT = 31 +TYPE_NULL = 0 +TYPE_REFERENCE = 1 +TYPE_STRING = 3 + +TYPE_TABLE = { + TYPE_ATTRIBUTE: "attribute", + TYPE_DIMENSION: "dimension", + TYPE_FLOAT: "float", + TYPE_FRACTION: "fraction", + TYPE_INT_BOOLEAN: "int_boolean", + TYPE_INT_DEC: "int_dec", + TYPE_INT_HEX: "int_hex", + TYPE_NULL: "null", + TYPE_REFERENCE: "reference", + TYPE_STRING: "string", +} + +RADIX_MULTS = [0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010] +DIMENSION_UNITS = ["px", "dip", "sp", "pt", "in", "mm"] +FRACTION_UNITS = ["%", "%p"] + +COMPLEX_UNIT_MASK = 15 + + +def complexToFloat(xcomplex): + return (float)(xcomplex & 0xFFFFFF00) * RADIX_MULTS[(xcomplex >> 4) & 3] + + +def getPackage(id): + if id >> 24 == 1: + return "android:" + return "" + + +def format_value(_type, _data, lookup_string=lambda ix: ""): + if _type == TYPE_STRING: + return lookup_string(_data) + + elif _type == TYPE_ATTRIBUTE: + return "?%s%08X" % (getPackage(_data), _data) + + elif _type == TYPE_REFERENCE: + return "@%s%08X" % (getPackage(_data), _data) + + elif _type == TYPE_FLOAT: + return "%f" % unpack("=f", pack("=L", _data))[0] + + elif _type == TYPE_INT_HEX: + return "0x%08X" % _data + + elif _type == TYPE_INT_BOOLEAN: + if _data == 0: + return "false" + return "true" + + elif _type == TYPE_DIMENSION: + return "%f%s" % (complexToFloat(_data), DIMENSION_UNITS[_data & COMPLEX_UNIT_MASK]) + + elif _type == TYPE_FRACTION: + return "%f%s" % (complexToFloat(_data) * 100, FRACTION_UNITS[_data & COMPLEX_UNIT_MASK]) + + elif _type >= TYPE_FIRST_COLOR_INT and _type <= TYPE_LAST_COLOR_INT: + return "#%08X" % _data + + elif _type >= TYPE_FIRST_INT and _type <= TYPE_LAST_INT: + return "%d" % long2int(_data) + + return "<0x%X, type 0x%02X>" % (_data, _type) + + +class AXMLPrinter(object): + + def __init__(self, raw_buff): + self.axml = AXMLParser(raw_buff) + self.xmlns = False + + self.buff = u'' + + while True and self.axml.is_valid(): + _type = self.axml.next() + + if _type == START_DOCUMENT: + self.buff += u'\n' + elif _type == START_TAG: + self.buff += u'<' + self.getPrefix(self.axml.getPrefix( + )) + self.axml.getName() + u'\n' + self.buff += self.axml.getXMLNS() + + for i in range(0, self.axml.getAttributeCount()): + self.buff += "%s%s=\"%s\"\n" % ( + self.getPrefix( + self.axml.getAttributePrefix(i)), + self.axml.getAttributeName(i), + self._escape(self.getAttributeValue(i))) + + self.buff += u'>\n' + + elif _type == END_TAG: + self.buff += "\n" % ( + self.getPrefix(self.axml.getPrefix()), self.axml.getName()) + + elif _type == TEXT: + self.buff += "%s\n" % self.axml.getText() + + elif _type == END_DOCUMENT: + break + + # pleed patch + def _escape(self, s): + s = s.replace("&", "&") + s = s.replace('"', """) + s = s.replace("'", "'") + s = s.replace("<", "<") + s = s.replace(">", ">") + return escape(s) + + def get_buff(self): + return self.buff.encode('utf-8') + + def get_xml(self): + return minidom.parseString(self.get_buff()).toprettyxml( + encoding="utf-8") + + def get_xml_obj(self): + return minidom.parseString(self.get_buff()) + + def getPrefix(self, prefix): + if prefix is None or len(prefix) == 0: + return u'' + + return prefix + u':' + + def getAttributeValue(self, index): + _type = self.axml.getAttributeValueType(index) + _data = self.axml.getAttributeValueData(index) + + return format_value(_type, _data, lambda _: self.axml.getAttributeValue(index)) + + +class SV(object): + + def __init__(self, size, buff): + self.__size = size + self.__value = unpack(self.__size, buff)[0] + + def _get(self): + return pack(self.__size, self.__value) + + def __str__(self): + return "0x%x" % self.__value + + def __int__(self): + return self.__value + + def get_value_buff(self): + return self._get() + + def get_value(self): + return self.__value + + def set_value(self, attr): + self.__value = attr + + +class SVs(object): + + def __init__(self, size, ntuple, buff): + self.__size = size + + self.__value = ntuple._make(unpack(self.__size, buff)) + + def _get(self): + l = [] + for i in self.__value._fields: + l.append(getattr(self.__value, i)) + return pack(self.__size, *l) + + def _export(self): + return [x for x in self.__value._fields] + + def get_value_buff(self): + return self._get() + + def get_value(self): + return self.__value + + def set_value(self, attr): + self.__value = self.__value._replace(**attr) + + def __str__(self): + return self.__value.__str__() + + +class BuffHandle(object): + + def __init__(self, buff): + self.__buff = buff + self.__idx = 0 + + def size(self): + return len(self.__buff) + + def set_idx(self, idx): + self.__idx = idx + + def get_idx(self): + return self.__idx + + def readNullString(self, size): + data = self.read(size) + return data + + def read_b(self, size): + return self.__buff[self.__idx:self.__idx + size] + + def read_at(self, offset, size): + return self.__buff[offset:offset + size] + + def read(self, size): + if isinstance(size, SV): + size = size.value + + buff = self.__buff[self.__idx:self.__idx + size] + self.__idx += size + + return buff + + def end(self): + return self.__idx == len(self.__buff) + + +class Buff(object): + + def __init__(self, offset, buff): + self.offset = offset + self.buff = buff + + self.size = len(buff) + + +def long2int(l): + if l > 0x7fffffff: + l = (0x7fffffff & l) - 0x80000000 + return l diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/aliyun-libs/FaceLivenessOpen-2.1.6.12.aar b/app/aliyun-libs/FaceLivenessOpen-2.1.6.12.aar new file mode 100644 index 000000000..6ec971869 Binary files /dev/null and b/app/aliyun-libs/FaceLivenessOpen-2.1.6.12.aar differ diff --git a/app/aliyun-libs/NoCaptchaSDK-external-release-5.4.29.aar b/app/aliyun-libs/NoCaptchaSDK-external-release-5.4.29.aar new file mode 100644 index 000000000..df3a0bf5c Binary files /dev/null and b/app/aliyun-libs/NoCaptchaSDK-external-release-5.4.29.aar differ diff --git a/app/aliyun-libs/SecurityBodySDK-external-release-5.4.79.aar b/app/aliyun-libs/SecurityBodySDK-external-release-5.4.79.aar new file mode 100644 index 000000000..91c813903 Binary files /dev/null and b/app/aliyun-libs/SecurityBodySDK-external-release-5.4.79.aar differ diff --git a/app/aliyun-libs/SecurityGuardSDK-external-release-5.4.121.aar b/app/aliyun-libs/SecurityGuardSDK-external-release-5.4.121.aar new file mode 100644 index 000000000..f01e0a8fa Binary files /dev/null and b/app/aliyun-libs/SecurityGuardSDK-external-release-5.4.121.aar differ diff --git a/app/aliyun-libs/aliyun-oss-sdk-android-2.3.0.1.jar b/app/aliyun-libs/aliyun-oss-sdk-android-2.3.0.1.jar new file mode 100644 index 000000000..0662f657b Binary files /dev/null and b/app/aliyun-libs/aliyun-oss-sdk-android-2.3.0.1.jar differ diff --git a/app/aliyun-libs/rpsdk-release-3.0.0.1.aar b/app/aliyun-libs/rpsdk-release-3.0.0.1.aar new file mode 100644 index 000000000..e807dd890 Binary files /dev/null and b/app/aliyun-libs/rpsdk-release-3.0.0.1.aar differ diff --git a/app/aliyun-libs/windvane-min-8.0.3.2.3.jar b/app/aliyun-libs/windvane-min-8.0.3.2.3.jar new file mode 100644 index 000000000..d5ea50d7c Binary files /dev/null and b/app/aliyun-libs/windvane-min-8.0.3.2.3.jar differ diff --git a/app/and_res_guard.gradle b/app/and_res_guard.gradle new file mode 100644 index 000000000..33cd337c3 --- /dev/null +++ b/app/and_res_guard.gradle @@ -0,0 +1,78 @@ +/** + * ************************************* + * android 资源混淆脚本 + *************************************** + */ +apply plugin: 'AndResGuard' + + +andResGuard { + mappingFile = file("./resource_mapping.txt") +// mappingFile = null + // 当你使用v2签名的时候,7zip压缩是无法生效的。 + use7zip = false + useSign = true + // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字 + keepRoot = false + whiteList = [ + // for your icon + "R.mipmap.app_logo", + // for fabric + "R.string.com.crashlytics.*", + //sharesdk + "R.string.ssdk_*", + "R.string.smssdk_*", + "R.layout.ssdk_*", + "R.drawable.ssdk_*", + "R.mipmap.ssdk_*", + "R.anim.ssdk_*", + "R.color.ssdk_*", + "R.style.ssdk_*", + "R.id.ssdk_*", + //ktv + "R.id.sb_accompany_voice", + "R.id.tv_accompany_voice", + "R.id.sb_person_voice", + "R.id.tv_person_voice", + "R.id.tv_change_audio", + "R.id.iv_play_or_pause", + "R.id.cv_people_sound", + "R.id.cv_accompany_sound", + "R.id.layout_song_progress", + // for google-services + "R.string.google_app_id", + "R.string.gcm_defaultSenderId", + "R.string.default_web_client_id", + "R.string.ga_trackingId", + "R.string.firebase_database_url", + "R.string.google_api_key", + "R.string.google_crash_reporting_api_key", + //for aliyun RPSDK + "R.drawable.yw_1222_*", + //for voice match + "R.id.iv_group_like", + "R.id.iv_group_dont_like", + "R.id.fl_group_content", + "R.id.svga_group_voice_like" + ] + compressFilePattern = [ + "*.png", + "*.jpg", + "*.jpeg", + "*.gif", + "resources.arsc" + ] + sevenzip { + artifact = 'com.tencent.mm:SevenZip:1.2.15' + //path = "/usr/local/bin/7za" + } + + // erban-${variant.buildType.name}-${defaultConfig.versionName}_${defaultConfig.versionCode}-${releaseTime()}-${variant.productFlavors[0].name}.apk".toLowerCase()) +// sourceApk = "${project.rootDir}/耳伴-${buildTypes}-${defaultConfig.versionName}_${defaultConfig.versionCode}-${releaseTime()}.apk".toLowerCase() + + /** + * 可选: 指定v1签名时生成jar文件的摘要算法 + * 默认值为“SHA-1” + **/ + // digestalg = "SHA-256" +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 000000000..931080496 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,280 @@ +apply plugin: 'com.android.application' + +// android res guard 资源混淆脚本 +apply from: 'and_res_guard.gradle' + +android { + compileSdkVersion 27 + + defaultConfig { + applicationId "com.wudoo.qingxun" + minSdkVersion 19 + targetSdkVersion 26 + versionCode Integer.valueOf(version_code) + versionName version_name + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + multiDexEnabled true + + ndk { + //设置支持的SO库架构 + if (ndk_abi_filters == "x86") { + abiFilters "x86" + } else if (ndk_abi_filters == "arm_x86") { + abiFilters "armeabi-v7a", "x86" + } else { + abiFilters "armeabi-v7a" + } + } + + flavorDimensions 'default' + } + + lintOptions { + abortOnError false + disable 'MissingTranslation' + disable 'ExtraTranslation' + } + + dexOptions { + javaMaxHeapSize "1g" + jumboMode = true + } + + dataBinding { + enabled = true + } + + packagingOptions { + exclude 'lib/armeabi-v7a/libagora-crypto.so' + } + + signingConfigs { + + v2 { + storeFile file('../qx.jks') + storePassword "123456789" + keyAlias "key_qingxun" + keyPassword "123456789" + v2SigningEnabled true + v1SigningEnabled true + } + + v1 { + storeFile file('../qx.jks') + storePassword "123456789" + keyAlias "key_qingxun" + keyPassword "123456789" + if (sign_mode == "v1v2") { + v2SigningEnabled true + } else { + v2SigningEnabled false + } + v1SigningEnabled true + } + + } + + sourceSets { + + main { + java.srcDirs = [ + 'src/main/java', + 'src/module_public_chat_hall/java', + 'src/module_upgrade_app/java', + 'src/module_mentoring_relationship/java', + 'src/module_labour_union/java', + 'src/module_room_chat/java', + 'src/model_customer_server/java', + 'src/module_music/java', + 'src/module_mini_world/java', + 'src/module_lottery_dialog/java', + 'src/module_bank_card/java', + 'src/module_super_admin/java', + 'src/module_treasure_box/java', + + 'src/module_community/java', + 'src/module_album/java' + + ] + + res.srcDirs = [ + 'src/main/res', + 'src/common/res', + 'src/module_public_chat_hall/res', + 'src/module_upgrade_app/res', + 'src/module_mentoring_relationship/res', + 'src/module_labour_union/res', + 'src/module_room_chat/res', + 'src/model_customer_server/res', + 'src/module_music/res', + 'src/module_mini_world/res', + 'src/module_lottery_dialog/res', + 'src/module_bank_card/res', + 'src/module_super_admin/res', + 'src/module_treasure_box/res', + + 'src/module_community/res', + 'src/module_album/res' + + ] + } + } + + buildTypes { + release { +// buildConfigField "String", "BASE_URL", "\"https://www.erbanyy.com/\"" + buildConfigField "String", "BASE_URL", "\"https://api.qxjiaoyou.com/\"" + buildConfigField "String", "BASE_URL_DEBUG", "BASE_URL" + buildConfigField "String", "BASE_URL_STAGING", "BASE_URL" + buildConfigField "String", "BASE_URL_RELEASE", "BASE_URL" + minifyEnabled true + shrinkResources true + signingConfig signingConfigs.v2 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + + staging { + buildConfigField "String", "BASE_URL", "\"https://preview.qxjiaoyou.com/\"" + buildConfigField "String", "BASE_URL_DEBUG", "BASE_URL" + buildConfigField "String", "BASE_URL_STAGING", "BASE_URL" + buildConfigField "String", "BASE_URL_RELEASE", "BASE_URL" + minifyEnabled true + shrinkResources true + signingConfig signingConfigs.v2 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + matchingFallbacks = ['staging', 'release'] + } + + debug { +// buildConfigField "String", "BASE_URL", "\"https://115.28.86.139/\"" + buildConfigField "String", "BASE_URL", "\"http://apibeta.qxjiaoyou.com/\"" + buildConfigField "String", "BASE_URL_DEBUG", "BASE_URL" + buildConfigField "String", "BASE_URL_STAGING", "\"https://preview.qxjiaoyou.com/\"" + buildConfigField "String", "BASE_URL_RELEASE", "\"https://api.qxjiaoyou.com/\"" + + minifyEnabled false + shrinkResources false + signingConfig signingConfigs.v1 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + productFlavors { + qingxun { + dimension 'default' + } + + } + +} + +def supportLibraryVersion = "27.1.1" +def Lombok = "1.16.20" + +dependencies { + api fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + + api "com.android.support:recyclerview-v7:${supportLibraryVersion}" + api "com.android.support:cardview-v7:${supportLibraryVersion}" + api "com.android.support:gridlayout-v7:${supportLibraryVersion}" + api "com.android.support:multidex:1.0.3" + + debugApi "com.squareup.leakcanary:leakcanary-android:1.6.3" + releaseApi "com.squareup.leakcanary:leakcanary-android-no-op:1.6.3" + stagingApi "com.squareup.leakcanary:leakcanary-android-no-op:1.6.3" + + api "com.orhanobut:dialogplus:1.11@aar" + + api "com.readystatesoftware.systembartint:systembartint:1.0.4" + api "com.rengwuxian.materialedittext:library:2.1.4" + api "com.github.flavienlaurent.datetimepicker:library:0.0.2" + + api "com.darsh.multipleimageselect:multipleimageselect:1.0.4" + api "me.shaohui.advancedluban:library:1.3.2" + api "com.tencent.bugly:crashreport:2.8.6" + api "pl.droidsonroids.gif:android-gif-drawable:1.2.7" +// api "com.jude:rollviewpager:1.4.6" + implementation 'com.github.dongxingrong:RollViewPager:V1.0' + api "com.makeramen:roundedimageview:2.3.0" + api "com.jzxiang.pickerview:TimePickerDialog:1.0.1" + api "com.github.zyyoona7:EasyPopup:1.0.2" + api "com.github.donkingliang:LabelsView:1.2.0" + api "com.github.yyued:SVGAPlayer-Android:2.4.2" + api "com.mcxiaoke.packer-ng:helper:2.0.0" + implementation "com.orhanobut:logger:2.1.1" + api "com.ms-square:expandableTextView:0.1.4" + api "com.jakewharton:butterknife:8.8.1" + annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1" + implementation "com.llew.huawei:verifier:1.0.3" + + api "com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar" + api "com.nex3z:flow-layout:1.2.2" + + api project(':core') + + implementation 'com.github.qiujayen:sticky-layoutmanager:1.0.1' + + implementation 'com.github.chenBingX:SuperTextView:v3.0.0' + + //支付密码输入框 + api 'com.jungly:gridPasswordView:0.3' + api 'com.google.android:flexbox:1.0.0' + + compileOnly "org.projectlombok:lombok:${Lombok}" + annotationProcessor "org.projectlombok:lombok:${Lombok}" + api "android.arch.lifecycle:extensions:1.1.1" + implementation 'nl.dionsegijn:konfetti:1.1.2' + + // 华为推送 + api(name: 'base-2.6.0.301', ext: 'aar') + api(name: 'push-2.6.0.301', ext: 'aar') + // 魅族推送 + implementation 'com.meizu.flyme.internet:push-internal:3.6.3@aar' + +// api 'com.aliyun.dpa:oss-android-sdk:2.2.0' + api files('aliyun-libs/aliyun-oss-sdk-android-2.3.0.1.jar') + api files('aliyun-libs/windvane-min-8.0.3.2.3.jar') +// api files('aliyun-libs/okhttp-3.12.0.jar') +// api files('aliyun-libs/okio-1.16.0.jar') + api(name: 'FaceLivenessOpen-2.1.6.12', ext: 'aar') + api(name: 'rpsdk-release-3.0.0.1', ext: 'aar') + api(name: 'SecurityGuardSDK-external-release-5.4.121', ext: 'aar') + api(name: 'SecurityBodySDK-external-release-5.4.79', ext: 'aar') + api(name: 'NoCaptchaSDK-external-release-5.4.29', ext: 'aar') + //数字滚动效果 + implementation 'com.github.YvesCheung:RollingText:1.2.3' + // 引入原有第三方裁图源码,方便修改 + api project(':android_crop_lib') + //网易七鱼客服 + implementation 'com.qiyukf.unicorn:unicorn:4.9.1' + + //rx权限请求框架 + implementation('com.github.tbruyelle:rxpermissions:0.10.2') { + exclude group: 'io.reactivex.rxjava2' + } + //验证码控件 https://github.com/JingYeoh/VercodeEditText + implementation 'com.justkiddingbaby:vercodeedittext:1.1.0' + + //高德地图 + implementation 'com.amap.api:location:3.3.0' + + implementation 'it.sephiroth.android.library.imagezoom:library:1.0.4' + +} + +repositories { + flatDir { + dirs 'aliyun-libs', 'hw-push-libs' + } +} diff --git a/app/hw-push-libs/base-2.6.0.301-sources.jar b/app/hw-push-libs/base-2.6.0.301-sources.jar new file mode 100644 index 000000000..9126e5509 Binary files /dev/null and b/app/hw-push-libs/base-2.6.0.301-sources.jar differ diff --git a/app/hw-push-libs/base-2.6.0.301.aar b/app/hw-push-libs/base-2.6.0.301.aar new file mode 100644 index 000000000..ea3c7e207 Binary files /dev/null and b/app/hw-push-libs/base-2.6.0.301.aar differ diff --git a/app/hw-push-libs/push-2.6.0.301-sources.jar b/app/hw-push-libs/push-2.6.0.301-sources.jar new file mode 100644 index 000000000..b2024d8c0 Binary files /dev/null and b/app/hw-push-libs/push-2.6.0.301-sources.jar differ diff --git a/app/hw-push-libs/push-2.6.0.301.aar b/app/hw-push-libs/push-2.6.0.301.aar new file mode 100644 index 000000000..d2e7467be Binary files /dev/null and b/app/hw-push-libs/push-2.6.0.301.aar differ diff --git a/app/libs/MiPush_SDK_Client_3_6_2.jar b/app/libs/MiPush_SDK_Client_3_6_2.jar new file mode 100644 index 000000000..220b9baf1 Binary files /dev/null and b/app/libs/MiPush_SDK_Client_3_6_2.jar differ diff --git a/app/libs/nanohttpd-2.2.0.jar b/app/libs/nanohttpd-2.2.0.jar new file mode 100644 index 000000000..1f1e82cd9 Binary files /dev/null and b/app/libs/nanohttpd-2.2.0.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..42b4c27d4 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,306 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +# 保留行号 +-keepattributes SourceFile,LineNumberTable + +#-dontwarn #//dontwarn去掉警告 +#-dontskipnonpubliclibraryclassmembers +#-keep public class * extends android.app.Fragment +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +#-keep public class * extends android.preference.Preference +#-keep public class * extends android.support.v4.** +-keep public class com.android.vending.licensing.ILicensingService +-keepclasseswithmembernames class * { + native ; +} +#-keepclasseswithmembernames class * { +# public (android.content.Context, android.util.AttributeSet); +#} +#-keepclasseswithmembernames class * { +# public (android.content.Context, android.util.AttributeSet, int); +#} +#----------------enum----------------- +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} +#----------------Parcelable----------------- +-keepclassmembers class * implements android.os.Parcelable { + static ** CREATOR; + ; + ; +} +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; +} + +-keep class * implements java.io.Serializable { + *; +} +##---------------Begin: proguard configuration for Gson ---------- +# Gson specific classes +-dontwarn sun.misc.** + +-keep class com.google.gson.**{*;} + +#-keep class com.google.gson.stream.** { *; } + +# Application classes that will be serialized/deserialized over Gson +-keep class com.google.gson.examples.android.model.** { *; } + +# Prevent proguard from stripping interface information from TypeAdapterFactory, +# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer + +-keepattributes Signature +-keepattributes *Annotation* + +#----------------android----------------- +-dontwarn android.** +-keep class android.** { *;} +#----------------v4----------------- +-dontwarn android.support.v4.** +-keep class android.support.v4.** { *; } +#----------------v7----------------- +-dontwarn android.support.v7.** +-keep class android.support.v7.** { *;} + +#----------------EventBus事件巴士----------------- +-keepclassmembers class ** { + @org.greenrobot.eventbus.Subscribe ; +} +-keep enum org.greenrobot.eventbus.ThreadMode { *; } + +# Only required if you use AsyncExecutor +-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent { + (Java.lang.Throwable); +} + + +#-------------云信相关的混淆配置------------ +-dontwarn com.netease.** +-keep class com.netease.** {*;} + +# Presenter 相关 +-keep class com.yizhuan.erban.base.** { *; } +-keep public class * extends com.yizhuan.erban.base.BaseMvpPresenter +-keep public class * extends com.yizhuan.xchat_android_library.base.AbstractMvpPresenter + +# 云信自定义 ViewHolder 配置 +-dontwarn com.yizhuan.erban.ui.im.recent.holder.** +-keep class com.yizhuan.erban.ui.im.recent.holder.** {*;} +-keep class com.yizhuan.erban.ui.im.chat.** {*;} +-keep class com.yizhuan.erban.luckymoney.viewholder.** {*;} +-keep class com.yizhuan.erban.share.viewholder.** {*;} +-keep class com.yizhuan.erban.public_chat_hall.msg.viewholder.** {*;} +-keep class com.yizhuan.erban.module_hall.im.msgholder.** {*;} +-keep class com.yizhuan.tutu.mentoring_relationship.viewholder.** {*;} +-keep public class * extends com.netease.nim.uikit.common.ui.recyclerview.holder.RecyclerViewHolder {*;} +-keep public class * extends com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase {*;} + +#如果你使用全文检索插件,需要加入 +-dontwarn org.apache.lucene.** +-keep class org.apache.lucene.** {*;} + +# 云信集成小米推送 +-dontwarn com.xiaomi.push.** +-keep class com.xiaomi.** {*;} + +# 云信集成华为推送 +-ignorewarning +-keepattributes *Annotation* +-keepattributes Exceptions +-keepattributes Signature +# hmscore-support: remote transport +-keep class * extends com.huawei.hms.core.aidl.IMessageEntity { *; } +# hmscore-support: remote transport +-keepclasseswithmembers class * implements com.huawei.hms.support.api.transport.DatagramTransport { +(...); } +# manifest: provider for updates +-keep public class com.huawei.hms.update.provider.UpdateProvider { public *; protected *; } + +# 云信集成魅族推送 +-dontwarn com.meizu.cloud.** +-keep class com.meizu.cloud.** {*;} +#-------------云信相关的混淆配置------------ + + +#-------------TakePhoto的混淆配置------------ +-keep class com.jph.takephoto.** { *; } +-dontwarn com.jph.takephoto.** + +-keep class com.darsh.multipleimageselect.** { *; } +-dontwarn com.darsh.multipleimageselect.** + +-keep class com.soundcloud.android.crop.** { *; } +-dontwarn com.soundcloud.android.crop.** + +#-------------TakePhoto的混淆配置------------ + + + +#腾讯崩溃收集 +-dontwarn com.tencent.bugly.** +-keep public class com.tencent.bugly.**{*;} + +# glide4.0 +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { + **[] $VALUES; + public *; +} +# for DexGuard only +#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule + +# BaseAdapter +-keep class com.chad.library.adapter.** { +*; +} +-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter +-keep public class * extends com.chad.library.adapter.base.BaseViewHolder +-keepclassmembers class **$** extends com.chad.library.adapter.base.BaseViewHolder { + (...); +} + +-dontwarn com.yizhuan.erban.bindadapter.** +-keep class com.yizhuan.erban.bindadapter.** {*;} + +# Ping++ 混淆过滤 +-dontwarn com.pingplusplus.** +-keep class com.pingplusplus.** {*;} +# 支付宝混淆过滤 +-dontwarn com.alipay.** +-keep class com.alipay.** {*;} +# 微信或QQ钱包混淆过滤 +-dontwarn com.tencent.** +-keep class com.tencent.** {*;} + +# 银联支付混淆过滤 +#-dontwarn com.unionpay.** +#-keep class com.unionpay.** {*;} +# +## 招行一网通混淆过滤 +#-keepclasseswithmembers class cmb.pb.util.CMBKeyboardFunc { +# public (android.app.Activity); +# public boolean HandleUrlCall(android.webkit.WebView,java.lang.String); +# public void callKeyBoardActivity(); +#} + +# 内部WebView混淆过滤 +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} + + +# TODO 网络加载 一些业务bean gson 时候混淆问题 +-keep class org.json.** {*;} +-dontwarn com.yizhuan.xchat_android_core.** +-keep class com.yizhuan.xchat_android_core.** {*;} + + +#百度统计 +-keep class com.baidu.bottom.** { *; } +-keep class com.baidu.kirin.** { *; } +-keep class com.baidu.mobstat.** { *; } + +-keep class io.agora.** { *; } + +# 七牛 +-keep class com.qiniu.**{*;} +-keep class com.qiniu.**{public ();} +-ignorewarnings + +# shareSdk +-keep class cn.sharesdk.**{*;} +-keep class com.sina.**{*;} +-keep class **.R$* {*;} +-keep class **.R{*;} +-keep class com.mob.**{*;} +-dontwarn com.mob.** +-dontwarn cn.sharesdk.** +-dontwarn **.R$* + +# fastjson +-dontwarn com.alibaba.fastjson.** +-keep class com.alibaba.fastjson.**{*; } + +# retrofit2 +# Platform calls Class.forName on types which do not checkExist on Android to determine platform. +-dontnote retrofit2.Platform +# Platform used when running on Java 8 VMs. Will not be used at runtime. +-dontwarn retrofit2.Platform$Java8 +# Retain declared checked exceptions for use by a Proxy instance. +-keepattributes Exceptions + +# okhttp3 +-dontwarn okhttp3.** +# okio +-dontwarn okio.** +# A resource is loaded with a relative path so the package of this class must be preserved. +-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase + +# Aliyun oss +-keep class com.taobao.securityjni.**{*;} +-keep class com.taobao.wireless.security.**{*;} +-keep class com.ut.secbody.**{*;} +-keep class com.taobao.dp.**{*;} +-keep class com.alibaba.wireless.security.**{*;} +-keep class com.alibaba.security.rp.**{*;} +-keep class com.alibaba.sdk.android.**{*;} +-keep class com.alibaba.security.biometrics.**{*;} +-keep class android.taobao.windvane.**{*;} + + +#网易七鱼客服系统 +-dontwarn com.qiyukf.** +-keep class com.qiyukf.** {*;} + +# 确保openFileChooser方法不被混淆 +-keepclassmembers class * extends android.webkit.WebChromeClient{ + public void openFileChooser(...); + } + +#高德地图 +-keep class com.amap.api.location.**{*;} +-keep class com.amap.api.fence.**{*;} +-keep class com.autonavi.aps.amapapi.model.**{*;} + +#暂时keep这个View排查华为oom问题 +-keep class com.yizhuan.erban.avroom.widget.MicroView{*;} +-keep class com.jude.rollviewpager.RollPagerView{*;} + +#linkedMe +-keep class com.microquation.linkedme.android.** { *; } diff --git a/app/resource_mapping.txt b/app/resource_mapping.txt new file mode 100644 index 000000000..ded759141 --- /dev/null +++ b/app/resource_mapping.txt @@ -0,0 +1,2 @@ +res path mapping: + res/drawable -> res/drawable diff --git a/app/src/androidTest/java/com/yizhuan/erban/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/yizhuan/erban/ExampleInstrumentedTest.java new file mode 100644 index 000000000..df6b2eac5 --- /dev/null +++ b/app/src/androidTest/java/com/yizhuan/erban/ExampleInstrumentedTest.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.yizhuan.erban_android_client", appContext.getPackageName()); + } + +} diff --git a/app/src/common/res/drawable/bg_f5f5f5_0_15.xml b/app/src/common/res/drawable/bg_f5f5f5_0_15.xml new file mode 100644 index 000000000..e42042887 --- /dev/null +++ b/app/src/common/res/drawable/bg_f5f5f5_0_15.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_btn_highlight_click.xml b/app/src/common/res/drawable/selector_btn_highlight_click.xml new file mode 100644 index 000000000..e4bdb7589 --- /dev/null +++ b/app/src/common/res/drawable/selector_btn_highlight_click.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_check_box_pic_check.xml b/app/src/common/res/drawable/selector_check_box_pic_check.xml new file mode 100644 index 000000000..ce5cf1b17 --- /dev/null +++ b/app/src/common/res/drawable/selector_check_box_pic_check.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_check_box_pic_check_white.xml b/app/src/common/res/drawable/selector_check_box_pic_check_white.xml new file mode 100644 index 000000000..a664f4ea3 --- /dev/null +++ b/app/src/common/res/drawable/selector_check_box_pic_check_white.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_check_box_pic_select.xml b/app/src/common/res/drawable/selector_check_box_pic_select.xml new file mode 100644 index 000000000..97d5319f8 --- /dev/null +++ b/app/src/common/res/drawable/selector_check_box_pic_select.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_common_gray_appcolor_corner.xml b/app/src/common/res/drawable/selector_common_gray_appcolor_corner.xml new file mode 100644 index 000000000..f675f3cdc --- /dev/null +++ b/app/src/common/res/drawable/selector_common_gray_appcolor_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_radio_btn.xml b/app/src/common/res/drawable/selector_radio_btn.xml new file mode 100644 index 000000000..cea3a634b --- /dev/null +++ b/app/src/common/res/drawable/selector_radio_btn.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_select_all_btn.xml b/app/src/common/res/drawable/selector_select_all_btn.xml new file mode 100644 index 000000000..75388e5b0 --- /dev/null +++ b/app/src/common/res/drawable/selector_select_all_btn.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/selector_select_mark.xml b/app/src/common/res/drawable/selector_select_mark.xml new file mode 100644 index 000000000..e27fa7faa --- /dev/null +++ b/app/src/common/res/drawable/selector_select_mark.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_btn_highlight_gradient.xml b/app/src/common/res/drawable/shape_btn_highlight_gradient.xml new file mode 100644 index 000000000..1e541fd1e --- /dev/null +++ b/app/src/common/res/drawable/shape_btn_highlight_gradient.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_common_enable.xml b/app/src/common/res/drawable/shape_common_enable.xml new file mode 100644 index 000000000..8cb7dc354 --- /dev/null +++ b/app/src/common/res/drawable/shape_common_enable.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_common_unable.xml b/app/src/common/res/drawable/shape_common_unable.xml new file mode 100644 index 000000000..28248a99c --- /dev/null +++ b/app/src/common/res/drawable/shape_common_unable.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_corner_white_tran_80.xml b/app/src/common/res/drawable/shape_corner_white_tran_80.xml new file mode 100644 index 000000000..c75bd6e74 --- /dev/null +++ b/app/src/common/res/drawable/shape_corner_white_tran_80.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_edit_cursor.xml b/app/src/common/res/drawable/shape_edit_cursor.xml new file mode 100644 index 000000000..78d3d4d9e --- /dev/null +++ b/app/src/common/res/drawable/shape_edit_cursor.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_female_corner.xml b/app/src/common/res/drawable/shape_female_corner.xml new file mode 100644 index 000000000..fc0de0810 --- /dev/null +++ b/app/src/common/res/drawable/shape_female_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_gray_corner_12.xml b/app/src/common/res/drawable/shape_gray_corner_12.xml new file mode 100644 index 000000000..147878e32 --- /dev/null +++ b/app/src/common/res/drawable/shape_gray_corner_12.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_male_corner.xml b/app/src/common/res/drawable/shape_male_corner.xml new file mode 100644 index 000000000..c69d21b34 --- /dev/null +++ b/app/src/common/res/drawable/shape_male_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_43c5ff_radius_22dp.xml b/app/src/common/res/drawable/shape_round_43c5ff_radius_22dp.xml new file mode 100644 index 000000000..0b606ff61 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_43c5ff_radius_22dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_9af5ef_radius_5dp.xml b/app/src/common/res/drawable/shape_round_9af5ef_radius_5dp.xml new file mode 100644 index 000000000..72f66fb53 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_9af5ef_radius_5dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_app_color_radius_19dp.xml b/app/src/common/res/drawable/shape_round_app_color_radius_19dp.xml new file mode 100644 index 000000000..3c9d42112 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_app_color_radius_19dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_app_color_radius_22dp.xml b/app/src/common/res/drawable/shape_round_app_color_radius_22dp.xml new file mode 100644 index 000000000..e3f9d25f1 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_app_color_radius_22dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_app_color_radius_5dp.xml b/app/src/common/res/drawable/shape_round_app_color_radius_5dp.xml new file mode 100644 index 000000000..18c94175f --- /dev/null +++ b/app/src/common/res/drawable/shape_round_app_color_radius_5dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_app_color_solid.xml b/app/src/common/res/drawable/shape_round_app_color_solid.xml new file mode 100644 index 000000000..208e72571 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_app_color_solid.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_color_ff9976_radius_5dp_padding_13dp.xml b/app/src/common/res/drawable/shape_round_color_ff9976_radius_5dp_padding_13dp.xml new file mode 100644 index 000000000..f8e2dc8b4 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_color_ff9976_radius_5dp_padding_13dp.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_ececec_radius_6dp.xml b/app/src/common/res/drawable/shape_round_ececec_radius_6dp.xml new file mode 100644 index 000000000..62721c0fd --- /dev/null +++ b/app/src/common/res/drawable/shape_round_ececec_radius_6dp.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_f0f0f0_radius_22dp.xml b/app/src/common/res/drawable/shape_round_f0f0f0_radius_22dp.xml new file mode 100644 index 000000000..2f61f4536 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_f0f0f0_radius_22dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_f5f5f5_radius_5dp.xml b/app/src/common/res/drawable/shape_round_f5f5f5_radius_5dp.xml new file mode 100644 index 000000000..09b5cd194 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_f5f5f5_radius_5dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_ff5a79_radius_22dp.xml b/app/src/common/res/drawable/shape_round_ff5a79_radius_22dp.xml new file mode 100644 index 000000000..55eb2ada8 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_ff5a79_radius_22dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_ff894f_radius_19.xml b/app/src/common/res/drawable/shape_round_ff894f_radius_19.xml new file mode 100644 index 000000000..1d028a044 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_ff894f_radius_19.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_ffc4ab_radius_5dp.xml b/app/src/common/res/drawable/shape_round_ffc4ab_radius_5dp.xml new file mode 100644 index 000000000..e8a7c66fe --- /dev/null +++ b/app/src/common/res/drawable/shape_round_ffc4ab_radius_5dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_ffdbdbdb_radius_19.xml b/app/src/common/res/drawable/shape_round_ffdbdbdb_radius_19.xml new file mode 100644 index 000000000..9c2f69f63 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_ffdbdbdb_radius_19.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_gray_solid.xml b/app/src/common/res/drawable/shape_round_gray_solid.xml new file mode 100644 index 000000000..a13022500 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_gray_solid.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_qq_login.xml b/app/src/common/res/drawable/shape_round_qq_login.xml new file mode 100644 index 000000000..7734a511c --- /dev/null +++ b/app/src/common/res/drawable/shape_round_qq_login.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_white_5dp.xml b/app/src/common/res/drawable/shape_round_white_5dp.xml new file mode 100644 index 000000000..14a29c6a4 --- /dev/null +++ b/app/src/common/res/drawable/shape_round_white_5dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_white_5dp_padding_13dp.xml b/app/src/common/res/drawable/shape_round_white_5dp_padding_13dp.xml new file mode 100644 index 000000000..29857034d --- /dev/null +++ b/app/src/common/res/drawable/shape_round_white_5dp_padding_13dp.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_white_radius_19dp_transparent_16.xml b/app/src/common/res/drawable/shape_round_white_radius_19dp_transparent_16.xml new file mode 100644 index 000000000..1210b2f8e --- /dev/null +++ b/app/src/common/res/drawable/shape_round_white_radius_19dp_transparent_16.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_round_white_radius_9dp.xml b/app/src/common/res/drawable/shape_round_white_radius_9dp.xml new file mode 100644 index 000000000..a5ae83bcb --- /dev/null +++ b/app/src/common/res/drawable/shape_round_white_radius_9dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_withdraw_item_selected.xml b/app/src/common/res/drawable/shape_withdraw_item_selected.xml new file mode 100644 index 000000000..b368e1025 --- /dev/null +++ b/app/src/common/res/drawable/shape_withdraw_item_selected.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/drawable/shape_withdraw_item_unselect.xml b/app/src/common/res/drawable/shape_withdraw_item_unselect.xml new file mode 100644 index 000000000..5c20242ee --- /dev/null +++ b/app/src/common/res/drawable/shape_withdraw_item_unselect.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_add.png b/app/src/common/res/mipmap-xhdpi/common_ic_add.png new file mode 100644 index 000000000..af614977c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_add.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_add_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_add_white.png new file mode 100644 index 000000000..b7af6a417 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_add_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_attention.png b/app/src/common/res/mipmap-xhdpi/common_ic_attention.png new file mode 100644 index 000000000..cd4815ffa Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_attention.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_attention_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_attention_grey.png new file mode 100644 index 000000000..4cb39b626 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_attention_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_back.png b/app/src/common/res/mipmap-xhdpi/common_ic_back.png new file mode 100644 index 000000000..4243a4f35 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_back.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_back_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_back_white.png new file mode 100644 index 000000000..de9ed7eef Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_back_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_black_list.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_black_list.png new file mode 100644 index 000000000..d62e4d913 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_black_list.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_decoration.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_decoration.png new file mode 100644 index 000000000..1c35b30d9 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_decoration.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_gift.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_gift.png new file mode 100644 index 000000000..12df56e82 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_gift.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_gift_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_gift_grey.png new file mode 100644 index 000000000..703361e96 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_gift_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room.png new file mode 100644 index 000000000..4d63f82fc Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room_grey.png new file mode 100644 index 000000000..519f96d3d Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_kick_out_room_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_magic.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_magic.png new file mode 100644 index 000000000..a2809b31d Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_magic.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_card_manager.png b/app/src/common/res/mipmap-xhdpi/common_ic_card_manager.png new file mode 100644 index 000000000..5cb161e58 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_card_manager.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_charge.png b/app/src/common/res/mipmap-xhdpi/common_ic_charge.png new file mode 100644 index 000000000..4963b61a3 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_charge.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_checked.webp b/app/src/common/res/mipmap-xhdpi/common_ic_checked.webp new file mode 100644 index 000000000..184036791 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_checked.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_checked_white.webp b/app/src/common/res/mipmap-xhdpi/common_ic_checked_white.webp new file mode 100644 index 000000000..4173fc9eb Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_checked_white.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_black.webp b/app/src/common/res/mipmap-xhdpi/common_ic_close_black.webp new file mode 100644 index 000000000..4a03ce0ef Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_black.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_close_grey.png new file mode 100644 index 000000000..b1d522a1a Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen.png b/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen.png new file mode 100644 index 000000000..88013936d Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen_white.png new file mode 100644 index 000000000..f496f6136 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_public_screen_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_red.png b/app/src/common/res/mipmap-xhdpi/common_ic_close_red.png new file mode 100644 index 000000000..214d96dc7 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_red.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_close_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_close_white.png new file mode 100644 index 000000000..e9221e158 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_close_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_create_family.png b/app/src/common/res/mipmap-xhdpi/common_ic_create_family.png new file mode 100644 index 000000000..8ae516a47 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_create_family.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_customer_service.png b/app/src/common/res/mipmap-xhdpi/common_ic_customer_service.png new file mode 100644 index 000000000..ff37dcdb0 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_customer_service.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_decoration_store.png b/app/src/common/res/mipmap-xhdpi/common_ic_decoration_store.png new file mode 100644 index 000000000..e0cf34998 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_decoration_store.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_delete.png b/app/src/common/res/mipmap-xhdpi/common_ic_delete.png new file mode 100644 index 000000000..bab1646cf Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_delete.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_delete_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_delete_white.png new file mode 100644 index 000000000..49ca0939c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_delete_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_discover.png b/app/src/common/res/mipmap-xhdpi/common_ic_discover.png new file mode 100644 index 000000000..cd4815ffa Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_discover.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_discover_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_discover_white.png new file mode 100644 index 000000000..8f6d7858a Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_discover_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_edit.png b/app/src/common/res/mipmap-xhdpi/common_ic_edit.png new file mode 100644 index 000000000..e6341e4a9 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_edit.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_edit_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_edit_white.png new file mode 100644 index 000000000..f1c4453d5 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_edit_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_exit_family.png b/app/src/common/res/mipmap-xhdpi/common_ic_exit_family.png new file mode 100644 index 000000000..6aaecf1b4 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_exit_family.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_face_wall.png b/app/src/common/res/mipmap-xhdpi/common_ic_face_wall.png new file mode 100644 index 000000000..a68bb649c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_face_wall.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_family_guide.png b/app/src/common/res/mipmap-xhdpi/common_ic_family_guide.png new file mode 100644 index 000000000..e4853fc45 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_family_guide.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_family_square.png b/app/src/common/res/mipmap-xhdpi/common_ic_family_square.png new file mode 100644 index 000000000..7077fe5d1 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_family_square.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_gift_black.png b/app/src/common/res/mipmap-xhdpi/common_ic_gift_black.png new file mode 100644 index 000000000..643f26843 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_gift_black.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_gift_effect.png b/app/src/common/res/mipmap-xhdpi/common_ic_gift_effect.png new file mode 100644 index 000000000..1cfb7f665 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_gift_effect.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_gift_limit.png b/app/src/common/res/mipmap-xhdpi/common_ic_gift_limit.png new file mode 100644 index 000000000..81d6b5e08 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_gift_limit.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_gift_new.png b/app/src/common/res/mipmap-xhdpi/common_ic_gift_new.png new file mode 100644 index 000000000..b03d5cfdc Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_gift_new.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_gift_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_gift_white.png new file mode 100644 index 000000000..e4853fc45 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_gift_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_help.webp b/app/src/common/res/mipmap-xhdpi/common_ic_help.webp new file mode 100644 index 000000000..9f142b560 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_help.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_help_small.png b/app/src/common/res/mipmap-xhdpi/common_ic_help_small.png new file mode 100644 index 000000000..4cbbfae68 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_help_small.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_help_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_help_white.png new file mode 100644 index 000000000..ad39d123f Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_help_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_home_page.png b/app/src/common/res/mipmap-xhdpi/common_ic_home_page.png new file mode 100644 index 000000000..c2741803b Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_home_page.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_home_page_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_home_page_white.png new file mode 100644 index 000000000..164c60133 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_home_page_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_invite_friends.png b/app/src/common/res/mipmap-xhdpi/common_ic_invite_friends.png new file mode 100644 index 000000000..71e19c6f8 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_invite_friends.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_manager.png b/app/src/common/res/mipmap-xhdpi/common_ic_manager.png new file mode 100644 index 000000000..b070ca070 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_manager.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_manager_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_manager_grey.png new file mode 100644 index 000000000..28f7ad1ad Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_manager_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_manager_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_manager_white.png new file mode 100644 index 000000000..f6bbb6d2e Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_manager_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_me.png b/app/src/common/res/mipmap-xhdpi/common_ic_me.png new file mode 100644 index 000000000..c845f4b65 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_me.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_me_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_me_white.png new file mode 100644 index 000000000..3be8a7689 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_me_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_moments.png b/app/src/common/res/mipmap-xhdpi/common_ic_moments.png new file mode 100644 index 000000000..839dcb619 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_moments.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_moments_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_moments_grey.png new file mode 100644 index 000000000..3415c78cb Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_moments_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_more.png b/app/src/common/res/mipmap-xhdpi/common_ic_more.png new file mode 100644 index 000000000..b6bca803d Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_more.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_more_arrow.png b/app/src/common/res/mipmap-xhdpi/common_ic_more_arrow.png new file mode 100644 index 000000000..56b5c5858 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_more_arrow.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_more_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_more_white.png new file mode 100644 index 000000000..57b025a8e Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_more_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_msg.png b/app/src/common/res/mipmap-xhdpi/common_ic_msg.png new file mode 100644 index 000000000..87538b7bf Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_msg.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_msg_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_msg_white.png new file mode 100644 index 000000000..baf2633d5 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_msg_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_my_family.png b/app/src/common/res/mipmap-xhdpi/common_ic_my_family.png new file mode 100644 index 000000000..ba480ccc1 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_my_family.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_my_income.png b/app/src/common/res/mipmap-xhdpi/common_ic_my_income.png new file mode 100644 index 000000000..38cd94502 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_my_income.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_narrow.png b/app/src/common/res/mipmap-xhdpi/common_ic_narrow.png new file mode 100644 index 000000000..25f5690c4 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_narrow.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_narrow_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_narrow_white.png new file mode 100644 index 000000000..4c559e38c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_narrow_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_noble_privilege.png b/app/src/common/res/mipmap-xhdpi/common_ic_noble_privilege.png new file mode 100644 index 000000000..71e5fb91e Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_noble_privilege.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_open_room.png b/app/src/common/res/mipmap-xhdpi/common_ic_open_room.png new file mode 100644 index 000000000..94601e1b3 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_open_room.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_open_room_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_open_room_white.png new file mode 100644 index 000000000..076c2adc9 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_open_room_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_qq.png b/app/src/common/res/mipmap-xhdpi/common_ic_qq.png new file mode 100644 index 000000000..265675ac0 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_qq.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_qq_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_qq_grey.png new file mode 100644 index 000000000..752d96711 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_qq_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone.png b/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone.png new file mode 100644 index 000000000..09a8b50c8 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone_grey.png new file mode 100644 index 000000000..21145069c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_qq_zone_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_refresh.png b/app/src/common/res/mipmap-xhdpi/common_ic_refresh.png new file mode 100644 index 000000000..8fafec444 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_refresh.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_refresh_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_refresh_white.png new file mode 100644 index 000000000..f0a0b6be0 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_refresh_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_related_to_me.png b/app/src/common/res/mipmap-xhdpi/common_ic_related_to_me.png new file mode 100644 index 000000000..aa95f0d5b Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_related_to_me.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_face.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_face.png new file mode 100644 index 000000000..2b97e9384 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_face.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_gift.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_gift.png new file mode 100644 index 000000000..c9e3cddc6 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_gift.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_off.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_off.png new file mode 100644 index 000000000..d9af119c7 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_off.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_on.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_on.png new file mode 100644 index 000000000..f75b7828b Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_mic_on.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_more.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_more.png new file mode 100644 index 000000000..bbc5072bc Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_more.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_msg.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_msg.png new file mode 100644 index 000000000..7aead4d55 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_msg.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add.png new file mode 100644 index 000000000..1eaa4a515 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add_white.png new file mode 100644 index 000000000..c1658a3b1 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_add_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment.png new file mode 100644 index 000000000..7fb4a9cb4 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment_white.png new file mode 100644 index 000000000..f4c491fed Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_music_adjustment_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_off.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_off.png new file mode 100644 index 000000000..9fb447631 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_off.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_on.png b/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_on.png new file mode 100644 index 000000000..66dae1b13 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_room_speaker_on.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_search.png b/app/src/common/res/mipmap-xhdpi/common_ic_search.png new file mode 100644 index 000000000..f4bfcfe44 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_search.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_search_black.png b/app/src/common/res/mipmap-xhdpi/common_ic_search_black.png new file mode 100644 index 000000000..fe00e1358 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_search_black.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_search_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_search_white.png new file mode 100644 index 000000000..1003c13ac Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_search_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_selected.webp b/app/src/common/res/mipmap-xhdpi/common_ic_selected.webp new file mode 100644 index 000000000..afbfd7aff Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_selected.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_setting.png b/app/src/common/res/mipmap-xhdpi/common_ic_setting.png new file mode 100644 index 000000000..42fd88fc0 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_setting.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_setting_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_setting_grey.png new file mode 100644 index 000000000..3c32a922c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_setting_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_setting_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_setting_white.png new file mode 100644 index 000000000..8f43233d3 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_setting_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_share.png b/app/src/common/res/mipmap-xhdpi/common_ic_share.png new file mode 100644 index 000000000..166866772 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_share.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_share_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_share_white.png new file mode 100644 index 000000000..58854ffd5 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_share_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_switch_close.png b/app/src/common/res/mipmap-xhdpi/common_ic_switch_close.png new file mode 100644 index 000000000..e1b146853 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_switch_close.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_switch_open.png b/app/src/common/res/mipmap-xhdpi/common_ic_switch_open.png new file mode 100644 index 000000000..83e24f77c Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_switch_open.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_team.png b/app/src/common/res/mipmap-xhdpi/common_ic_team.png new file mode 100644 index 000000000..c1d6c7b1a Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_team.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_team_white.png b/app/src/common/res/mipmap-xhdpi/common_ic_team_white.png new file mode 100644 index 000000000..bece01a7f Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_team_white.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends.png b/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends.png new file mode 100644 index 000000000..03362a38e Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends_grey.png new file mode 100644 index 000000000..7796d8696 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_tutu_friends_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_unchecked.webp b/app/src/common/res/mipmap-xhdpi/common_ic_unchecked.webp new file mode 100644 index 000000000..523681bc2 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_unchecked.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_unchecked_white.webp b/app/src/common/res/mipmap-xhdpi/common_ic_unchecked_white.webp new file mode 100644 index 000000000..78b9334cd Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_unchecked_white.webp differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_unselected.png b/app/src/common/res/mipmap-xhdpi/common_ic_unselected.png new file mode 100644 index 000000000..e1daf9c9b Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_unselected.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_wechat.png b/app/src/common/res/mipmap-xhdpi/common_ic_wechat.png new file mode 100644 index 000000000..ef035f34a Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_wechat.png differ diff --git a/app/src/common/res/mipmap-xhdpi/common_ic_wechat_grey.png b/app/src/common/res/mipmap-xhdpi/common_ic_wechat_grey.png new file mode 100644 index 000000000..03c8e8988 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/common_ic_wechat_grey.png differ diff --git a/app/src/common/res/mipmap-xhdpi/drawable_checkbox_selected.png b/app/src/common/res/mipmap-xhdpi/drawable_checkbox_selected.png new file mode 100644 index 000000000..d044e91ba Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/drawable_checkbox_selected.png differ diff --git a/app/src/common/res/mipmap-xhdpi/drawable_checkbox_unselected.png b/app/src/common/res/mipmap-xhdpi/drawable_checkbox_unselected.png new file mode 100644 index 000000000..083f2239e Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/drawable_checkbox_unselected.png differ diff --git a/app/src/common/res/mipmap-xhdpi/ic_private_chat.png b/app/src/common/res/mipmap-xhdpi/ic_private_chat.png new file mode 100644 index 000000000..c3da0b280 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/ic_private_chat.png differ diff --git a/app/src/common/res/mipmap-xhdpi/ic_user_new_10dp.png b/app/src/common/res/mipmap-xhdpi/ic_user_new_10dp.png new file mode 100644 index 000000000..373ad556b Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/ic_user_new_10dp.png differ diff --git a/app/src/common/res/mipmap-xhdpi/ic_user_new_13dp.png b/app/src/common/res/mipmap-xhdpi/ic_user_new_13dp.png new file mode 100644 index 000000000..e76f047ac Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/ic_user_new_13dp.png differ diff --git a/app/src/common/res/mipmap-xhdpi/ic_user_official_10dp.png b/app/src/common/res/mipmap-xhdpi/ic_user_official_10dp.png new file mode 100644 index 000000000..5acc1c7e3 Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/ic_user_official_10dp.png differ diff --git a/app/src/common/res/mipmap-xhdpi/ic_user_official_13dp.png b/app/src/common/res/mipmap-xhdpi/ic_user_official_13dp.png new file mode 100644 index 000000000..5159b384d Binary files /dev/null and b/app/src/common/res/mipmap-xhdpi/ic_user_official_13dp.png differ diff --git a/app/src/common/res/mipmap-xxhdpi/common_ic_checked.webp b/app/src/common/res/mipmap-xxhdpi/common_ic_checked.webp new file mode 100644 index 000000000..f6e21c14c Binary files /dev/null and b/app/src/common/res/mipmap-xxhdpi/common_ic_checked.webp differ diff --git a/app/src/common/res/mipmap-xxhdpi/common_ic_checked_white.webp b/app/src/common/res/mipmap-xxhdpi/common_ic_checked_white.webp new file mode 100644 index 000000000..008c019f6 Binary files /dev/null and b/app/src/common/res/mipmap-xxhdpi/common_ic_checked_white.webp differ diff --git a/app/src/common/res/mipmap-xxhdpi/common_ic_help.webp b/app/src/common/res/mipmap-xxhdpi/common_ic_help.webp new file mode 100644 index 000000000..6bcc5176d Binary files /dev/null and b/app/src/common/res/mipmap-xxhdpi/common_ic_help.webp differ diff --git a/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked.webp b/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked.webp new file mode 100644 index 000000000..1374f5f79 Binary files /dev/null and b/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked.webp differ diff --git a/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked_white.webp b/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked_white.webp new file mode 100644 index 000000000..39606654a Binary files /dev/null and b/app/src/common/res/mipmap-xxhdpi/common_ic_unchecked_white.webp differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..3d567f194 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,1134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/ShareSDK.xml b/app/src/main/assets/ShareSDK.xml new file mode 100644 index 000000000..dbf42c54d --- /dev/null +++ b/app/src/main/assets/ShareSDK.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/NimbusSanConLOT-Bla.otf b/app/src/main/assets/fonts/NimbusSanConLOT-Bla.otf new file mode 100644 index 000000000..1281df5e0 Binary files /dev/null and b/app/src/main/assets/fonts/NimbusSanConLOT-Bla.otf differ diff --git a/app/src/main/assets/svga/svga_voice_bottle.svga b/app/src/main/assets/svga/svga_voice_bottle.svga new file mode 100644 index 000000000..24531c0bc Binary files /dev/null and b/app/src/main/assets/svga/svga_voice_bottle.svga differ diff --git a/app/src/main/assets/svga/svga_voice_bubble.svga b/app/src/main/assets/svga/svga_voice_bubble.svga new file mode 100644 index 000000000..20be5de53 Binary files /dev/null and b/app/src/main/assets/svga/svga_voice_bubble.svga differ diff --git a/app/src/main/assets/svga/svga_voice_like_button.svga b/app/src/main/assets/svga/svga_voice_like_button.svga new file mode 100644 index 000000000..e6b7d919d Binary files /dev/null and b/app/src/main/assets/svga/svga_voice_like_button.svga differ diff --git a/app/src/main/java/com/jph/takephoto/app/TakePhoto.java b/app/src/main/java/com/jph/takephoto/app/TakePhoto.java new file mode 100644 index 000000000..010f786e6 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/app/TakePhoto.java @@ -0,0 +1,126 @@ +package com.jph.takephoto.app; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.MultipleCrop; +import com.jph.takephoto.model.TException; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.model.TakePhotoOptions; +import com.jph.takephoto.permission.PermissionManager; + + +/** + - 支持通过相机拍照获取图片 + - 支持从相册选择图片 + - 支持从文件选择图片 + - 支持多图选择 + - 支持批量图片裁切 + - 支持批量图片压缩 + - 支持对图片进行压缩 + - 支持对图片进行裁剪 + - 支持对裁剪及压缩参数自定义 + - 提供自带裁剪工具(可选) + - 支持智能选取及裁剪异常处理 + - 支持因拍照Activity被回收后的自动恢复 + * Author: crazycodeboy + * Date: 2016/9/21 0007 20:10 + * Version:4.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public interface TakePhoto { + /** + * 图片多选 + * @param limit 最多选择图片张数的限制 + * */ + void onPickMultiple(int limit); + /** + * 图片多选,并裁切 + * @param limit 最多选择图片张数的限制 + * @param options 裁剪配置 + * */ + void onPickMultipleWithCrop(int limit, CropOptions options); + /** + * 从文件中获取图片(不裁剪) + */ + void onPickFromDocuments(); + /** + * 从文件中获取图片并裁剪 + * @param outPutUri 图片裁剪之后保存的路径 + * @param options 裁剪配置 + */ + void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options); + /** + * 从相册中获取图片(不裁剪) + */ + void onPickFromGallery(); + /** + * 从相册中获取图片并裁剪 + * @param outPutUri 图片裁剪之后保存的路径 + * @param options 裁剪配置 + */ + void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options); + + /** + * 从相机获取图片(不裁剪) + * @param outPutUri 图片保存的路径 + */ + void onPickFromCapture(Uri outPutUri); + /** + * 从相机获取图片并裁剪 + * @param outPutUri 图片裁剪之后保存的路径 + * @param options 裁剪配置 + */ + void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options); + + /** + * 裁剪图片 + * @param imageUri 要裁剪的图片 + * @param outPutUri 图片裁剪之后保存的路径 + * @param options 裁剪配置 + */ + void onCrop(Uri imageUri, Uri outPutUri, CropOptions options)throws TException; + /** + * 裁剪多张图片 + * @param multipleCrop 要裁切的图片的路径以及输出路径 + * @param options 裁剪配置 + */ + void onCrop(MultipleCrop multipleCrop, CropOptions options)throws TException; + void permissionNotify(PermissionManager.TPermissionType type); + /** + * 启用图片压缩 + * @param config 压缩图片配置 + * @param showCompressDialog 压缩时是否显示进度对话框 + */ + void onEnableCompress(CompressConfig config, boolean showCompressDialog); + + /** + * 设置TakePhoto相关配置 + * @param options + */ + void setTakePhotoOptions(TakePhotoOptions options); + void onCreate(Bundle savedInstanceState); + void onSaveInstanceState(Bundle outState); + /** + * 处理拍照或从相册选择的图片或裁剪的结果 + * @param requestCode + * @param resultCode + * @param data + */ + void onActivityResult(int requestCode, int resultCode, Intent data); + /** + * 拍照结果监听接口 + */ + interface TakeResultListener { + void takeSuccess(TResult result); + + void takeFail(TResult result, String msg); + + void takeCancel(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jph/takephoto/app/TakePhotoActivity.java b/app/src/main/java/com/jph/takephoto/app/TakePhotoActivity.java new file mode 100644 index 000000000..cdd753fcd --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/app/TakePhotoActivity.java @@ -0,0 +1,100 @@ +package com.jph.takephoto.app; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.util.Log; + +import com.jph.takephoto.model.InvokeParam; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.permission.InvokeListener; +import com.jph.takephoto.permission.PermissionManager; +import com.jph.takephoto.permission.PermissionManager.TPermissionType; +import com.jph.takephoto.permission.TakePhotoInvocationHandler; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; + +/** + * 继承这个类来让Activity获取拍照的能力
+ * Author: crazycodeboy + * Date: 2016/9/21 0007 20:10 + * Version:3.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TakePhotoActivity extends BaseActivity implements TakePhoto.TakeResultListener, InvokeListener { + private static final String TAG = TakePhotoActivity.class.getName(); + private TakePhoto takePhoto; + private InvokeParam invokeParam; + + @Override + @CallSuper + protected void onCreate(Bundle savedInstanceState) { + getTakePhoto().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + + //保存activity之前的状态 + @Override + @CallSuper + protected void onSaveInstanceState(Bundle outState) { + getTakePhoto().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + + //访问请求结果 + @Override + @CallSuper + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + getTakePhoto().onActivityResult(requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + + } + + //请求权限返回结果 + @Override + @CallSuper + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + TPermissionType type = PermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + PermissionManager.handlePermissionsResult(this, type, invokeParam, this); + } + + /** + * 获取TakePhoto实例 + * + * @return + */ + public TakePhoto getTakePhoto() { + if (takePhoto == null) { + takePhoto = (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this, this)); + } + return takePhoto; + } + + @Override + public void takeSuccess(TResult result) { + Log.i(TAG, "takeSuccess:" + result.getImage().getCompressPath()); + } + + @Override + public void takeFail(TResult result, String msg) { + Log.i(TAG, "takeFail:" + msg); + } + + @Override + public void takeCancel() { + Log.i(TAG, getResources().getString(R.string.msg_operation_canceled)); + } + + @Override + public TPermissionType invoke(InvokeParam invokeParam) { + TPermissionType type = PermissionManager.checkPermission(TContextWrap.of(this), invokeParam.getMethod()); + if (TPermissionType.WAIT.equals(type)) { + this.invokeParam = invokeParam; + } + return type; + } +} diff --git a/app/src/main/java/com/jph/takephoto/app/TakePhotoFragment.java b/app/src/main/java/com/jph/takephoto/app/TakePhotoFragment.java new file mode 100644 index 000000000..9ef37a620 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/app/TakePhotoFragment.java @@ -0,0 +1,81 @@ +package com.jph.takephoto.app; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; + +import com.jph.takephoto.model.InvokeParam; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.permission.InvokeListener; +import com.jph.takephoto.permission.PermissionManager; +import com.jph.takephoto.permission.TakePhotoInvocationHandler; +import com.yizhuan.erban.R; + +/** + * 继承这个类来让Fragment获取拍照的能力
+ * Author: crazycodeboy + * Date: 2016/9/21 0007 20:10 + * Version:3.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TakePhotoFragment extends Fragment implements TakePhoto.TakeResultListener,InvokeListener { + private static final String TAG = TakePhotoFragment.class.getName(); + private InvokeParam invokeParam; + private TakePhoto takePhoto; + + @Override + public void onCreate(Bundle savedInstanceState) { + getTakePhoto().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + @Override + public void onSaveInstanceState(Bundle outState) { + getTakePhoto().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + getTakePhoto().onActivityResult(requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + PermissionManager.TPermissionType type= PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults); + PermissionManager.handlePermissionsResult(getActivity(),type,invokeParam,this); + } + /** + * 获取TakePhoto实例 + * @return + */ + public TakePhoto getTakePhoto(){ + if (takePhoto==null){ + takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this)); + } + return takePhoto; + } + @Override + public void takeSuccess(TResult result) { + Log.i(TAG,"takeSuccess:" + result.getImage().getCompressPath()); + } + @Override + public void takeFail(TResult result, String msg) { + Log.i(TAG, "takeFail:" + msg); + } + @Override + public void takeCancel() { + Log.i(TAG, getResources().getString(R.string.msg_operation_canceled)); + } + @Override + public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) { + PermissionManager.TPermissionType type= PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod()); + if(PermissionManager.TPermissionType.WAIT.equals(type)){ + this.invokeParam=invokeParam; + } + return type; + } +} diff --git a/app/src/main/java/com/jph/takephoto/app/TakePhotoFragmentActivity.java b/app/src/main/java/com/jph/takephoto/app/TakePhotoFragmentActivity.java new file mode 100644 index 000000000..da935da55 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/app/TakePhotoFragmentActivity.java @@ -0,0 +1,80 @@ +package com.jph.takephoto.app; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.util.Log; + +import com.jph.takephoto.model.InvokeParam; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.permission.InvokeListener; +import com.jph.takephoto.permission.PermissionManager; +import com.jph.takephoto.permission.TakePhotoInvocationHandler; +import com.yizhuan.erban.R; + +/** + * 继承这个类来让Activity获取拍照的能力
+ * Author: crazycodeboy + * Date: 2016/9/21 0007 20:10 + * Version:3.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TakePhotoFragmentActivity extends FragmentActivity implements TakePhoto.TakeResultListener,InvokeListener { + private static final String TAG = TakePhotoFragmentActivity.class.getName(); + private TakePhoto takePhoto; + private InvokeParam invokeParam; + @Override + protected void onCreate(Bundle savedInstanceState) { + getTakePhoto().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + @Override + protected void onSaveInstanceState(Bundle outState) { + getTakePhoto().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + getTakePhoto().onActivityResult(requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + PermissionManager.TPermissionType type= PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults); + PermissionManager.handlePermissionsResult(this,type,invokeParam,this); + } + /** + * 获取TakePhoto实例 + * @return + */ + public TakePhoto getTakePhoto(){ + if (takePhoto==null){ + takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this)); + } + return takePhoto; + } + @Override + public void takeSuccess(TResult result) { + Log.i(TAG,"takeSuccess:" + result.getImage().getCompressPath()); + } + @Override + public void takeFail(TResult result, String msg) { + Log.i(TAG, "takeFail:" + msg); + } + @Override + public void takeCancel() { + Log.i(TAG, getResources().getString(R.string.msg_operation_canceled)); + } + @Override + public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) { + PermissionManager.TPermissionType type= PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod()); + if(PermissionManager.TPermissionType.WAIT.equals(type)){ + this.invokeParam=invokeParam; + } + return type; + } +} diff --git a/app/src/main/java/com/jph/takephoto/app/TakePhotoImpl.java b/app/src/main/java/com/jph/takephoto/app/TakePhotoImpl.java new file mode 100644 index 000000000..96373efc3 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/app/TakePhotoImpl.java @@ -0,0 +1,529 @@ +package com.jph.takephoto.app; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.widget.Toast; + +import com.darsh.multipleimageselect.helpers.Constants; +import com.darsh.multipleimageselect.models.Image; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.compress.CompressImage; +import com.jph.takephoto.compress.CompressImageImpl; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.MultipleCrop; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TException; +import com.jph.takephoto.model.TExceptionType; +import com.jph.takephoto.model.TImage; +import com.jph.takephoto.model.TIntentWap; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.model.TakePhotoOptions; +import com.jph.takephoto.permission.PermissionManager; +import com.jph.takephoto.uitl.ImageRotateUtil; +import com.jph.takephoto.uitl.IntentUtils; +import com.jph.takephoto.uitl.TConstant; +import com.jph.takephoto.uitl.TFileUtils; +import com.jph.takephoto.uitl.TImageFiles; +import com.jph.takephoto.uitl.TUriParse; +import com.jph.takephoto.uitl.TUtils; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.orhanobut.logger.Logger; +import com.soundcloud.android.crop.Crop; +import com.soundcloud.android.crop.CropImageActivity; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.Map; + +/** + * - 支持通过相机拍照获取图片 + * - 支持从相册选择图片 + * - 支持从文件选择图片 + * - 支持多图选择 + * - 支持批量图片裁切 + * - 支持批量图片压缩 + * - 支持对图片进行压缩 + * - 支持对图片进行裁剪 + * - 支持对裁剪及压缩参数自定义 + * - 提供自带裁剪工具(可选) + * - 支持智能选取及裁剪异常处理 + * - 支持因拍照Activity被回收后的自动恢复 + * Date: 2016/9/21 0007 20:10 + * Version:4.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TakePhotoImpl implements TakePhoto { + private static final String TAG = IntentUtils.class.getName(); + private TContextWrap contextWrap; + private TakeResultListener listener; + private Uri outPutUri; + private Uri tempUri; + private CropOptions cropOptions; + private TakePhotoOptions takePhotoOptions; + private CompressConfig compressConfig; + private MultipleCrop multipleCrop; + private PermissionManager.TPermissionType permissionType; + private TImage.FromType fromType; //CAMERA图片来源相机,OTHER图片来源其他 + + /** + * 是否显示压缩对话框 + */ + private boolean showCompressDialog; + private ProgressDialog wailLoadDialog; + + public TakePhotoImpl(Activity activity, TakeResultListener listener) { + contextWrap = TContextWrap.of(activity); + this.listener = listener; + defaultInit(); + } + + public TakePhotoImpl(Fragment fragment, TakeResultListener listener) { + contextWrap = TContextWrap.of(fragment); + this.listener = listener; + defaultInit(); + } + + private void defaultInit() { + //需要矫正图片角度 + setTakePhotoOptions(new TakePhotoOptions.Builder().setCorrectImage(true).create()); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + cropOptions = (CropOptions) savedInstanceState.getSerializable("cropOptions"); + takePhotoOptions = (TakePhotoOptions) savedInstanceState.getSerializable("takePhotoOptions"); + showCompressDialog = savedInstanceState.getBoolean("showCompressDialog"); + outPutUri = savedInstanceState.getParcelable("outPutUri"); + tempUri = savedInstanceState.getParcelable("tempUri"); + compressConfig = (CompressConfig) savedInstanceState.getSerializable("compressConfig"); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putSerializable("cropOptions", cropOptions); + outState.putSerializable("takePhotoOptions", takePhotoOptions); + outState.putBoolean("showCompressDialog", showCompressDialog); + outState.putParcelable("outPutUri", outPutUri); + outState.putParcelable("tempUri", tempUri); + outState.putSerializable("compressConfig", compressConfig); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (outPutUri == null && data != null) { + outPutUri = data.getData(); + if (outPutUri == null) return; + } + switch (requestCode) { + case TConstant.RC_PICK_PICTURE_FROM_GALLERY_CROP: + if (resultCode == Activity.RESULT_OK && data != null) {//从相册选择照片并裁剪 + try { + onCrop(data.getData(), outPutUri, cropOptions); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL://从相册选择照片不裁剪 + if (resultCode == Activity.RESULT_OK) { + try { + String realPath = TUriParse.getFilePathWithUri(data.getData(), contextWrap.getActivity()); + takeResult(TResult.of(TImage.of(realPath, fromType))); + } catch (TException e) { + takeResult(TResult.of(TImage.of(data.getData(), fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL://从文件选择照片不裁剪 + if (resultCode == Activity.RESULT_OK) { + try { + String realPath = TUriParse.getFilePathWithDocumentsUri(data.getData(), contextWrap.getActivity()); + takeResult(TResult.of(TImage.of(realPath, fromType))); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_CROP://从文件选择照片,并裁剪 + if (resultCode == Activity.RESULT_OK) { + try { + onCrop(data.getData(), outPutUri, cropOptions); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_PICK_PICTURE_FROM_CAPTURE_CROP://拍取照片,并裁剪 + //TODO:断点 拍照裁剪 + if (resultCode == Activity.RESULT_OK) { + try { + onCrop(tempUri, Uri.fromFile(new File(TUriParse.parseOwnUri(contextWrap.getActivity(), outPutUri))), cropOptions); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_PICK_PICTURE_FROM_CAPTURE://拍取照片 + if (resultCode == Activity.RESULT_OK) { + try { + takeResult(TResult.of(TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType))); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } else { + listener.takeCancel(); + } + break; + case TConstant.RC_CROP://裁剪照片返回结果 + case Crop.REQUEST_CROP://裁剪照片返回结果 + if (resultCode == Activity.RESULT_OK) { + if (multipleCrop != null) { + cropContinue(true); + } else { + try { + TImage image = TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType); + image.setCropped(true); + takeResult(TResult.of(image)); + } catch (TException e) { + takeResult(TResult.of(TImage.of(outPutUri.getPath(), fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } + } else if (resultCode == Activity.RESULT_CANCELED) {//裁剪的照片没有保存 + if (multipleCrop != null) { + if (data != null) { + Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据 + TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件 + cropContinue(true); + } else { + cropContinue(false); + } + } else { + if (data != null) { + Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据 + TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件 + + TImage image = TImage.of(outPutUri.getPath(), fromType); + image.setCropped(true); + takeResult(TResult.of(image)); + } else { + listener.takeCancel(); + } + } + } else { + if (multipleCrop != null) { + cropContinue(false); + } else { + listener.takeCancel(); + } + } + break; + case TConstant.RC_PICK_MULTIPLE://多选图片返回结果 + if (resultCode == Activity.RESULT_OK && data != null) { + ArrayList images = data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES); + if (cropOptions != null) { + try { + onCrop(MultipleCrop.of(TUtils.convertImageToUri(contextWrap.getActivity(), images), contextWrap.getActivity(), fromType), cropOptions); + } catch (TException e) { + cropContinue(false); + e.printStackTrace(); + } + } else { + takeResult(TResult.of(TUtils.getTImagesWithImages(images, fromType))); + } + + } else { + listener.takeCancel(); + } + break; + default: + break; + } + } + + @Override + public void onPickMultiple(int limit) { + if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return; + TUtils.startActivityForResult(contextWrap, new TIntentWap(IntentUtils.getPickMultipleIntent(contextWrap, limit), TConstant.RC_PICK_MULTIPLE)); + } + + @Override + public void onPickMultipleWithCrop(int limit, CropOptions options) { + this.fromType = TImage.FromType.OTHER; + onPickMultiple(limit); + this.cropOptions = options; + } + + /** + * -----crop------ + **/ + @Override + public void onCrop(Uri imageUri, Uri outPutUri, CropOptions options) throws TException { + if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return; + this.outPutUri = outPutUri; + if (!TImageFiles.checkMimeType(contextWrap.getActivity(), TImageFiles.getMimeType(contextWrap.getActivity(), imageUri))) { +// Toast.makeText(contextWrap.getActivity(), contextWrap.getActivity().getResources().getText(R.string.tip_type_not_image), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.tip_type_not_image); + throw new TException(TExceptionType.TYPE_NOT_IMAGE); + } + cropWithNonException(imageUri, outPutUri, options); + } + + @Override + public void onCrop(MultipleCrop multipleCrop, CropOptions options) throws TException { + this.multipleCrop = multipleCrop; + onCrop(multipleCrop.getUris().get(0), multipleCrop.getOutUris().get(0), options); + } + + private void cropWithNonException(Uri imageUri, Uri outPutUri, CropOptions options) { + //bugly这里出现options为null的情况,具体原因待排查... + //猜测可能是takePhoneImpl 实例只有一个,options出现意外清空的情况 + if (options == null) { + return; + } + this.outPutUri = outPutUri; + if (options.isWithOwnCrop()) { + TUtils.cropWithOwnApp(contextWrap, imageUri, outPutUri, options); + } else { + TUtils.cropWithOtherAppBySafely(contextWrap, imageUri, outPutUri, options); + } + } + + private void cropContinue(boolean preSuccess) { + Map result = multipleCrop.setCropWithUri(outPutUri, preSuccess); + int index = (int) result.get("index"); + boolean isLast = (boolean) result.get("isLast"); + + if (isLast) { + if (preSuccess) { + takeResult(TResult.of(multipleCrop.gettImages())); + } else { + takeResult(TResult.of(multipleCrop.gettImages()), outPutUri.getPath() + contextWrap.getActivity().getResources().getString(R.string.msg_crop_canceled)); + } + } else { + cropWithNonException(multipleCrop.getUris().get(index + 1), multipleCrop.getOutUris().get(index + 1), cropOptions); + } + } + + @Override + public void onPickFromDocuments() { + selectPicture(0, false); + } + + @Override + public void onPickFromGallery() { + selectPicture(1, false); + } + + private void selectPicture(int defaultIndex, boolean isCrop) { + this.fromType = TImage.FromType.OTHER; + if (takePhotoOptions != null && takePhotoOptions.isWithOwnGallery()) { + onPickMultiple(1); + return; + } + if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return; + ArrayList intentWapList = new ArrayList<>(); + intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithDocuments(), isCrop ? TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_CROP : TConstant.RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL)); + intentWapList.add(new TIntentWap(IntentUtils.getPickIntentWithGallery(), isCrop ? TConstant.RC_PICK_PICTURE_FROM_GALLERY_CROP : TConstant.RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL)); + try { + TUtils.sendIntentBySafely(contextWrap, intentWapList, defaultIndex, isCrop); + } catch (TException e) { + takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } + + @Override + public void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options) { + this.cropOptions = options; + this.outPutUri = outPutUri; + selectPicture(1, true); + } + + @Override + public void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options) { + this.cropOptions = options; + this.outPutUri = outPutUri; + selectPicture(0, true); + } + + @Override + public void onPickFromCapture(Uri outPutUri) { + this.fromType = TImage.FromType.CAMERA; + if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return; + if (Build.VERSION.SDK_INT >= 23) { + this.outPutUri = TUriParse.convertFileUriToFileProviderUri(contextWrap.getActivity(), outPutUri); + } else { + this.outPutUri = outPutUri; + } + + try { + TUtils.captureBySafely(contextWrap, new TIntentWap(IntentUtils.getCaptureIntent(this.outPutUri), TConstant.RC_PICK_PICTURE_FROM_CAPTURE)); + } catch (TException e) { + takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } + + @Override + public void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options) { + this.fromType = TImage.FromType.CAMERA; + if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return; + this.cropOptions = options; + this.outPutUri = outPutUri; + if (Build.VERSION.SDK_INT >= 23) { + this.tempUri = TUriParse.getTempUri(contextWrap.getActivity()); + } else { + this.tempUri = outPutUri; + } + + try { + TUtils.captureBySafely(contextWrap, new TIntentWap(IntentUtils.getCaptureIntent(this.tempUri), TConstant.RC_PICK_PICTURE_FROM_CAPTURE_CROP)); + } catch (TException e) { + takeResult(TResult.of(TImage.of("", fromType)), e.getDetailMessage()); + e.printStackTrace(); + } + } + + @Override + public void onEnableCompress(CompressConfig config, boolean showCompressDialog) { + this.compressConfig = config; + this.showCompressDialog = showCompressDialog; + } + + @Override + public void setTakePhotoOptions(TakePhotoOptions options) { + this.takePhotoOptions = options; + } + + @Override + public void permissionNotify(PermissionManager.TPermissionType type) { + this.permissionType = type; + } + + private void takeResult(final TResult result, final String... message) { + if (null == compressConfig) { + handleTakeCallBack(result, message); + } else { + if (showCompressDialog) + wailLoadDialog = TUtils.showProgressDialog(contextWrap.getActivity(), contextWrap.getActivity().getResources().getString(R.string.tip_compress)); + + CompressImageImpl.of(contextWrap.getActivity(), compressConfig, result.getImages(), new CompressImage.CompressListener() { + @Override + public void onCompressSuccess(ArrayList images) { + if(compressConfig != null && !compressConfig.isEnableReserveRaw()) { + deleteRawFile(images); + } + handleTakeCallBack(result); + if (wailLoadDialog != null && !contextWrap.getActivity().isFinishing()) + wailLoadDialog.dismiss(); + } + + @Override + public void onCompressFailed(ArrayList images, String msg) { + if(!compressConfig.isEnableReserveRaw()) { + deleteRawFile(images); + } + handleTakeCallBack(TResult.of(images), String.format(contextWrap.getActivity().getResources().getString(R.string.tip_compress_failed), message.length > 0 ? message[0] : "", msg, result.getImage().getCompressPath())); + if (wailLoadDialog != null && !contextWrap.getActivity().isFinishing()) + wailLoadDialog.dismiss(); + } + }).compress(); + } + } + + private void deleteRawFile(ArrayList images) { + for(TImage image : images) { + if(TImage.FromType.CAMERA == fromType) { + TFileUtils.delete(image.getOriginalPath()); + image.setOriginalPath(""); + } + } + } + + private void handleTakeCallBack(final TResult result, String... message) { + boolean success = false; + if (message.length > 0) { + listener.takeFail(result, message[0]); + } else if (multipleCrop != null && multipleCrop.hasFailed) { + listener.takeFail(result, contextWrap.getActivity().getResources().getString(R.string.msg_crop_failed)); + } else if (compressConfig != null) { + boolean hasFailed = false; + for (TImage image : result.getImages()) { + if (image == null || !image.isCompressed()) { + hasFailed = true; + break; + } + } + if (hasFailed) { + listener.takeFail(result, contextWrap.getActivity().getString(R.string.msg_compress_failed)); + } else { + success = true; + } + } else { + success = true; + } + //这里矫正图片的旋转角度 + if (success) { + if (takePhotoOptions != null && takePhotoOptions.isCorrectImage() && result != null) { + for (TImage image : result.getImages()) { + if (image != null + && !TextUtils.isEmpty(image.getOriginalPath()) + && !TextUtils.isEmpty(image.getCompressPath())) { + int degree = ImageRotateUtil.of().getBitmapDegree(image.getOriginalPath()); + Logger.i("crop info rotate degree = " + degree); + String rotatePath = ImageRotateUtil.of().correctImage( + image.getCompressPath(), degree); + if (!TextUtils.isEmpty(rotatePath)) { + String oldCompressPath = image.getCompressPath(); + File file = new File(oldCompressPath); + if (file.exists()) { + //noinspection ResultOfMethodCallIgnored + file.delete(); + } + image.setCompressPath(rotatePath); + Logger.i("fix path = " + rotatePath); + } + } + } + } + listener.takeSuccess(result); + } + clearParams(); + } + + private void clearParams() { + compressConfig = null; + cropOptions = null; + multipleCrop = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jph/takephoto/compress/CompressConfig.java b/app/src/main/java/com/jph/takephoto/compress/CompressConfig.java new file mode 100644 index 000000000..d795bdec1 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/compress/CompressConfig.java @@ -0,0 +1,123 @@ +package com.jph.takephoto.compress; + + +import com.jph.takephoto.model.LubanOptions; + +import java.io.Serializable; + +/** + * 压缩配置类 + * Author: JPH + * Date: 2016/6/7 0007 18:01 + */ +public class CompressConfig implements Serializable { + + /** + * 长或宽不超过的最大像素,单位px + */ + private int maxPixel=1280; + /** + * 压缩到的最大大小,单位B + */ + private int maxSize=500*1024; + + /** + * 是否启用像素压缩 + */ + private boolean enablePixelCompress=true; + /** + * 是否启用质量压缩 + */ + private boolean enableQualityCompress=true; + + /** + * 是否保留原文件 + */ + private boolean enableReserveRaw = true; + + /** + * Luban压缩配置 + */ + private LubanOptions lubanOptions; + public static CompressConfig ofDefaultConfig(){ + return new CompressConfig(); + } + public static CompressConfig ofLuban(LubanOptions options){ + return new CompressConfig(options); + } + private CompressConfig(){} + private CompressConfig(LubanOptions options){ + this.lubanOptions=options; + } + + public LubanOptions getLubanOptions() { + return lubanOptions; + } + + public int getMaxPixel() { + return maxPixel; + } + public CompressConfig setMaxPixel(int maxPixel) { + this.maxPixel = maxPixel; + return this; + } + public int getMaxSize() { + return maxSize; + } + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } + + public boolean isEnablePixelCompress() { + return enablePixelCompress; + } + + public void enablePixelCompress(boolean enablePixelCompress) { + this.enablePixelCompress = enablePixelCompress; + } + + public boolean isEnableQualityCompress() { + return enableQualityCompress; + } + + public void enableQualityCompress(boolean enableQualityCompress) { + this.enableQualityCompress = enableQualityCompress; + } + + public boolean isEnableReserveRaw() { + return enableReserveRaw; + } + public void enableReserveRaw(boolean enableReserveRaw) { + this.enableReserveRaw = enableReserveRaw; + } + public static class Builder{ + private CompressConfig config; + public Builder() { + config=new CompressConfig(); + } + public Builder setMaxSize(int maxSize) { + config.setMaxSize( maxSize); + return this; + } + public Builder setMaxPixel(int maxPixel) { + config.setMaxPixel(maxPixel); + return this; + } + public Builder enablePixelCompress(boolean enablePixelCompress) { + config.enablePixelCompress(enablePixelCompress); + return this; + } + public Builder enableQualityCompress(boolean enableQualityCompress) { + config.enableQualityCompress(enableQualityCompress); + return this; + } + public Builder enableReserveRaw(boolean enableReserveRaw) { + config.enableReserveRaw(enableReserveRaw); + return this; + } + public CompressConfig create(){ + return config; + } + } +} + diff --git a/app/src/main/java/com/jph/takephoto/compress/CompressImage.java b/app/src/main/java/com/jph/takephoto/compress/CompressImage.java new file mode 100644 index 000000000..54b11e5eb --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/compress/CompressImage.java @@ -0,0 +1,33 @@ +package com.jph.takephoto.compress; + +import com.jph.takephoto.model.TImage; + +import java.util.ArrayList; + +/** + * 压缩照片2.0 + * + * Author JPH + * Date 2015-08-26 下午1:44:26 + */ +public interface CompressImage { + void compress(); + + /** + * 压缩结果监听器 + */ + interface CompressListener { + /** + * 压缩成功 + * @param images 已经压缩图片 + */ + void onCompressSuccess(ArrayList images); + + /** + * 压缩失败 + * @param images 压缩失败的图片 + * @param msg 失败的原因 + */ + void onCompressFailed(ArrayList images, String msg); + } +} diff --git a/app/src/main/java/com/jph/takephoto/compress/CompressImageImpl.java b/app/src/main/java/com/jph/takephoto/compress/CompressImageImpl.java new file mode 100644 index 000000000..37b5300e4 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/compress/CompressImageImpl.java @@ -0,0 +1,100 @@ +package com.jph.takephoto.compress; + +import android.content.Context; +import android.text.TextUtils; + +import com.jph.takephoto.model.TImage; + +import java.io.File; +import java.util.ArrayList; + +/** + * 压缩照片 + * + * Date: 2016/9/21 0007 20:10 + * Version:3.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class CompressImageImpl implements CompressImage { + private CompressImageUtil compressImageUtil; + private ArrayList images; + private CompressImage.CompressListener listener; + + public static CompressImage of(Context context, CompressConfig config, ArrayList images, CompressImage.CompressListener listener) { + if(config.getLubanOptions()!=null){ + return new CompressWithLuBan(context,config,images,listener); + }else { + return new CompressImageImpl(context,config,images,listener); + } + } + private CompressImageImpl(Context context, CompressConfig config, ArrayList images, CompressImage.CompressListener listener){ + compressImageUtil = new CompressImageUtil(context,config); + this.images = images; + this.listener = listener; + } + + @Override + public void compress() { + if(images==null||images.isEmpty())listener.onCompressFailed(images," images is null"); + for(TImage image:images){ + if(image==null){ + listener.onCompressFailed(images," There are pictures of compress is null."); + return; + } + } + compress(images.get(0)); + } + + private void compress(final TImage image) { + if (TextUtils.isEmpty(image.getOriginalPath())){ + continueCompress(image,false); + return; + } + + File file = new File(image.getOriginalPath()); + if (!file.exists() || !file.isFile()){ + continueCompress(image,false); + return; + } + + compressImageUtil.compress(image.getOriginalPath(), new CompressImageUtil.CompressListener() { + @Override + public void onCompressSuccess(String imgPath) { + image.setCompressPath(imgPath); + continueCompress(image,true); + } + + @Override + public void onCompressFailed(String imgPath, String msg) { + continueCompress(image,false,msg); + } + }); + } + + private void continueCompress(TImage image, boolean preSuccess, String...message){ + image.setCompressed(preSuccess); + int index=images.indexOf(image); + boolean isLast=index== images.size() - 1; + if (isLast) { + handleCompressCallBack(message); + }else { + compress(images.get(index+1)); + } + } + private void handleCompressCallBack(String...message){ + if(message.length>0){ + listener.onCompressFailed(images,message[0]); + return; + } + + for(TImage image:images){ + if(!image.isCompressed()){ + listener.onCompressFailed(images,image.getCompressPath()+" is compress failures"); + return; + } + } + listener.onCompressSuccess(images); + } +} diff --git a/app/src/main/java/com/jph/takephoto/compress/CompressImageUtil.java b/app/src/main/java/com/jph/takephoto/compress/CompressImageUtil.java new file mode 100644 index 000000000..758db1f4d --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/compress/CompressImageUtil.java @@ -0,0 +1,166 @@ +package com.jph.takephoto.compress; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.os.Handler; + +import com.jph.takephoto.uitl.TFileUtils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +/** + * 压缩照片 + * @author JPH + * Date 2015-08-26 下午1:44:26 + * Version:1.0.3 + */ +public class CompressImageUtil{ + private CompressConfig config; + private Context context; + Handler mhHandler = new Handler(); + public CompressImageUtil(Context context,CompressConfig config) { + this.context=context; + this.config=config==null? CompressConfig.ofDefaultConfig():config; + } + public void compress(String imagePath, CompressListener listener) { + if (config.isEnablePixelCompress()){ + try { + compressImageByPixel(imagePath,listener); + } catch (FileNotFoundException e) { + listener.onCompressFailed(imagePath,String.format("图片压缩失败,%s",e.toString())); + e.printStackTrace(); + } + }else { + compressImageByQuality(BitmapFactory.decodeFile(imagePath),imagePath,listener); + } + } + /** + * 多线程压缩图片的质量 + * @author JPH + * @param bitmap 内存中的图片 + * @param imgPath 图片的保存路径 + * @date 2014-12-5下午11:30:43 + */ + private void compressImageByQuality(final Bitmap bitmap, final String imgPath, final CompressListener listener){ + if(bitmap==null){ + sendMsg(false,imgPath,"像素压缩失败,bitmap is null",listener); + return; + } + new Thread(new Runnable() {//开启多线程进行压缩处理 + @Override + public void run() { + // TODO Auto-generated method stub + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int options = 100; + bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小) + while (baos.toByteArray().length >config.getMaxSize()) {//循环判断如果压缩后图片是否大于指定大小,大于继续压缩 + baos.reset();//重置baos即让下一次的写入覆盖之前的内容 + options -= 5;//图片质量每次减少5 + if(options<=5)options=5;//如果图片质量小于5,为保证压缩后的图片质量,图片最底压缩质量为5 + bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//将压缩后的图片保存到baos中 + if(options==5)break;//如果图片的质量已降到最低则,不再进行压缩 + } +// if(bitmap!=null&&!bitmap.isRecycled()){ +// bitmap.recycle();//回收内存中的图片 +// } + try { + File thumbnailFile=getThumbnailFile(new File(imgPath)); + FileOutputStream fos = new FileOutputStream(thumbnailFile);//将压缩后的图片保存的本地上指定路径中 + fos.write(baos.toByteArray()); + fos.flush(); + fos.close(); + sendMsg(true, thumbnailFile.getPath(),null,listener); + } catch (Exception e) { + sendMsg(false,imgPath,"质量压缩失败",listener); + e.printStackTrace(); + } + } + }).start(); + } + /** + * 按比例缩小图片的像素以达到压缩的目的 + * @author JPH + * @param imgPath + * @return + * @date 2014-12-5下午11:30:59 + */ + private void compressImageByPixel(String imgPath,CompressListener listener) throws FileNotFoundException { + if(imgPath==null){ + sendMsg(false,imgPath,"要压缩的文件不存在",listener); + return; + } + BitmapFactory.Options newOpts = new BitmapFactory.Options(); + newOpts.inJustDecodeBounds = true;//只读边,不读内容 + BitmapFactory.decodeFile(imgPath, newOpts); + newOpts.inJustDecodeBounds = false; + int width = newOpts.outWidth; + int height = newOpts.outHeight; + float maxSize =config.getMaxPixel(); + int be = 1; + if (width >= height && width > maxSize) {//缩放比,用高或者宽其中较大的一个数据进行计算 + be = (int) (newOpts.outWidth / maxSize); + be++; + } else if (width < height && height > maxSize) { + be = (int) (newOpts.outHeight / maxSize); + be++; + } + newOpts.inSampleSize =be;//设置采样率 + newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设 + newOpts.inPurgeable = true;// 同时设置才会有效 + newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收 + Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts); + if (config.isEnableQualityCompress()){ + compressImageByQuality(bitmap,imgPath,listener);//压缩好比例大小后再进行质量压缩 + }else { + File thumbnailFile=getThumbnailFile(new File(imgPath)); + bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(thumbnailFile)); + + listener.onCompressSuccess(thumbnailFile.getPath()); + } + } + /** + * 发送压缩结果的消息 + * @param isSuccess 压缩是否成功 + * @param imagePath + * @param message + */ + private void sendMsg(final boolean isSuccess, final String imagePath,final String message, final CompressListener listener){ + mhHandler.post(new Runnable() { + @Override + public void run() { + if (isSuccess){ + listener.onCompressSuccess(imagePath); + }else{ + listener.onCompressFailed(imagePath,message); + } + } + }); + } + private File getThumbnailFile(File file){ + if (file==null||!file.exists())return file; + return TFileUtils.getPhotoCacheDir(context,file); + } + /** + * 压缩结果监听器 + */ + public interface CompressListener { + /** + * 压缩成功 + * + * @param imgPath 压缩图片的路径 + */ + void onCompressSuccess(String imgPath); + + /** + * 压缩失败 + * @param imgPath 压缩失败的图片 + * @param msg 失败的原因 + */ + void onCompressFailed(String imgPath, String msg); + } +} diff --git a/app/src/main/java/com/jph/takephoto/compress/CompressWithLuBan.java b/app/src/main/java/com/jph/takephoto/compress/CompressWithLuBan.java new file mode 100644 index 000000000..e9bfdcbd8 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/compress/CompressWithLuBan.java @@ -0,0 +1,113 @@ +package com.jph.takephoto.compress; + +import android.content.Context; + +import com.jph.takephoto.model.LubanOptions; +import com.jph.takephoto.model.TImage; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import me.shaohui.advancedluban.Luban; +import me.shaohui.advancedluban.OnCompressListener; +import me.shaohui.advancedluban.OnMultiCompressListener; + +/** + * 压缩照片,采用luban + * Author: crazycodeboy + * Date: 2016/11/5 0007 20:10 + * Version:4.0.0 + * 技术博文:http://www.devio.org/ + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class CompressWithLuBan implements CompressImage { + private ArrayList images; + private CompressListener listener; + private Context context; + private LubanOptions options; + private ArrayList files = new ArrayList<>(); + + public CompressWithLuBan(Context context, CompressConfig config, ArrayList images, + CompressListener listener) { + options = config.getLubanOptions(); + this.images = images; + this.listener = listener; + this.context = context; + } + + @Override public void compress() { + if (images == null || images.isEmpty()) { + listener.onCompressFailed(images, " images is null"); + return; + } + for (TImage image : images) { + if (image == null) { + listener.onCompressFailed(images, " There are pictures of compress is null."); + return; + } + files.add(new File(image.getOriginalPath())); + } + if (images.size() == 1) { + compressOne(); + } else { + compressMulti(); + } + } + + private void compressOne() { + Luban.compress(context, files.get(0)) + .putGear(Luban.CUSTOM_GEAR) + .setMaxHeight(options.getMaxHeight()) + .setMaxWidth(options.getMaxWidth()) + .setMaxSize(options.getMaxSize() / 1000) + .launch(new OnCompressListener() { + @Override public void onStart() { + + } + + @Override public void onSuccess(File file) { + TImage image = images.get(0); + image.setCompressPath(file.getPath()); + image.setCompressed(true); + listener.onCompressSuccess(images); + } + + @Override public void onError(Throwable e) { + listener.onCompressFailed(images, e.getMessage() + " is compress failures"); + } + }); + } + + private void compressMulti() { + Luban.compress(context, files) + .putGear(Luban.CUSTOM_GEAR) + .setMaxSize( + options.getMaxSize() / 1000) // limit the final image size(unit:Kb) + .setMaxHeight(options.getMaxHeight()) // limit image height + .setMaxWidth(options.getMaxWidth()) + .launch(new OnMultiCompressListener() { + @Override public void onStart() { + + } + + @Override public void onSuccess(List fileList) { + handleCompressCallBack(fileList); + } + + @Override public void onError(Throwable e) { + listener.onCompressFailed(images, e.getMessage() + " is compress failures"); + } + }); + } + + private void handleCompressCallBack(List files) { + for (int i = 0, j = images.size(); i < j; i++) { + TImage image = images.get(i); + image.setCompressed(true); + image.setCompressPath(files.get(i).getPath()); + } + listener.onCompressSuccess(images); + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/CropOptions.java b/app/src/main/java/com/jph/takephoto/model/CropOptions.java new file mode 100644 index 000000000..0d579ebdf --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/CropOptions.java @@ -0,0 +1,94 @@ +package com.jph.takephoto.model; + +import java.io.Serializable; + +/** + * 裁剪配置类 + * Author: JPH + * Date: 2016/7/27 13:19 + */ +public class CropOptions implements Serializable{ + /**使用TakePhoto自带的裁切工具进行裁切*/ + private boolean withOwnCrop; + private int aspectX; + private int aspectY; + private int outputX; + private int outputY; + private CropOptions(){} + + public int getAspectX() { + return aspectX; + } + + public void setAspectX(int aspectX) { + this.aspectX = aspectX; + } + + public int getAspectY() { + return aspectY; + } + + public void setAspectY(int aspectY) { + this.aspectY = aspectY; + } + + public int getOutputX() { + return outputX; + } + + public void setOutputX(int outputX) { + this.outputX = outputX; + } + + public int getOutputY() { + return outputY; + } + + public void setOutputY(int outputY) { + this.outputY = outputY; + } + + public boolean isWithOwnCrop() { + return withOwnCrop; + } + + public void setWithOwnCrop(boolean withOwnCrop) { + this.withOwnCrop = withOwnCrop; + } + + public static class Builder{ + private CropOptions options; + + public Builder() { + options=new CropOptions(); + } + + public Builder setAspectX(int aspectX) { + options.setAspectX(aspectX); + return this; + } + + public Builder setAspectY(int aspectY) { + options.setAspectY(aspectY); + return this; + } + + public Builder setOutputX(int outputX) { + options.setOutputX(outputX); + return this; + } + + public Builder setOutputY(int outputY) { + options.setOutputY(outputY); + return this; + } + + public Builder setWithOwnCrop(boolean withOwnCrop) { + options.setWithOwnCrop(withOwnCrop); + return this; + } + public CropOptions create(){ + return options; + } + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/InvokeParam.java b/app/src/main/java/com/jph/takephoto/model/InvokeParam.java new file mode 100644 index 000000000..160feebb3 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/InvokeParam.java @@ -0,0 +1,42 @@ +package com.jph.takephoto.model; + +import java.lang.reflect.Method; + +/** + * Created by penn on 16/9/22. + */ +public class InvokeParam { + private Object proxy; + private Method method; + private Object[] args; + + public InvokeParam(Object proxy, Method method, Object[] args) { + this.proxy = proxy; + this.method = method; + this.args = args; + } + + public Object getProxy() { + return proxy; + } + + public void setProxy(Object proxy) { + this.proxy = proxy; + } + + public Method getMethod() { + return method; + } + + public void setMethod(Method method) { + this.method = method; + } + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/LubanOptions.java b/app/src/main/java/com/jph/takephoto/model/LubanOptions.java new file mode 100644 index 000000000..f8a1caba5 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/LubanOptions.java @@ -0,0 +1,75 @@ +package com.jph.takephoto.model; + +import java.io.Serializable; + +/** + * Luban配置类 + * Author: crazycodeboy + * Date: 2016/11/5 0007 20:10 + * Version:4.0.1 + * 技术博文:http://www.devio.org/ + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class LubanOptions implements Serializable { + /** + * 压缩到的最大大小,单位B + */ + private int maxSize; + private int maxHeight; + private int maxWidth; + + private LubanOptions() { + } + + public int getMaxSize() { + return maxSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } + + public int getMaxHeight() { + return maxHeight; + } + + public void setMaxHeight(int maxHeight) { + this.maxHeight = maxHeight; + } + + public int getMaxWidth() { + return maxWidth; + } + + public void setMaxWidth(int maxWidth) { + this.maxWidth = maxWidth; + } + + public static class Builder { + private LubanOptions options; + + public Builder() { + options = new LubanOptions(); + } + + public Builder setMaxSize(int maxSize) { + options.setMaxSize(maxSize); + return this; + } + + public Builder setMaxHeight(int maxHeight) { + options.setMaxHeight(maxHeight); + return this; + } + + public Builder setMaxWidth(int maxWidth) { + options.setMaxWidth(maxWidth); + return this; + } + + public LubanOptions create() { + return options; + } + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/MultipleCrop.java b/app/src/main/java/com/jph/takephoto/model/MultipleCrop.java new file mode 100644 index 000000000..6240a4f47 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/MultipleCrop.java @@ -0,0 +1,84 @@ +package com.jph.takephoto.model; + +import android.app.Activity; +import android.net.Uri; + +import com.jph.takephoto.uitl.TImageFiles; +import com.jph.takephoto.uitl.TUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * Author: JPH + * Date: 2016/8/11 17:01 + */ +public class MultipleCrop { + private ArrayList uris; + private ArrayList outUris; + private ArrayListtImages; + private TImage.FromType fromType; + public boolean hasFailed;//是否有裁切失败的标识 + public static MultipleCrop of(ArrayList uris, Activity activity, TImage.FromType fromType) throws TException { + return new MultipleCrop(uris,activity, fromType); + } + public static MultipleCrop of(ArrayList uris, ArrayListoutUris, TImage.FromType fromType){ + return new MultipleCrop(uris,outUris, fromType); + } + private MultipleCrop(ArrayList uris,Activity activity, TImage.FromType fromType) throws TException { + this.uris=uris; + ArrayListoutUris=new ArrayList<>(); + for (Uri uri:uris){ + outUris.add(Uri.fromFile(TImageFiles.getTempFile(activity,uri)));//生成临时裁切输出路径 + } + this.outUris=outUris; + this.tImages= TUtils.getTImagesWithUris(outUris, fromType); + this.fromType = fromType; + } + private MultipleCrop(ArrayList uris,ArrayListoutUris, TImage.FromType fromType) { + this.uris=uris; + this.outUris=outUris; + this.tImages= TUtils.getTImagesWithUris(outUris, fromType); + this.fromType = fromType; + } + + public ArrayList getUris() { + return uris; + } + + public void setUris(ArrayList uris) { + this.uris = uris; + } + + public ArrayList getOutUris() { + return outUris; + } + + public void setOutUris(ArrayList outUris) { + this.outUris = outUris; + } + + public ArrayList gettImages() { + return tImages; + } + + public void settImages(ArrayList tImages) { + this.tImages = tImages; + } + + /** + * 为被裁切的图片设置已被裁切的标识 + * @param uri 被裁切的图片 + * @return 该图片是否是最后一张 + */ + public Map setCropWithUri(Uri uri,boolean cropped){ + if(!cropped)hasFailed=true; + int index=outUris.indexOf(uri); + tImages.get(index).setCropped(cropped); + Map result=new HashMap(); + result.put("index",index); + result.put("isLast",index==outUris.size()-1? true:false); + return result; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TContextWrap.java b/app/src/main/java/com/jph/takephoto/model/TContextWrap.java new file mode 100644 index 000000000..439a30be6 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TContextWrap.java @@ -0,0 +1,43 @@ +package com.jph.takephoto.model; + +import android.app.Activity; +import android.support.v4.app.Fragment; + +/** + * Author: JPH + * Date: 2016/8/11 17:01 + */ +public class TContextWrap { + private Activity activity; + private Fragment fragment; + public static TContextWrap of(Activity activity){ + return new TContextWrap(activity); + } + public static TContextWrap of(Fragment fragment){ + return new TContextWrap(fragment); + } + private TContextWrap(Activity activity) { + this.activity = activity; + } + + private TContextWrap(Fragment fragment) { + this.fragment = fragment; + this.activity=fragment.getActivity(); + } + + public Activity getActivity() { + return activity; + } + + public void setActivity(Activity activity) { + this.activity = activity; + } + + public Fragment getFragment() { + return fragment; + } + + public void setFragment(Fragment fragment) { + this.fragment = fragment; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TException.java b/app/src/main/java/com/jph/takephoto/model/TException.java new file mode 100644 index 000000000..844f36c3c --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TException.java @@ -0,0 +1,16 @@ +package com.jph.takephoto.model; + +/** + * Author: JPH + * Date: 2016/7/26 10:53 + */ +public class TException extends Exception{ + String detailMessage; + public TException(TExceptionType exceptionType) { + super(exceptionType.getStringValue()); + this.detailMessage=exceptionType.getStringValue(); + } + public String getDetailMessage() { + return detailMessage; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TExceptionType.java b/app/src/main/java/com/jph/takephoto/model/TExceptionType.java new file mode 100644 index 000000000..36988c659 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TExceptionType.java @@ -0,0 +1,24 @@ +package com.jph.takephoto.model; + +/** + * Author: JPH + * Date: 2016/7/26 11:01 + */ +public enum TExceptionType { + TYPE_NOT_IMAGE("选择的文件不是图片"), + TYPE_WRITE_FAIL("保存选择的的文件失败"), + TYPE_URI_NULL("所选照片的Uri 为null"), + TYPE_URI_PARSE_FAIL("从Uri中获取文件路径失败"), + TYPE_NO_MATCH_PICK_INTENT("没有匹配到选择图片的Intent"), + TYPE_NO_MATCH_CROP_INTENT("没有匹配到裁切图片的Intent"), + TYPE_NO_CAMERA("没有相机"), + TYPE_NO_FIND("选择的文件没有找到"); + + String stringValue; + TExceptionType(String stringValue) { + this.stringValue=stringValue; + } + public String getStringValue() { + return stringValue; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TImage.java b/app/src/main/java/com/jph/takephoto/model/TImage.java new file mode 100644 index 000000000..af6614989 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TImage.java @@ -0,0 +1,77 @@ +package com.jph.takephoto.model; + +import android.net.Uri; + +import java.io.Serializable; + +/** + * TakePhoto 操作成功返回的处理结果 + * + * Author: JPH + * Date: 2016/8/11 17:01 + */ +public class TImage implements Serializable{ + private String originalPath; + private String compressPath; + private FromType fromType; + private boolean cropped; + private boolean compressed; + public static TImage of(String path, FromType fromType){ + return new TImage(path, fromType); + } + public static TImage of(Uri uri, FromType fromType){ + return new TImage(uri, fromType); + } + private TImage(String path, FromType fromType) { + this.originalPath = path; + this.fromType = fromType; + } + private TImage(Uri uri, FromType fromType) { + this.originalPath = uri.getPath(); + this.fromType = fromType; + } + + public String getOriginalPath() { + return originalPath; + } + + public void setOriginalPath(String originalPath) { + this.originalPath = originalPath; + } + + public String getCompressPath() { + return compressPath; + } + + public void setCompressPath(String compressPath) { + this.compressPath = compressPath; + } + + public FromType getFromType() { + return fromType; + } + + public void setFromType(FromType fromType) { + this.fromType = fromType; + } + + public boolean isCropped() { + return cropped; + } + + public void setCropped(boolean cropped) { + this.cropped = cropped; + } + + public boolean isCompressed() { + return compressed; + } + + public void setCompressed(boolean compressed) { + this.compressed = compressed; + } + + public enum FromType { + CAMERA, OTHER + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TIntentWap.java b/app/src/main/java/com/jph/takephoto/model/TIntentWap.java new file mode 100644 index 000000000..4517acfc1 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TIntentWap.java @@ -0,0 +1,36 @@ +package com.jph.takephoto.model; + +import android.content.Intent; + +/** + * Author: JPH + * Date: 2016/7/26 14:23 + */ +public class TIntentWap { + private Intent intent; + private int requestCode; + + public TIntentWap() { + } + + public TIntentWap(Intent intent, int requestCode) { + this.intent = intent; + this.requestCode = requestCode; + } + + public Intent getIntent() { + return intent; + } + + public void setIntent(Intent intent) { + this.intent = intent; + } + + public int getRequestCode() { + return requestCode; + } + + public void setRequestCode(int requestCode) { + this.requestCode = requestCode; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TResult.java b/app/src/main/java/com/jph/takephoto/model/TResult.java new file mode 100644 index 000000000..bc6398831 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TResult.java @@ -0,0 +1,41 @@ +package com.jph.takephoto.model; + +import java.util.ArrayList; + +/** + * TakePhoto 操作成功返回的处理结果 + * Author: JPH + * Date: 2016/8/11 17:01 + */ +public class TResult { + private ArrayList images; + private TImage image; + public static TResult of(TImage image){ + ArrayList images=new ArrayList<>(1); + images.add(image); + return new TResult(images); + } + public static TResult of(ArrayList images){ + return new TResult(images); + } + private TResult(ArrayList images) { + this.images = images; + if(images!=null&&!images.isEmpty())this.image=images.get(0); + } + + public ArrayList getImages() { + return images; + } + + public void setImages(ArrayList images) { + this.images = images; + } + + public TImage getImage() { + return image; + } + + public void setImage(TImage image) { + this.image = image; + } +} diff --git a/app/src/main/java/com/jph/takephoto/model/TakePhotoOptions.java b/app/src/main/java/com/jph/takephoto/model/TakePhotoOptions.java new file mode 100644 index 000000000..49f2a2a10 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/model/TakePhotoOptions.java @@ -0,0 +1,61 @@ +package com.jph.takephoto.model; + +import java.io.Serializable; + +/** + * Author: crazycodeboy + * Date: 2016/11/5 0007 20:10 + * Version:4.0.0 + * 技术博文:http://www.devio.org/ + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TakePhotoOptions implements Serializable { + /** + * 是否使用TakePhoto自带的相册进行图片选择,默认不使用,但选择多张图片会使用 + */ + private boolean withOwnGallery; + /** + * 是对拍的照片进行旋转角度纠正 + */ + private boolean correctImage; + + private TakePhotoOptions() { + } + + public boolean isWithOwnGallery() { + return withOwnGallery; + } + + public void setWithOwnGallery(boolean withOwnGallery) { + this.withOwnGallery = withOwnGallery; + } + + public boolean isCorrectImage() { + return correctImage; + } + + public void setCorrectImage(boolean correctImage) { + this.correctImage = correctImage; + } + + public static class Builder { + private TakePhotoOptions options; + + public Builder() { + this.options = new TakePhotoOptions(); + } + + public Builder setWithOwnGallery(boolean withOwnGallery) { + options.setWithOwnGallery(withOwnGallery); + return this; + } + public Builder setCorrectImage(boolean isCorrectImage) { + options.setCorrectImage(isCorrectImage); + return this; + } + public TakePhotoOptions create(){ + return options; + } + } +} diff --git a/app/src/main/java/com/jph/takephoto/permission/InvokeListener.java b/app/src/main/java/com/jph/takephoto/permission/InvokeListener.java new file mode 100644 index 000000000..45297ceef --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/permission/InvokeListener.java @@ -0,0 +1,10 @@ +package com.jph.takephoto.permission; + +import com.jph.takephoto.model.InvokeParam; + +/** + * 授权管理回调 + */ +public interface InvokeListener { + PermissionManager.TPermissionType invoke(InvokeParam invokeParam); +} diff --git a/app/src/main/java/com/jph/takephoto/permission/PermissionManager.java b/app/src/main/java/com/jph/takephoto/permission/PermissionManager.java new file mode 100644 index 000000000..66bb30aba --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/permission/PermissionManager.java @@ -0,0 +1,157 @@ +package com.jph.takephoto.permission; + +import android.Manifest; +import android.app.Activity; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; +import android.widget.Toast; + +import com.jph.takephoto.app.TakePhoto; +import com.jph.takephoto.model.InvokeParam; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.uitl.TConstant; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.lang.reflect.Method; +import java.util.ArrayList; + +/** + * Created by penn on 16/9/22. + */ +public class PermissionManager { + public enum TPermission { + STORAGE(Manifest.permission.WRITE_EXTERNAL_STORAGE), + CAMERA(Manifest.permission.CAMERA); + String stringValue; + + TPermission(String stringValue) { + this.stringValue = stringValue; + } + + public String stringValue() { + return stringValue; + } + } + + public enum TPermissionType { + GRANTED("已授权"), + DENIED("未授权"), + WAIT("等待授权"), + NOT_NEED("无需授权"), + ONLY_CAMERA_DENIED("没有拍照权限"), + ONLY_STORAGE_DENIED("没有读写SD卡权限"); + String stringValue; + + TPermissionType(String stringValue) { + this.stringValue = stringValue; + } + + public String stringValue() { + return stringValue; + } + } + private final static String []methodNames={ + "onPickFromCapture", + "onPickFromCaptureWithCrop", + "onPickMultiple", + "onPickMultipleWithCrop", + "onPickFromDocuments", + "onPickFromDocumentsWithCrop", + "onPickFromGallery", + "onPickFromGalleryWithCrop", + "onCrop" + }; + /** + * 检查当前应用是否被授予相应权限 + * + * @param contextWrap + * @param method + * @return + */ + public static TPermissionType checkPermission(@NonNull TContextWrap contextWrap, @NonNull Method method) { + String methodName = method.getName(); + boolean contain=false; + for(int i=0,j=methodNames.length;i permissions = new ArrayList<>(); + if (!storageGranted) permissions.add(TPermission.STORAGE.stringValue()); + if (!cameraGranted) permissions.add(TPermission.CAMERA.stringValue()); + requestPermission(contextWrap,permissions.toArray(new String[permissions.size()])); + } + return granted ? TPermissionType.GRANTED : TPermissionType.WAIT; + } + + public static void requestPermission(@NonNull TContextWrap contextWrap, @NonNull String[] permissions) { + if(contextWrap.getFragment()!=null){ + contextWrap.getFragment().requestPermissions(permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO); + }else{ + ActivityCompat.requestPermissions(contextWrap.getActivity(), permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO); + } + } + + public static TPermissionType onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == TConstant.PERMISSION_REQUEST_TAKE_PHOTO) { + boolean cameraGranted = true, storageGranted = true; + for (int i = 0, j = permissions.length; i < j; i++) { + if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { + if (TextUtils.equals(TPermission.STORAGE.stringValue(),permissions[i])) { + storageGranted = false; + } else if (TextUtils.equals(TPermission.CAMERA.stringValue(),permissions[i])) { + cameraGranted = false; + } + } + } + if (cameraGranted && storageGranted) return TPermissionType.GRANTED; + if (!cameraGranted && storageGranted) return TPermissionType.ONLY_CAMERA_DENIED; + if (!storageGranted && cameraGranted) return TPermissionType.ONLY_STORAGE_DENIED; + if(!storageGranted&&!cameraGranted)return TPermissionType.DENIED; + } + return TPermissionType.WAIT; + } + public static void handlePermissionsResult(Activity activity, TPermissionType type, InvokeParam invokeParam, TakePhoto.TakeResultListener listener){ + String tip=null; + switch (type){ + case DENIED: + listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera_storage)); + break; + case ONLY_CAMERA_DENIED: + listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera)); + break; + case ONLY_STORAGE_DENIED: + listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_storage)); + break; + case GRANTED: + try { + invokeParam.getMethod().invoke(invokeParam.getProxy(),invokeParam.getArgs()); + } catch (Exception e) { + e.printStackTrace(); + listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera_storage)); + } + break; + default: + break; + } + if(tip!=null) + SingleToastUtil.showToastShort(tip); +// Toast.makeText(activity,tip,Toast.LENGTH_LONG).show(); + + } +} diff --git a/app/src/main/java/com/jph/takephoto/permission/TakePhotoInvocationHandler.java b/app/src/main/java/com/jph/takephoto/permission/TakePhotoInvocationHandler.java new file mode 100644 index 000000000..538b821ff --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/permission/TakePhotoInvocationHandler.java @@ -0,0 +1,41 @@ +package com.jph.takephoto.permission; + +import com.jph.takephoto.app.TakePhoto; +import com.jph.takephoto.model.InvokeParam; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public class TakePhotoInvocationHandler implements InvocationHandler{ + private TakePhoto delegate; + private InvokeListener listener; + public static TakePhotoInvocationHandler of(InvokeListener listener){ + return new TakePhotoInvocationHandler(listener); + } + + private TakePhotoInvocationHandler(InvokeListener listener) { + this.listener=listener; + } + + /** + * 绑定委托对象并返回一个代理类 + * @param delegate + * @return + */ + public Object bind(TakePhoto delegate) { + this.delegate = delegate; + return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this); + } + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + PermissionManager.TPermissionType type=listener.invoke(new InvokeParam(proxy,method,args)); + if(proxy instanceof TakePhoto){ + if(!PermissionManager.TPermissionType.NOT_NEED.equals(type)){ + ((TakePhoto)proxy).permissionNotify(type); + } + } + return method.invoke(delegate, args); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jph/takephoto/uitl/ImageRotateUtil.java b/app/src/main/java/com/jph/takephoto/uitl/ImageRotateUtil.java new file mode 100644 index 000000000..0c6f9b6bc --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/ImageRotateUtil.java @@ -0,0 +1,164 @@ +package com.jph.takephoto.uitl; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.media.ExifInterface; +import android.net.Uri; +import android.text.TextUtils; + +import com.netease.nim.uikit.common.util.log.LogUtil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * 图片旋转角度修正工具类 + * Author: crazycodeboy + * Date: 2016/9/21 0007 20:10 + * Version:3.0.0 + * 技术博文:http://www.cboy.me + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class ImageRotateUtil { + + public static ImageRotateUtil of(){ + return new ImageRotateUtil(); + } + + private ImageRotateUtil() { + } + + /** + * 纠正照片的旋转角度 + * @param path + */ + public void correctImage(Context context,Uri path){ + String imagePath = TUriParse.parseOwnUri(context, path); + int degree = getBitmapDegree(imagePath); + if (degree != 0) { + Bitmap bitmap = BitmapFactory.decodeFile(imagePath); + if (bitmap == null) return; + Bitmap resultBitmap = rotateBitmapByDegree(bitmap, degree); + if (resultBitmap == null) return; + try { + resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(imagePath))); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + } + } + + /** + * 纠正照片的旋转角度 + * @param imagePath 原图片路径 + * @param degree 旋转角度 + * @return 旋转后的图片路径 + */ + public String correctImage(String imagePath, int degree){ + String newImagePath = null; + if (degree != 0) { + Bitmap bitmap = BitmapFactory.decodeFile(imagePath); + if (bitmap == null) return null; + Bitmap resultBitmap = rotateBitmapByDegree(bitmap, degree); + if (resultBitmap == null) return null; + try { + newImagePath = getRotatePath(imagePath); + if (!TextUtils.isEmpty(newImagePath)) { + File file = new File(newImagePath); + if (file.exists()) { + file.delete(); + } + resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(newImagePath))); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + } + return newImagePath; + } + + private String getRotatePath(String sourcePath) { + if (TextUtils.isEmpty(sourcePath)) { + return null; + } + try { + int index = sourcePath.lastIndexOf("/"); + if (index >= 0) { + String dir = sourcePath.substring(0, index + 1); + String name = sourcePath.substring(index + 1); + return dir + "rotate_" + name; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + + } + + /** + * 读取图片的旋转的角度 + * + * @param path 图片绝对路径 + * @return 图片的旋转角度 + */ + public int getBitmapDegree(String path) { + int degree = 0; + try { + // 从指定路径下读取图片,并获取其EXIF信息 + ExifInterface exifInterface = new ExifInterface(path); + // 获取图片的旋转信息 + int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, + ExifInterface.ORIENTATION_NORMAL); + switch (orientation) { + case ExifInterface.ORIENTATION_ROTATE_90: + degree = 90; + break; + case ExifInterface.ORIENTATION_ROTATE_180: + degree = 180; + break; + case ExifInterface.ORIENTATION_ROTATE_270: + degree = 270; + break; + } + } catch (IOException e) { + e.printStackTrace(); + } + return degree; + } + + /** + * 将图片按照某个角度进行旋转 + * + * @param bm 需要旋转的图片 + * @param degree 旋转角度 + * @return 旋转后的图片 + */ + private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) { + Bitmap returnBm = null; + + // 根据旋转角度,生成旋转矩阵 + Matrix matrix = new Matrix(); + matrix.postRotate(degree); + try { + // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 + returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); + } catch (OutOfMemoryError e) { + } + if (returnBm == null) { + returnBm = bm; + } + if (bm != returnBm) { + bm.recycle(); + } + return returnBm; + } +} diff --git a/app/src/main/java/com/jph/takephoto/uitl/IntentUtils.java b/app/src/main/java/com/jph/takephoto/uitl/IntentUtils.java new file mode 100644 index 000000000..243265f84 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/IntentUtils.java @@ -0,0 +1,93 @@ +package com.jph.takephoto.uitl; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.provider.MediaStore; +import android.util.Log; + +import com.darsh.multipleimageselect.activities.AlbumSelectActivity; +import com.darsh.multipleimageselect.helpers.Constants; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.TContextWrap; + +/** + * Intent工具类用于生成拍照、 + * 从相册选择照片,裁剪照片所需的Intent + * Author: JPH + * Date: 2016/6/7 0007 13:41 + */ +public class IntentUtils { + private static final String TAG = IntentUtils.class.getName(); + + /** + * 获取图片多选的Intent + * @param limit 最多选择图片张数的限制 + * */ + public static Intent getPickMultipleIntent(TContextWrap contextWrap, int limit){ + Intent intent = new Intent(contextWrap.getActivity(), AlbumSelectActivity.class); + intent.putExtra(Constants.INTENT_EXTRA_LIMIT, limit>0? limit:1); + return intent; + } + + /** + * 获取裁剪照片的Intent + * @param targetUri 要裁剪的照片 + * @param outPutUri 裁剪完成的照片 + * @param options 裁剪配置 + * @return + */ + public static Intent getCropIntentWithOtherApp(Uri targetUri, Uri outPutUri, CropOptions options) { + boolean isReturnData = TUtils.isReturnData(); + Log.w(TAG, "getCaptureIntentWithCrop:isReturnData:" + (isReturnData ? "true" : "false")); + Intent intent = new Intent("com.android.camera.action.CROP"); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setDataAndType(targetUri, "image/*"); + intent.putExtra("crop", "true"); + if (options.getAspectX()*options.getAspectY()>0){ + intent.putExtra("aspectX", options.getAspectX()); + intent.putExtra("aspectY", options.getAspectY()); + } + if (options.getOutputX()*options.getOutputY()>0){ + intent.putExtra("outputX", options.getOutputX()); + intent.putExtra("outputY", options.getOutputY()); + } + intent.putExtra("scale", true); + intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri); + intent.putExtra("return-data", isReturnData); + intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); + intent.putExtra("noFaceDetection", true); // no face detection + return intent; + } + + /** + * 获取拍照的Intent + * @return + */ + public static Intent getCaptureIntent(Uri outPutUri) { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照 + intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);//将拍取的照片保存到指定URI + return intent; + } + /** + * 获取选择照片的Intent + * @return + */ + public static Intent getPickIntentWithGallery() { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_PICK);//Pick an item from the data + intent.setType("image/*");//从所有图片中进行选择 + return intent; + } + /** + * 获取从文件中选择照片的Intent + * @return + */ + public static Intent getPickIntentWithDocuments() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("image/*"); + return intent; + } +} diff --git a/app/src/main/java/com/jph/takephoto/uitl/TConstant.java b/app/src/main/java/com/jph/takephoto/uitl/TConstant.java new file mode 100644 index 000000000..6aa9ead74 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/TConstant.java @@ -0,0 +1,55 @@ +package com.jph.takephoto.uitl; + +import android.content.Context; + +/** + * 常量类 + * @author JPH + * Date 2016/6/7 0007 9:39 + */ +public class TConstant { + + + /** + * request Code 裁剪照片 + **/ + public final static int RC_CROP = 1001; + /** + * request Code 从相机获取照片并裁剪 + **/ + public final static int RC_PICK_PICTURE_FROM_CAPTURE_CROP = 1002; + /** + * request Code 从相机获取照片不裁剪 + **/ + public final static int RC_PICK_PICTURE_FROM_CAPTURE = 1003; + /** + * request Code 从文件中选择照片 + **/ + public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL = 1004; + /** + * request Code 从文件中选择照片并裁剪 + **/ + public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_CROP = 1005; + /** + * request Code 从相册选择照 + **/ + public final static int RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL = 1006; + /** + * request Code 从相册选择照片并裁剪 + **/ + public final static int RC_PICK_PICTURE_FROM_GALLERY_CROP = 1007; + /** + * request Code 选择多张照片 + **/ + public final static int RC_PICK_MULTIPLE = 1008; + + + /** + * requestCode 请求权限 + **/ + public final static int PERMISSION_REQUEST_TAKE_PHOTO = 2000; + + public final static String getFileProviderName(Context context){ + return context.getPackageName()+".fileprovider"; + } + } \ No newline at end of file diff --git a/app/src/main/java/com/jph/takephoto/uitl/TFileUtils.java b/app/src/main/java/com/jph/takephoto/uitl/TFileUtils.java new file mode 100644 index 000000000..90a17403b --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/TFileUtils.java @@ -0,0 +1,48 @@ +package com.jph.takephoto.uitl; + +import android.content.Context; +import android.util.Log; + +import java.io.File; + +/** + * Author: crazycodeboy + * Date: 2016/11/5 0007 20:10 + * Version:4.0.0 + * 技术博文:http://www.devio.org/ + * GitHub:https://github.com/crazycodeboy + * Eamil:crazycodeboy@gmail.com + */ +public class TFileUtils { + private static final String TAG="TFileUtils"; + private static String DEFAULT_DISK_CACHE_DIR = "takephoto_cache"; + public static File getPhotoCacheDir(Context context, File file) { + File cacheDir = context.getCacheDir(); + if (cacheDir != null) { + File mCacheDir = new File(cacheDir,DEFAULT_DISK_CACHE_DIR); + if (!mCacheDir.mkdirs() && (!mCacheDir.exists() || !mCacheDir.isDirectory())) { + return file; + }else { + return new File(mCacheDir, file.getName()); + } + } + if (Log.isLoggable(TAG, Log.ERROR)) { + Log.e(TAG, "default disk cache dir is null"); + } + return file; + } + + public static void delete(String path) { + try { + if(path == null) { + return ; + } + File file = new File(path); + if(!file.delete()) { + file.deleteOnExit(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/jph/takephoto/uitl/TImageFiles.java b/app/src/main/java/com/jph/takephoto/uitl/TImageFiles.java new file mode 100644 index 000000000..e1b849ff3 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/TImageFiles.java @@ -0,0 +1,154 @@ +package com.jph.takephoto.uitl; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; +import android.webkit.MimeTypeMap; +import android.widget.Toast; + +import com.jph.takephoto.model.TException; +import com.jph.takephoto.model.TExceptionType; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +/** + * ImageFiles工具类 + * + * @author JPH + * Date 2016/6/7 0007 9:39 + */ +public class TImageFiles { + private static final String TAG = IntentUtils.class.getName(); + + /** + * 将bitmap写入到文件 + * + * @param bitmap + */ + public static void writeToFile(Bitmap bitmap, Uri imageUri) { + if (bitmap == null) return; + File file = new File(imageUri.getPath()); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + fos.write(bos.toByteArray()); + bos.flush(); + fos.flush(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (fos != null) try { + fos.close(); + if (bos != null) bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * InputStream 转File + */ + public static void inputStreamToFile(InputStream is, File file) throws TException { + if (file == null) { + Log.i(TAG, "inputStreamToFile:file not be null"); + throw new TException(TExceptionType.TYPE_WRITE_FAIL); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + byte[] buffer = new byte[1024 * 10]; + int i; + while ((i = is.read(buffer)) != -1) { + fos.write(buffer, 0, i); + } + } catch (IOException e) { + Log.e(TAG, "InputStream 写入文件出错:" + e.toString()); + throw new TException(TExceptionType.TYPE_WRITE_FAIL); + } finally { + try { + fos.flush(); + fos.close(); + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 获取临时文件 + * + * @param context + * @param photoUri + * @return + */ + public static File getTempFile(Activity context, Uri photoUri) throws TException { + String minType = getMimeType(context, photoUri); + if (!checkMimeType(context, minType)) throw new TException(TExceptionType.TYPE_NOT_IMAGE); + File filesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); + if (!filesDir.exists()) filesDir.mkdirs(); + File photoFile = new File(filesDir, UUID.randomUUID().toString() + "." + minType); + return photoFile; + } + + /** + * 检查文件类型是否是图片 + * + * @param minType + * @return + */ + public static boolean checkMimeType(Context context, String minType) { + boolean isPicture = TextUtils.isEmpty(minType) ? false : ".jpg|.gif|.png|.bmp|.jpeg|.webp|".contains(minType.toLowerCase()) ? true : false; + if (!isPicture) + SingleToastUtil.showToastShort(R.string.tip_type_not_image); +// Toast.makeText(context, context.getResources().getText(R.string.tip_type_not_image), Toast.LENGTH_SHORT).show(); + return isPicture; + } + + /** + * To find out the extension of required object in given uri + * Solution by http://stackoverflow.com/a/36514823/1171484 + */ + public static String getMimeType(Activity context, Uri uri) { + String extension; + //Check uri format to avoid null + if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { + //If scheme is a content + extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri)); + if (TextUtils.isEmpty(extension)) + extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString()); + } else { + //If scheme is a File + //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters. + extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString()); + if (TextUtils.isEmpty(extension)) + extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri)); + } + if (TextUtils.isEmpty(extension)) { + File fileWithUri = TUriParse.getFileWithUri(uri, context); + if (fileWithUri != null) { + extension = getMimeTypeByFileName(fileWithUri.getName()); + } + } + return extension; + } + + public static String getMimeTypeByFileName(String fileName) { + return fileName.substring(fileName.lastIndexOf("."), fileName.length()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/jph/takephoto/uitl/TUriParse.java b/app/src/main/java/com/jph/takephoto/uitl/TUriParse.java new file mode 100644 index 000000000..ce93b4d76 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/TUriParse.java @@ -0,0 +1,205 @@ +package com.jph.takephoto.uitl; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.MediaStore; +import android.support.v4.content.FileProvider; +import android.text.TextUtils; +import android.util.Log; + +import com.jph.takephoto.model.TException; +import com.jph.takephoto.model.TExceptionType; + +import java.io.File; +import java.io.FileNotFoundException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + + +/** + * Uri解析工具类 + * Author: JPH + * Date: 2015/8/26 0026 16:23 + */ +public class TUriParse { + private static final String TAG = IntentUtils.class.getName(); + + /** + * 将scheme为file的uri转成FileProvider 提供的content uri + * + * @param context + * @param uri + * @return + */ + public static Uri convertFileUriToFileProviderUri(Context context, Uri uri) { + if (uri == null) return null; + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + return getUriForFile(context, new File(uri.getPath())); + } + return uri; + + } + + /** + * 获取一个临时的Uri, 文件名随机生成 + * + * @param context + * @return + */ + public static Uri getTempUri(Context context) { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); + File file = new File(Environment.getExternalStorageDirectory(), "/images/" + timeStamp + ".jpg"); + if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); + return getUriForFile(context, file); + } + + /** + * 获取一个临时的Uri, 通过传入字符串路径 + * + * @param context + * @param path + * @return + */ + public static Uri getTempUri(Context context, String path) { + File file = new File(path); + return getTempUri(context, file); + } + + /** + * 获取一个临时的Uri, 通过传入File对象 + * + * @param context + * @return + */ + public static Uri getTempUri(Context context, File file) { + if (!file.getParentFile().exists()) file.getParentFile().mkdirs(); + return getUriForFile(context, file); + } + + /** + * 创建一个用于拍照图片输出路径的Uri (FileProvider) + * + * @param context + * @return + */ + public static Uri getUriForFile(Context context, File file) { + return FileProvider.getUriForFile(context, TConstant.getFileProviderName(context), file); + } + + /** + * 将TakePhoto 提供的Uri 解析出文件绝对路径 + * + * @param uri + * @return + */ + public static String parseOwnUri(Context context, Uri uri) { + if (uri == null) return null; + String path; + if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(context))) { + String target_text_camera_photos = "camera_photos/"; + if (uri.getPath() != null && uri.getPath().contains(target_text_camera_photos)) { + path = new File(uri.getPath().replace(target_text_camera_photos, "")) + .getAbsolutePath(); + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + path = new File(Environment.getExternalStorageDirectory(), + uri.getPath()) + .getAbsolutePath(); + } else { + path = uri.getPath(); + } + } + + } else { + path = uri.getPath(); + } + Log.e(TAG, "parseOwnUri: path: " + path); + return path; + } + + /** + * 通过URI获取文件的路径 + * + * @param uri + * @param activity + * @return Author JPH + * Date 2016/6/6 0006 20:01 + */ + public static String getFilePathWithUri(Uri uri, Activity activity) throws TException { + if (uri == null) { + Log.w(TAG, "uri is null,activity may have been recovered?"); + throw new TException(TExceptionType.TYPE_URI_NULL); + } + File picture = getFileWithUri(uri, activity); + String picturePath = picture == null ? null : picture.getPath(); + if (TextUtils.isEmpty(picturePath)) + throw new TException(TExceptionType.TYPE_URI_PARSE_FAIL); + if (!TImageFiles.checkMimeType(activity, TImageFiles.getMimeType(activity, uri))) + throw new TException(TExceptionType.TYPE_NOT_IMAGE); + return picturePath; + } + + /** + * 通过URI获取文件 + * + * @param uri + * @param activity + * @return Author JPH + * Date 2016/10/25 + */ + public static File getFileWithUri(Uri uri, Activity activity) { + String picturePath = null; + String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { + String[] filePathColumn = {MediaStore.Images.Media.DATA}; + Cursor cursor = activity.getContentResolver().query(uri, + filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片 + if (cursor != null) { + cursor.moveToFirst(); + int columnIndex = cursor.getColumnIndex(filePathColumn[0]); + if (columnIndex >= 0) { + picturePath = cursor.getString(columnIndex); //获取照片路径 + } else if (TextUtils.equals(uri.getAuthority(), TConstant.getFileProviderName(activity))) { + picturePath = parseOwnUri(activity, uri); + } + cursor.close(); + } + } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { + picturePath = uri.getPath(); + } + return TextUtils.isEmpty(picturePath) ? null : new File(picturePath); + } + + /** + * 通过从文件中得到的URI获取文件的路径 + * + * @param uri + * @param activity + * @return Author JPH + * Date 2016/6/6 0006 20:01 + */ + public static String getFilePathWithDocumentsUri(Uri uri, Activity activity) throws TException { + if (uri == null) { + Log.e(TAG, "uri is null,activity may have been recovered?"); + return null; + } + if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && uri.getPath().contains("document")) { + File tempFile = TImageFiles.getTempFile(activity, uri); + try { + TImageFiles.inputStreamToFile(activity.getContentResolver().openInputStream(uri), tempFile); + return tempFile.getPath(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new TException(TExceptionType.TYPE_NO_FIND); + } + } else { + return getFilePathWithUri(uri, activity); + } + } +} diff --git a/app/src/main/java/com/jph/takephoto/uitl/TUtils.java b/app/src/main/java/com/jph/takephoto/uitl/TUtils.java new file mode 100644 index 000000000..cbb1ac613 --- /dev/null +++ b/app/src/main/java/com/jph/takephoto/uitl/TUtils.java @@ -0,0 +1,206 @@ +package com.jph.takephoto.uitl; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.support.v4.content.FileProvider; +import android.text.TextUtils; +import android.util.Log; +import android.widget.Toast; + +import com.darsh.multipleimageselect.models.Image; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TException; +import com.jph.takephoto.model.TExceptionType; +import com.jph.takephoto.model.TImage; +import com.jph.takephoto.model.TIntentWap; +import com.soundcloud.android.crop.Crop; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * 工具类 + * Author: JPH + * Date: 2016/7/26 10:04 + */ +public class TUtils { + private static final String TAG = IntentUtils.class.getName(); + + + /** + * 将Image集合转换成Uri集合 + * @param images + * @return + */ + public static ArrayList convertImageToUri(Context context,ArrayListimages) throws TException { + ArrayListuris=new ArrayList(); + for(Image image:images){ + uris.add(FileProvider.getUriForFile(context, TConstant.getFileProviderName(context), new File(image.path))); + } + return uris; + } + /** + * 将Image集合转换成TImage集合 + * @param images + * @return + */ + public static ArrayList getTImagesWithImages(ArrayListimages, TImage.FromType fromType){ + ArrayListtImages=new ArrayList(); + for(Image image:images){ + tImages.add(TImage.of(image.path, fromType)); + } + return tImages; + } + /** + * 将Uri集合转换成TImage集合 + * @param uris + * @return + */ + public static ArrayList getTImagesWithUris(ArrayListuris, TImage.FromType fromType){ + ArrayListtImages=new ArrayList(); + for(Uri uri:uris){ + tImages.add(TImage.of(uri, fromType)); + } + return tImages; + } + /** + * @param contextWrap + * @param intentWap + */ + public static void startActivityForResult(TContextWrap contextWrap, TIntentWap intentWap){ + if (contextWrap.getFragment()!=null){ + contextWrap.getFragment().startActivityForResult(intentWap.getIntent(),intentWap.getRequestCode()); + }else { + contextWrap.getActivity().startActivityForResult(intentWap.getIntent(),intentWap.getRequestCode()); + } + } + /** + * 安全地发送Intent + * @param contextWrap + * @param intentWapList 要发送的Intent以及候选Intent + * @param defaultIndex 默认发送的Intent + * @param isCrop 是否为裁切照片的Intent + * @throws TException + */ + public static void sendIntentBySafely(TContextWrap contextWrap, List intentWapList, int defaultIndex, boolean isCrop)throws TException { + if (defaultIndex+1>intentWapList.size())throw new TException(isCrop? TExceptionType.TYPE_NO_MATCH_PICK_INTENT: TExceptionType.TYPE_NO_MATCH_CROP_INTENT); + TIntentWap intentWap=intentWapList.get(defaultIndex); + List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(),PackageManager.MATCH_ALL); + if (result.isEmpty()){ + sendIntentBySafely(contextWrap,intentWapList,++defaultIndex,isCrop); + }else { + startActivityForResult(contextWrap,intentWap); + } + } + /** + * 拍照前检查是否有相机 + **/ + public static void captureBySafely(TContextWrap contextWrap, TIntentWap intentWap)throws TException { + List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(),PackageManager.MATCH_ALL); + if (result.isEmpty()){ +// Toast.makeText(contextWrap.getActivity(),contextWrap.getActivity().getResources().getText(R.string.tip_no_camera),Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.tip_no_camera); + throw new TException(TExceptionType.TYPE_NO_CAMERA); + }else { + startActivityForResult(contextWrap,intentWap); + } + } + /** + * 通过第三方工具裁切照片,当没有第三方裁切工具时,会自动使用自带裁切工具进行裁切 + * @param contextWrap + * @param imageUri + * @param outPutUri + * @param options + */ + public static void cropWithOtherAppBySafely(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options){ + Intent nativeCropIntent= IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri,options); + List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(nativeCropIntent,PackageManager.MATCH_ALL); + if (result.isEmpty()){ + cropWithOwnApp(contextWrap,imageUri,outPutUri,options); + }else { +// try { +// imageUri=Uri.fromFile(new File(TUriParse.getFilePathWithDocumentsUri(imageUri,contextWrap.getActivity()))); +// } catch (TException e) { +// e.printStackTrace(); +// } + startActivityForResult(contextWrap,new TIntentWap(IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri,options), TConstant.RC_CROP)); + } + } + /** + * 通过TakePhoto自带的裁切工具裁切图片 + * @param contextWrap + * @param imageUri + * @param outPutUri + * @param options + */ + public static void cropWithOwnApp(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options){ + if (options.getAspectX()*options.getAspectY()>0){ + if (contextWrap.getFragment()!=null){ + Crop.of(imageUri, outPutUri).withAspect(options.getAspectX(),options.getAspectY()).start(contextWrap.getActivity(),contextWrap.getFragment()); + }else { + Crop.of(imageUri, outPutUri).withAspect(options.getAspectX(),options.getAspectY()).start(contextWrap.getActivity()); + } + }else if (options.getOutputX()*options.getOutputY()>0){ + if (contextWrap.getFragment()!=null){ + Crop.of(imageUri, outPutUri).withMaxSize(options.getOutputX(),options.getOutputY()).start(contextWrap.getActivity(),contextWrap.getFragment()); + }else { + Crop.of(imageUri, outPutUri).withMaxSize(options.getOutputX(),options.getOutputY()).start(contextWrap.getActivity()); + } + }else { + if (contextWrap.getFragment()!=null){ + Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity(),contextWrap.getFragment()); + }else { + Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity()); + } + } + } + /** + * 是否裁剪之后返回数据 + **/ + public static boolean isReturnData() { + String release= Build.VERSION.RELEASE; + int sdk= Build.VERSION.SDK_INT; + Log.i(TAG,"release:"+release+"sdk:"+sdk); + String manufacturer = Build.MANUFACTURER; + if (!TextUtils.isEmpty(manufacturer)) { + if (manufacturer.toLowerCase().contains("lenovo")) {//对于联想的手机返回数据 + return true; + } + } +// if (sdk>=21){//5.0或以上版本要求返回数据 +// return true; +// } + return false; + } + /** + * 显示圆形进度对话框 + * + * @author JPH + * Date 2014-12-12 下午7:04:09 + * @param activity + * @param progressTitle + * 显示的标题 + * @return + */ + public static ProgressDialog showProgressDialog(final Activity activity, + String... progressTitle) { + if(activity==null||activity.isFinishing())return null; + String title = activity.getResources().getString(R.string.tip_tips); + if (progressTitle != null && progressTitle.length > 0) + title = progressTitle[0]; + ProgressDialog progressDialog = new ProgressDialog(activity); + progressDialog.setTitle(title); + progressDialog.setCancelable(false); + progressDialog.show(); + return progressDialog; + } +} diff --git a/app/src/main/java/com/wudoo/qingxun/wxapi/WXEntryActivity.java b/app/src/main/java/com/wudoo/qingxun/wxapi/WXEntryActivity.java new file mode 100644 index 000000000..496b8f2d4 --- /dev/null +++ b/app/src/main/java/com/wudoo/qingxun/wxapi/WXEntryActivity.java @@ -0,0 +1,26 @@ +package com.wudoo.qingxun.wxapi; + +import android.content.Intent; + + +import cn.sharesdk.wechat.utils.WXMediaMessage; +import cn.sharesdk.wechat.utils.WechatHandlerActivity; + +/** + * create by lvzebiao @2019/11/8 + */ +public class WXEntryActivity extends WechatHandlerActivity { + + @Override + public void onShowMessageFromWXReq(WXMediaMessage msg) { + super.onShowMessageFromWXReq(msg); + } + + @Override + public void onGetMessageFromWXReq(WXMediaMessage msg) { + super.onGetMessageFromWXReq(msg); + //从小程序返回APP + Intent iLaunchMyself = getPackageManager().getLaunchIntentForPackage(getPackageName()); + startActivity(iLaunchMyself); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ErbanTakePhotoActivity.java b/app/src/main/java/com/yizhuan/erban/ErbanTakePhotoActivity.java new file mode 100644 index 000000000..21bf0c493 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ErbanTakePhotoActivity.java @@ -0,0 +1,174 @@ +package com.yizhuan.erban; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +import com.jph.takephoto.app.TakePhotoActivity; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.TResult; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; + +import java.io.File; + +public class ErbanTakePhotoActivity extends TakePhotoActivity { + private static final String CAMERA_PREFIX = "picture_"; + private static final int REQ_CODE = 1000; + + private static TakePhotoCallBack takePhotoCallBack; + + public final static String OPERATION_TYPE = "OPERATION_TYPE"; + public final static int SELECT_PHOTO = 1; + public final static int TAKE_PHOTO = 2; + public final static int SELECT_MULTIPLE_PHOTO = 3; + public final static String MULTIPLE_SELECT_PHOTO_LIMIT = "MULTIPLE_SELECT_PHOTO_LIMIT"; + + + /** + * 选择一张图片 + * @param context + */ + public static void startToSelectPhoto(Context context, TakePhotoCallBack callBack) { + Bundle bundle = new Bundle(); + bundle.putInt(OPERATION_TYPE, SELECT_PHOTO); + start(context, bundle, callBack); + } + + /** + * 选择多张图片 + * @param context + * @param limit + */ + public static void startToMultipleSelectPhoto(Context context, TakePhotoCallBack callBack, int limit){ + Bundle bundle = new Bundle(); + bundle.putInt(OPERATION_TYPE, SELECT_MULTIPLE_PHOTO); + bundle.putInt(MULTIPLE_SELECT_PHOTO_LIMIT, limit); + start(context, bundle, callBack); + } + + /** + * 照相 + * @param context + */ + public static void startToTakePhoto(Context context, TakePhotoCallBack callBack){ + Bundle bundle = new Bundle(); + bundle.putInt(OPERATION_TYPE,TAKE_PHOTO); + start(context, bundle, callBack); + } + + private static void start(Context context, Bundle bundle, TakePhotoCallBack callBack){ + takePhotoCallBack = callBack; + Intent intent = new Intent(context, ErbanTakePhotoActivity.class); + intent.putExtras(bundle); + context.startActivity(intent); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + int operationType = getIntent().getIntExtra(OPERATION_TYPE, SELECT_PHOTO); + int limit = getIntent().getIntExtra(MULTIPLE_SELECT_PHOTO_LIMIT,1); + if (operationType == SELECT_PHOTO){ + selectPhoto(); + } else if (operationType == TAKE_PHOTO){ + checkPermissionAndStartCamera(); + } else if (operationType == SELECT_MULTIPLE_PHOTO){ + multipleSelectPhoto(limit); + } + } + + @Override + protected void onDestroy() { + takePhotoCallBack = null; + super.onDestroy(); + } + + @Override + public void takeSuccess(TResult result) { + if (takePhotoCallBack != null){ + takePhotoCallBack.takeSuccess(result); + } + finish(); + } + @Override + public void takeFail(TResult result, String msg) { + if (takePhotoCallBack != null){ + takePhotoCallBack.takeFail(result,msg); + } + finish(); + } + @Override + public void takeCancel() { + if (takePhotoCallBack != null){ + takePhotoCallBack.takeCancel(); + } + finish(); + } + + + private void selectPhoto(){ + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(ErbanTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, true); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromGalleryWithCrop(uri, options); + } + + + private void multipleSelectPhoto(int limit){ + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(ErbanTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, true); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickMultipleWithCrop(limit, options); + } + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(checkPermissionListener, R.string.ask_camera, android.Manifest.permission.CAMERA); + } + + PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() { + @Override + public void superPermission() { + takePhoto(); + } + }; + + private void takePhoto() { + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(ErbanTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, false); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromCaptureWithCrop(uri, options); + } + + + public interface TakePhotoCallBack{ + public void takeSuccess(TResult result); + public void takeFail(TResult result, String msg); + public void takeCancel(); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/GuideAdapter.java b/app/src/main/java/com/yizhuan/erban/GuideAdapter.java new file mode 100644 index 000000000..247679abd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/GuideAdapter.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/7/12 0012. + */ + +public class GuideAdapter extends PagerAdapter { + private List mData=new ArrayList(); + public GuideAdapter(Context context){ + initData(context); + } + + //取得适配器装配的数据 + public List getData(){ + return mData; + } + //添加视图项 + public void addItem(ImageView imageView){ + mData.add(imageView); + } + + //初始化视图项的数据 + private void initData(Context context) { + ImageView imageView=new ImageView(context); +// imageView.setImageResource(resId);//设置ImageView的前景图片 +// imageView.setBackgroundResource(R.drawable.guide_one);//设置背景 + mData.add(imageView); + imageView=new ImageView(context); +// imageView.setBackgroundResource(R.drawable.guide_two);//设置背景 + mData.add(imageView); + imageView=new ImageView(context); +// imageView.setBackgroundResource(R.drawable.guide_three);//设置背景 + mData.add(imageView); + + } + //取得视图项的数量 + @Override + public int getCount() { + return mData.size(); + } + @Override + public boolean isViewFromObject(View arg0, Object arg1) { + return arg0==arg1; + } + //销毁视图项 + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + //从父控件中移除子控件 + container.removeView((View)object); + } + //初始化视图项 + @Override + public Object instantiateItem(ViewGroup container, int position) { + //容器(ViewPager--它是ViewGroup的子类) + container.addView(mData.get(position)); + return mData.get(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/MainActivity.java b/app/src/main/java/com/yizhuan/erban/MainActivity.java new file mode 100644 index 000000000..c437f5a96 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/MainActivity.java @@ -0,0 +1,1289 @@ +package com.yizhuan.erban; + +import android.Manifest; +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.text.TextUtils; +import android.util.Log; +import android.util.LongSparseArray; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; +import android.view.animation.LinearInterpolator; + +import com.mcxiaoke.packer.helper.PackerNg; +import com.microquation.linkedme.android.LinkedME; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.model.contact.ContactEventListener; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.api.model.session.SessionEventListener; +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.actions.ImageAction; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.impl.cache.NimUserInfoCache; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.orhanobut.logger.Logger; +import com.qiyukf.unicorn.api.Unicorn; +import com.tencent.bugly.crashreport.CrashReport; +import com.tongdaxing.erban.upgrade.AppUpgradeHelper; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.application.ActivityStackManager; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.ktv.KtvMusicManager; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.DragLayout; +import com.yizhuan.erban.common.widget.FloatingLiveMiniView; +import com.yizhuan.erban.community.dynamic.view.DynamicDetailActivity; +import com.yizhuan.erban.community.holder.DynamicSysHolder; +import com.yizhuan.erban.community.im.WorldDynamicShareViewHolder; +import com.yizhuan.erban.community.publish.view.PublishActivity; +import com.yizhuan.erban.decoration.view.widgets.ShowCarGuideDialog; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.guide.GuideActivity; +import com.yizhuan.erban.home.dialog.RecommendRoomForNewerDialog; +import com.yizhuan.erban.home.fragment.FindTabFragment; +import com.yizhuan.erban.home.fragment.GameHomeFragment; +import com.yizhuan.erban.home.fragment.MeFragment; +import com.yizhuan.erban.home.fragment.MsgFragment; +import com.yizhuan.erban.home.fragment.RankingFragment; +import com.yizhuan.erban.home.presenter.MainPresenter; +import com.yizhuan.erban.home.view.IMainView; +import com.yizhuan.erban.luckymoney.viewholder.LuckyMoneyMsgViewHolder; +import com.yizhuan.erban.luckymoney.viewholder.LuckyMoneyTipsViewHolder; +import com.yizhuan.erban.miniworld.activity.MiniWorldGuestPageActivity; +import com.yizhuan.erban.module.Extras; +import com.yizhuan.erban.module_hall.HallDataManager; +import com.yizhuan.erban.module_hall.secretcode.PwdCodeMgr; +import com.yizhuan.erban.public_chat_hall.msg.viewholder.MsgViewHolderAitMe; +import com.yizhuan.erban.radish.signin.SignDialogTimeManager; +import com.yizhuan.erban.service.DaemonService; +import com.yizhuan.erban.treasure_box.service.OpenBoxService; +import com.yizhuan.erban.share.viewholder.InAppSharingMsgViewHolder; +import com.yizhuan.erban.treasure_box.service.OpenHonourBoxService; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.im.actions.ChatterBoxAction; +import com.yizhuan.erban.ui.im.actions.DecorationAction; +import com.yizhuan.erban.ui.im.actions.GiftAction; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.im.chat.MVHChatterBoxInit; +import com.yizhuan.erban.ui.im.chat.MVHChatterBoxStart; +import com.yizhuan.erban.ui.im.chat.MVHDiceThrow; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderAudioParty; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderContent; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderGame; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderGift; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderLevel; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderLottery; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderOnline; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderRedPacket; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderText; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderTip; +import com.yizhuan.erban.ui.im.chat.MsgViewHolderVoiceBottleSayHi; +import com.yizhuan.erban.ui.im.chat.SignInNoticeMsgViewHolder; +import com.yizhuan.erban.ui.im.chat.SysMsgViewHolder; +import com.yizhuan.erban.ui.im.chat.SysMsgVoiceViewHolder; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.login.LoginActivity; +import com.yizhuan.erban.ui.patriarch.help.LimitEnterRoomHelper; +import com.yizhuan.erban.ui.patriarch.help.PmDialogShowMrg; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.LevelUpDialog; +import com.yizhuan.erban.ui.widget.LivingIconView; +import com.yizhuan.erban.ui.widget.MainTabLayout; +import com.yizhuan.erban.ui.widget.RecallDialog; +import com.yizhuan.erban.ui.widget.RedPacketDialog; +import com.yizhuan.erban.utils.CleanLeakUtils; +import com.yizhuan.tutu.mentoring_relationship.viewholder.ApprenticeMissionFourViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.ApprenticeMissionOneViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.ApprenticeMissionThreeViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.ApprenticeMissionTwoViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MasterMissionFourViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MasterMissionOneViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MasterMissionThreeViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MasterMissionTwoViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MentoringSharingRoomViewHolder; +import com.yizhuan.tutu.mentoring_relationship.viewholder.MentoringTipsViewHolder; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.community.event.SquareTaskEvent; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.KickOutEvent; +import com.yizhuan.xchat_android_core.auth.event.LoginEvent; +import com.yizhuan.xchat_android_core.auth.event.LogoutEvent; +import com.yizhuan.xchat_android_core.channel_page.bean.ChannelPageInfo; +import com.yizhuan.xchat_android_core.channel_page.model.ChannelPageModel; +import com.yizhuan.xchat_android_core.community.attachment.DynamicSysAttachment; +import com.yizhuan.xchat_android_core.community.event.UnReadCountEvent; +import com.yizhuan.xchat_android_core.community.im.WorldDynamicAttachment; +import com.yizhuan.xchat_android_core.customer_server.event.CustomerServerMsgEvent; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.im.custom.bean.AssistantAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarveUpGoldThirdLevelAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ChatterBoxAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ChatterBoxInitAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.DiceThrowAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingFamilyAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingMiniWorldAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingRoomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingTeamAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LevelUpAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LotteryAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyTipsAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NoticeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenRoomNotiAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RedPacketAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.SysMsgAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.SysMsgVoiceAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.VoiceBottleSayHiAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.VoiceBottleShakeHeartAttachment; +import com.yizhuan.xchat_android_core.level.event.CharmLevelUpEvent; +import com.yizhuan.xchat_android_core.level.event.LevelUpEvent; +import com.yizhuan.xchat_android_core.linked.bean.LinkedInfo; +import com.yizhuan.xchat_android_core.linked.event.LinkMeInfoUpdateEvent; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMBroadcastManager; +import com.yizhuan.xchat_android_core.manager.IMMessageManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.market_verify.event.MarketVerifyUpdateEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringApprenticeMissionFourAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringApprenticeMissionOneAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringApprenticeMissionThreeAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringApprenticeMissionTwoAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringMasterMissionFourAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringMasterMissionOneAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringMasterMissionThreeAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringMasterMissionTwoAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringMissionTipsAttachment; +import com.yizhuan.xchat_android_core.mentoring_relationship.attachment.MentoringSharingRoomAttachment; +import com.yizhuan.xchat_android_core.miniworld.bean.OpenAudioPartyAttachment; +import com.yizhuan.xchat_android_core.patriarch.event.CloseMinRoomEvent; +import com.yizhuan.xchat_android_core.patriarch.event.ImPushMsgPmLimitTimeEvent; +import com.yizhuan.xchat_android_core.patriarch.event.PmDismissAllLimitDialogEvent; +import com.yizhuan.xchat_android_core.public_chat_hall.attachment.AitMeAttachment; +import com.yizhuan.xchat_android_core.recall.RecallModel; +import com.yizhuan.xchat_android_core.recall.bean.CheckLostUserInfo; +import com.yizhuan.xchat_android_core.recall.event.CheckLostUserEvent; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfoV2; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserRecommendRoomInfo; +import com.yizhuan.xchat_android_core.user.event.CurrentUserInfoCompleteEvent; +import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_core.user.event.NeedBindPhoneEvent; +import com.yizhuan.xchat_android_core.user.event.NeedCompleteInfoEvent; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.threadmgr.ThreadPoolManager; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; +import com.yizhuan.xchat_android_library.utils.pref.CommonPref; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +import static com.yizhuan.xchat_android_core.Constants.SHOW_CAR_GUIDE; + +/** + * @author Administrator + */ +@CreatePresenter(MainPresenter.class) +public class MainActivity extends BaseMvpActivity + implements MainTabLayout.OnTabClickListener, IMainView { + + private static final String TAG = "MainActivity"; + + private static final String EXTRA_APP_QUIT = "APP_QUIT"; + public static final String MSG_TAB = "msgTab"; + + private DragLayout avatarLayout; + private CircleImageView avatarImage; + private LivingIconView userLivingView; + private View viewClose; + + private FloatingLiveMiniView floatingLiveMiniView; + + private MainTabLayout mMainTabLayout; + private int mCurrentMainPosition = MainTabLayout.MAIN_TAB_POS_GAME; + /** + * 是否需要预加载home,by lvzebiao v3.1.2 + * 因为首页标签添加帧动画,防止,第一次点击标签过于卡顿 + */ + private final static boolean PRELOAD_HOME = false; + + /** + * 保存登录的次数 + */ + private LongSparseArray loginCountMap = new LongSparseArray<>(1); + + /** + * 房间最小化动画,换成属性动画,原先的补间动画影响了activity的生命周期 + */ + private ObjectAnimator roomMinAnim; + /** + * 管理限制进房 + */ + private LimitEnterRoomHelper limitEnterRoomHelper; + + + public static void start(Context context) { + start(context, null); + } + + public static void start(Context context, Intent extras) { + Intent intent = new Intent(); + intent.setClass(context, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + if (extras != null) { + intent.putExtras(extras); + } + context.startActivity(intent); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(Constants.KEY_MAIN_POSITION, mCurrentMainPosition); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState != null) { + mCurrentMainPosition = savedInstanceState.getInt(Constants.KEY_MAIN_POSITION); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + mCurrentMainPosition = savedInstanceState.getInt(Constants.KEY_MAIN_POSITION); + } + Log.e(TAG, "onCreate: " + DESUtils.DESAndBase64("112030")); + setContentView(R.layout.activity_main); + //自动登录 + AuthModel.get().autoLogin().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + } + + @Override + public void onSuccess(String s) { + } + + @Override + public void onError(Throwable e) { + onNeedLogin(); + toast(e.getMessage()); + } + }); + + initTitleBar(getString(R.string.app_name)); + initView(); + startGuild(); + initMaterialView(); + permission(); + onParseIntent(); + updateDatas(); + updateRoomState(); + initP2PSessionCustomization(); + initTeamSessionCustomization(); + EventBus.getDefault().register(this); + otherModelInit(); + + } + + private void otherModelInit() { + PwdCodeMgr.get().onCreateInit(); + //初始化线程池 + ThreadPoolManager.instance().init(); + IMBroadcastManager.get().onCreate(); + ImageLoadUtilsV2.init(context); + } + + @Override + protected void onReceiveChatRoomEvent(RoomEvent roomEvent) { + super.onReceiveChatRoomEvent(roomEvent); + if (roomEvent == null || roomEvent.getEvent() == RoomEvent.NONE) return; + int event = roomEvent.getEvent(); + if (event == RoomEvent.ENTER_ROOM) { + onEnter(AvRoomDataManager.get().mCurrentRoomInfo); + } else if (event == RoomEvent.KICK_OUT_ROOM) { + + ChatRoomKickOutEvent reason = roomEvent.getReason(); + if (reason == null) return; + //加入黑名单,踢出房间回调 + ChatRoomKickOutEvent.ChatRoomKickOutReason reasonReason = reason.getReason(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.USER_KICKED_EVENT,"用户被踢"); + if (reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.BE_BLACKLISTED + || reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.KICK_OUT_BY_MANAGER + || reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.KICK_OUT_BY_CONFLICT_LOGIN + || reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + exitRoom(AvRoomDataManager.get().mCurrentRoomInfo); + } + } else if (event == RoomEvent.ROOM_EXIT) { + exitRoom(roomEvent.getRoomInfo()); + } else if (event == RoomEvent.ROOM_CHAT_RECONNECTION) { + updateRoomState(); + } else if (event == RoomEvent.MY_SELF_KICK_OUT_ROOM_BY_S_ADMIN) { + toast(R.string.kick_out_room_by_s_admin); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.USER_KICKED_EVENT,"用户被踢"); + getMvpPresenter().exitRoom(); + } + } + + private void closeOpenRoomAnimation() { + stopRoomMinAnim(); + avatarLayout.setVisibility(View.GONE); + } + + private void initP2PSessionCustomization() { + SessionCustomization sessionCustomization = new SessionCustomization(); + ArrayList actions = new ArrayList<>(); + actions.add(new ImageAction()); + actions.add(new DecorationAction()); + actions.add(new ChatterBoxAction()); + actions.add(new GiftAction()); + sessionCustomization.actions = actions; + sessionCustomization.withSticker = true; + NimUIKit.setCommonP2PSessionCustomization(sessionCustomization); + + // 语音派对 + NimUIKit.registerMsgItemViewHolder(OpenAudioPartyAttachment.class, MsgViewHolderAudioParty.class); + + NimUIKit.registerMsgItemViewHolder(OpenRoomNotiAttachment.class, MsgViewHolderOnline.class); + NimUIKit.registerMsgItemViewHolder(GiftAttachment.class, MsgViewHolderGift.class); + NimUIKit.registerMsgItemViewHolder(NoticeAttachment.class, MsgViewHolderContent.class); + NimUIKit.registerMsgItemViewHolder(RedPacketAttachment.class, MsgViewHolderRedPacket.class); + NimUIKit.registerMsgItemViewHolder(LotteryAttachment.class, MsgViewHolderLottery.class); + NimUIKit.registerMsgItemViewHolder(NobleAttachment.class, MsgViewHolderText.class); + NimUIKit.registerMsgItemViewHolder(CarAttachment.class, MsgViewHolderText.class); + NimUIKit.registerMsgItemViewHolder(AssistantAttachment.class, MsgViewHolderText.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingRoomAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingFamilyAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingMiniWorldAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingTeamAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(SysMsgAttachment.class, SysMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(LevelUpAttachment.class, MsgViewHolderLevel.class); + NimUIKit.registerMsgItemViewHolder(AitMeAttachment.class, MsgViewHolderAitMe.class); + // 声音瓶子 + NimUIKit.registerMsgItemViewHolder(SysMsgVoiceAttachment.class, SysMsgVoiceViewHolder.class); + NimUIKit.registerMsgItemViewHolder(VoiceBottleSayHiAttachment.class, MsgViewHolderVoiceBottleSayHi.class); + NimUIKit.registerMsgItemViewHolder(VoiceBottleShakeHeartAttachment.class, MsgViewHolderText.class); + // 师徒关系-师父看到的任务 + NimUIKit.registerMsgItemViewHolder(MentoringMasterMissionOneAttachment.class, MasterMissionOneViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringMasterMissionTwoAttachment.class, MasterMissionTwoViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringMasterMissionThreeAttachment.class, MasterMissionThreeViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringMasterMissionFourAttachment.class, MasterMissionFourViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringSharingRoomAttachment.class, MentoringSharingRoomViewHolder.class); + // 师徒关系-徒弟看到的任务 + NimUIKit.registerMsgItemViewHolder(MentoringApprenticeMissionOneAttachment.class, ApprenticeMissionOneViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringApprenticeMissionTwoAttachment.class, ApprenticeMissionTwoViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringApprenticeMissionThreeAttachment.class, ApprenticeMissionThreeViewHolder.class); + NimUIKit.registerMsgItemViewHolder(MentoringApprenticeMissionFourAttachment.class, ApprenticeMissionFourViewHolder.class); + // 师徒关系-提示消息 + NimUIKit.registerMsgItemViewHolder(MentoringMissionTipsAttachment.class, MentoringTipsViewHolder.class); + NimUIKit.registerMsgItemViewHolder(ImGameAttachment.class, MsgViewHolderGame.class); + NimUIKit.registerMsgItemViewHolder(ImTipAttachment.class, MsgViewHolderTip.class); + //模厅模块 + HallDataManager.get().mainNimOnCreate(); + //签到 + NimUIKit.registerMsgItemViewHolder(OpenSignInAttachment.class, SignInNoticeMsgViewHolder.class); + //瓜分金币 三级 + NimUIKit.registerMsgItemViewHolder(CarveUpGoldThirdLevelAttachment.class, MsgViewHolderText.class); + // 话匣子 + NimUIKit.registerMsgItemViewHolder(ChatterBoxAttachment.class, MVHChatterBoxStart.class); + NimUIKit.registerMsgItemViewHolder(DiceThrowAttachment.class, MVHDiceThrow.class); + NimUIKit.registerMsgItemViewHolder(ChatterBoxInitAttachment.class, MVHChatterBoxInit.class); + + // 社区动态 + NimUIKit.registerMsgItemViewHolder(DynamicSysAttachment.class, DynamicSysHolder.class); // 动态审核, 违规删除 + //世界动态分享 + NimUIKit.registerMsgItemViewHolder(WorldDynamicAttachment.class, WorldDynamicShareViewHolder.class); + + NimUIKit.setSessionListener(listener); + NimUIKit.setContactEventListener(listener1); + } + + private void initTeamSessionCustomization() { + SessionCustomization sessionCustomization = new SessionCustomization(); + ArrayList actions = new ArrayList<>(); + actions.add(new ImageAction()); + sessionCustomization.actions = actions; + sessionCustomization.withSticker = true; + NimUIKit.setCommonTeamSessionCustomization(sessionCustomization); + + NimUIKit.registerMsgItemViewHolder(LuckyMoneyAttachment.class, LuckyMoneyMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingRoomAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingFamilyAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingMiniWorldAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(InAppSharingTeamAttachment.class, InAppSharingMsgViewHolder.class); + NimUIKit.registerMsgItemViewHolder(LuckyMoneyTipsAttachment.class, LuckyMoneyTipsViewHolder.class); + + NimUIKit.setSessionListener(listener); + NimUIKit.setContactEventListener(listener1); + } + + private ContactEventListener listener1 = new ContactEventListener() { + @Override + public void onItemClick(Context context, String account) { + NimP2PMessageActivity.start(context, account); + } + + @Override + public void onItemLongClick(Context context, String account) { + + } + + @Override + public void onAvatarClick(Context context, String account) { + UserInfoActivity.Companion.start(MainActivity.this, Long.valueOf(account)); + } + }; + + private SessionEventListener listener = new SessionEventListener() { + @Override + public void onAvatarClicked(Context context, IMMessage message) { + switch (message.getSessionType()) { + case Team: + UserInfoActivity.Companion.start(MainActivity.this, Long.valueOf(message.getFromAccount())); + break; + + default: + case P2P: + UserInfoActivity.Companion.start(MainActivity.this, Long.valueOf(message.getFromAccount())); + break; + } + } + + @Override + public void onAvatarLongClicked(Context context, IMMessage message) { + + } + }; + + + @Override + protected void onResume() { + super.onResume(); + LinkedME.getInstance().setImmediate(true); + if (avatarLayout.getVisibility() == View.VISIBLE) { + userLivingView.start(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (avatarLayout.getVisibility() == View.VISIBLE) { + userLivingView.stop(); + } + } + + private void initView() { + mMainTabLayout = findViewById(R.id.main_tab_layout); + avatarLayout = findViewById(R.id.avatar_image_layout); + avatarImage = findViewById(R.id.avatar_image); + userLivingView = findViewById(R.id.liv_user); + viewClose = findViewById(R.id.view_close); +// floatingLiveMiniView = findViewById(R.id.floating_view); + + userLivingView.setColor(Color.WHITE); + mMainTabLayout.setOnTabClickListener(this); + + } + + + private void updateDatas() { + if ("baidutg".equals(PackerNg.getChannel(this))) { + mMainTabLayout.select(MainTabLayout.MAIN_TAB_POS_HOME); + } else { + mMainTabLayout.select(mCurrentMainPosition); + } + handleNimIntent(); + } + + + @Override + protected void onNewIntent(Intent intent) { + setIntent(intent); + //这里退出登录,实际上mainActivity是没有销毁的,当从linkme 调起来时候这里需要检查一下登录状态。 + if (TextUtils.isEmpty(AuthModel.get().getTicket())) { + onNeedLogin(); + return; + } + onParseIntent(); + handleNimIntent(); + } + + private long startTime; + private boolean shown; + + private void onParseIntent() { + Intent intent = getIntent(); + if (intent.hasExtra(EXTRA_APP_QUIT)) { + onLogout(); + } else if (intent.hasExtra(Extras.EXTRA_JUMP_P2P)) { + Intent data = intent.getParcelableExtra(Extras.EXTRA_DATA); + String account = data.getStringExtra(Extras.EXTRA_ACCOUNT); + if (!TextUtils.isEmpty(account)) { + NimP2PMessageActivity.start(this, account); + } + } else if (intent.hasExtra("url") && intent.hasExtra("type")) { + startTime = System.currentTimeMillis(); + } else if (intent.hasExtra("gameTab") && intent.getBooleanExtra("gameTab", false)) { + if (mMainTabLayout != null) { + mMainTabLayout.select(MainTabLayout.MAIN_TAB_POS_GAME); + } + } else if (intent.hasExtra(MSG_TAB) && intent.getBooleanExtra(MSG_TAB, false)) { + if (mMainTabLayout != null) { + mMainTabLayout.select(MainTabLayout.MAIN_TAB_POS_MSG); + } + } + } + + private void initMaterialView() { + avatarLayout.setVisibility(View.GONE); + avatarImage.setOnClickListener(v -> { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + if (AvRoomDataManager.get().isParty()) { + AVRoomActivity.start(MainActivity.this, true); + }else { + AVRoomActivity.start(MainActivity.this, roomInfo.getUid()); + } + } else { + toast("-房间信息为空-"); + } + }); + + viewClose.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_MINIMIZE_CLOSED, + "房间最小化关闭按钮"); + MainActivity.this.getMvpPresenter().exitRoom(); + } + ); + + } + + private void permission() { + checkPermission(() -> { + }, R.string.ask_again, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE); + } + + @Override + protected void onDestroy() { + CleanLeakUtils.fixInputMethodManagerLeak(MainActivity.this); + super.onDestroy(); + listener = null; + listener1 = null; + NimUIKit.setSessionListener(null); + NimUIKit.setContactEventListener(null); + + EventBus.getDefault().unregister(this); + stopRoomMinAnim(); + if (limitEnterRoomHelper != null) { + limitEnterRoomHelper.release(); + } + IMBroadcastManager.get().onDestroy(); + + } + + /** + * 双击返回键退出 + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { +// if (keyCode == KeyEvent.KEYCODE_BACK) { +// moveTaskToBack(true); +// return true; +// } +// return super.onKeyDown(keyCode, event); + + if (keyCode == KeyEvent.KEYCODE_BACK) { + + /** + * 防止华为机型未加入白名单时按返回键回到桌面再锁屏后几秒钟进程被杀 + */ + try { + Intent launcherIntent = new Intent(Intent.ACTION_MAIN); + launcherIntent.addCategory(Intent.CATEGORY_HOME); + startActivity(launcherIntent); + } catch (Throwable e) { + e.printStackTrace(); + } + + try { + moveTaskToBack(false); + } catch (Exception e) { + return super.onKeyDown(keyCode, event); + } + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onBackPressed() { + try { + moveTaskToBack(false); + } catch (Exception e) { + e.printStackTrace(); + } +// moveTaskToBack(true); +// super.onBackPressed(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLinkMeInfoUpdateEvent(LinkMeInfoUpdateEvent event) { + LinkedInfo linkedInfo = event.getLinkedInfo(); + if (linkedInfo == null || linkedInfo.getType() == null) { + return; + } + + LogUtil.print("linkedme跳转"); + handleChannelPageInfo(true) + .doOnError(throwable -> { + // 跳转 + if (!StringUtil.isEmpty(linkedInfo.getRoomUid()) && linkedInfo.getType().equals("2")) { + AVRoomActivity.start(this, Long.valueOf(linkedInfo.getRoomUid())); + } else if (!StringUtil.isEmpty(linkedInfo.getFamilyId()) && linkedInfo.getType().equals("4")) { + FamilyHomeActivity.start(this, linkedInfo.getFamilyId()); + } else if (!TextUtils.isEmpty(linkedInfo.getUrl()) && linkedInfo.getType().equals("3")) { + CommonWebViewActivity.start(context, UriProvider.getLinkUrl(linkedInfo.getUrl())); + } else if (!TextUtils.isEmpty(linkedInfo.getWorldId()) && linkedInfo.getType().equals("5")) { + MiniWorldGuestPageActivity.start(context, linkedInfo.getWorldId()); + } else if (linkedInfo.getType().equals("6") && !TextUtils.isEmpty(linkedInfo.getWorldId()) && + !TextUtils.isEmpty(linkedInfo.getDynamicId())) { + DynamicDetailActivity.start(context, JavaUtil.str2long(linkedInfo.getDynamicId()), + JavaUtil.str2long(linkedInfo.getWorldId()), 6); + } + }) + .subscribe(); + + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginEvent(LoginEvent event) { + onLogin(AuthModel.get().getCurrentUid()); + } + + /** + * 检查是否绑定手机 + */ + private void checkBindPhone() { + BinderPhoneActivity.start(context, true); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLogoutEvent(LogoutEvent event) { + onLogout(); + PwdCodeMgr.get().onLogout(); + } + + @SuppressLint("CheckResult") + public void onLogin(long uid) { + Logger.e(TAG, "onLogin Success ~~~~"); + CrashReport.setUserId(this, uid + ""); + + Log.i("checkLostUser", "onLogin"); + checkLostUser(uid); + + //登录完成后检查更新 + AppUpgradeHelper.checkAppUpgrade(this); + + //登录成功查询未读信息数量 + mMainTabLayout.setmUnReadDynamicCount(0); + int unreadCount = IMMessageManager.get().queryUnreadMsg() + Unicorn.getUnreadCount(); + mMainTabLayout.setMsgNum(unreadCount); + // 如果需要跳转,在这里实现 + if (!shown && + (System.currentTimeMillis() - startTime) <= 2000 && + getIntent().hasExtra("url") && getIntent().hasExtra("type")) { + shown = true; + + LogUtil.print("点击了闪屏"); + handleChannelPageInfo(true) + .doOnError(throwable -> { + //如果没有渠道页,就按原来的逻辑即可 + int type = getIntent().getIntExtra("type", 0); + String url = getIntent().getStringExtra("url"); + if (type == 3) { + Intent intent = new Intent(context, CommonWebViewActivity.class); + intent.putExtra("url", url); + startActivity(intent); + } else if (type == 2) { + AVRoomActivity.start(context, Long.valueOf(url)); + } + }) + .subscribe(); + + + } + + // 互动消息未读数量 + HomeModel.get().getUnreadCount(AuthModel.get().getCurrentUid()) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(Integer integer, Throwable throwable) throws Exception { + if (integer != null) { + EventBus.getDefault().post(new UnReadCountEvent(integer)); + } + } + }); + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoadLoginUserInfoEvent(LoadLoginUserInfoEvent event) { + handleSign(); + firstLoadedUserInfo(); + } + + private void handleSign() { + //检查是否需要弹 签到框 + //如果是新用户,因为有资料未完善,所以先不弹签到框 + UserInfo loginUserInfo = UserModel.get().getCacheLoginUserInfo(); + if (loginUserInfo == null) { + //弹出去绑定用户 + + return; + } + if (!TextUtils.isEmpty(loginUserInfo.getNick()) && !TextUtils.isEmpty(loginUserInfo.getAvatar())) { + //noinspection ResultOfMethodCallIgnored + SignDialogTimeManager.checkSignDialog(this, false); + } + } + + public void onLogout() { + Logger.e(TAG, "onLogout Success ~~~~"); + getMvpPresenter().exitRoom(); + LoginActivity.start(MainActivity.this); + PmDialogShowMrg.get().onLogout(); + } + + public void onNeedLogin() { + LoginActivity.start(MainActivity.this); + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onKickedOutEvent(KickOutEvent event) { + toast("您已被踢下线,若非正常行为,请及时修改密码"); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveRecentContactChanged(List imMessages) { + + int countIgnore = 0; + for (RecentContact recentContact : imMessages) { + + if (recentContact.getSessionType() == SessionTypeEnum.Team) { + Team team = NIMClient.getService(TeamService.class).queryTeamBlock(recentContact.getContactId()); + if (team != null && team.getMessageNotifyType() == TeamMessageNotifyTypeEnum.Mute) { + countIgnore += recentContact.getUnreadCount(); + } + + } + + } + int unreadCount = IMMessageManager.get().queryUnreadMsg() + Unicorn.getUnreadCount() - countIgnore; + mMainTabLayout.setMsgNum(unreadCount); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCustomerServerMsgEvent(CustomerServerMsgEvent event) { + int unreadCount = IMMessageManager.get().queryUnreadMsg() + event.unreadCount; + mMainTabLayout.setMsgNum(unreadCount); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onNeedCompleteInfo(NeedCompleteInfoEvent event) { + getDialogManager().dismissDialog(); + UIHelper.showAddInfoAct(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + int unreadCount = IMMessageManager.get().queryUnreadMsg() + Unicorn.getUnreadCount(); + mMainTabLayout.setMsgNum(unreadCount); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveNewPacket(final RedPacketInfoV2 redPacketInfo) { + CommonPref.instance(this).putBoolean("redPacketPoint", true); + if (redPacketInfo.isNeedAlert()) { + RedPacketDialog.start(this, redPacketInfo); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveLevelUpActivity(LevelUpEvent event) { + LevelUpDialog.start(this, event.getLevelName(), true); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveCharmLevelUpActivity(CharmLevelUpEvent event) { + LevelUpDialog.start(this, event.getLevelName(), false); + } + + @SuppressLint("CheckResult") + private void updateRoomState() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + UserModel.get().getUserInfo(roomInfo.getUid()).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + if (userInfo != null) { + displayAvatarLayout(userInfo.getAvatar()); + } else { + NimUserInfo nimUserInfo = NimUserInfoCache.getInstance().getUserInfo(roomInfo.getUid() + ""); + if (nimUserInfo == null) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(roomInfo.getUid() + "", new RequestCallbackWrapper() { + @Override + public void onResult(int i, NimUserInfo nimUserInfo, Throwable throwable) { + if (nimUserInfo != null) { + displayAvatarLayout(nimUserInfo.getAvatar()); + } + } + }); + } else { + displayAvatarLayout(nimUserInfo.getAvatar()); + } + } + } + }); + + } + } + + private void startRoomMinAnim() { + roomMinAnim = ObjectAnimator.ofFloat(avatarImage, "rotation", 0f, 360f); + roomMinAnim.setDuration(10000); + roomMinAnim.setRepeatCount(-1); + roomMinAnim.setInterpolator(new LinearInterpolator()); + roomMinAnim.start(); + } + + private void stopRoomMinAnim() { + if (roomMinAnim != null) { + roomMinAnim.cancel(); + roomMinAnim = null; + } + } + + private void displayAvatarLayout(String avatar) { + avatarLayout.clearAnimation(); + avatarLayout.setVisibility(View.VISIBLE); + userLivingView.start(); + stopRoomMinAnim(); + startRoomMinAnim(); + ImageLoadUtils.loadAvatar(MainActivity.this, avatar, avatarImage); + } + + public void onEnter(RoomInfo roomInfo) { + updateRoomState(); + DaemonService.start(this, roomInfo); + } + + @SuppressLint("RestrictedApi") + @Override + public void onTabClick(int position) { + List fragments = getSupportFragmentManager().getFragments(); + switchFragment(position); + if (position == MainTabLayout.MAIN_TAB_POS_HOME) { + //显示引导 +// FragmentManager fragmentManager = getSupportFragmentManager(); +// Fragment mainFragment = fragmentManager.findFragmentByTag(MainFragment.TAG); +// if (mainFragment != null && mainFragment instanceof MainFragment) { +// ((MainFragment) mainFragment).handleGuide(); +// } + } + } + + private void switchFragment(int position) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + //Fragment mainFragment = fragmentManager.findFragmentByTag(MainFragment.TAG); + Fragment attentionFragment = fragmentManager.findFragmentByTag(FindTabFragment.TAG); + Fragment msgFragment = fragmentManager.findFragmentByTag(MsgFragment.TAG); + Fragment meFragment = fragmentManager.findFragmentByTag(MeFragment.TAG); + Fragment rankingFragment = fragmentManager.findFragmentByTag(RankingFragment.TAG); + Fragment gameFragment = fragmentManager.findFragmentByTag(GameHomeFragment.TAG); + //先隐藏所有的 +// if (mainFragment != null && mainFragment.isVisible()) { +// fragmentTransaction.hide(mainFragment); +// } + if (attentionFragment != null && attentionFragment.isVisible()) { + fragmentTransaction.hide(attentionFragment); + } + if (msgFragment != null && msgFragment.isVisible()) { + fragmentTransaction.hide(msgFragment); + } + if (meFragment != null && meFragment.isVisible()) { + fragmentTransaction.hide(meFragment); + } + if (rankingFragment != null && rankingFragment.isVisible()) { + fragmentTransaction.hide(rankingFragment); + } + if (gameFragment != null && gameFragment.isVisible()) { + fragmentTransaction.hide(gameFragment); + } + //预加载首页 +// if (PRELOAD_HOME && mainFragment == null) { +// mainFragment = new MainFragment(); +// fragmentTransaction.add(R.id.main_fragment, mainFragment, MainFragment.TAG); +// } + if (position == MainTabLayout.MAIN_TAB_POS_GAME) { + if (gameFragment == null) { + gameFragment = new GameHomeFragment(); + fragmentTransaction.add(R.id.main_fragment, gameFragment, GameHomeFragment.TAG); + } + fragmentTransaction.show(gameFragment); + } else if (position == MainTabLayout.MAIN_TAB_POS_HOME) { +// if (mainFragment == null) { +// mainFragment = new MainFragment(); +// fragmentTransaction.add(R.id.main_fragment, mainFragment, MainFragment.TAG); +// } +// fragmentTransaction.show(mainFragment); + } else if (position == MainTabLayout.MAIN_TAB_POS_ATTENTION) { + if (attentionFragment == null) { + attentionFragment = new FindTabFragment(); + fragmentTransaction.add(R.id.main_fragment, attentionFragment, FindTabFragment.TAG); + } + fragmentTransaction.show(attentionFragment); + } else if (position == MainTabLayout.MAIN_TAB_POS_MSG) { + if (msgFragment == null) { + msgFragment = new MsgFragment(); + fragmentTransaction.add(R.id.main_fragment, msgFragment, MsgFragment.TAG); + } + fragmentTransaction.show(msgFragment); + } else if (position == MainTabLayout.MAIN_TAB_POS_ME) { + if (meFragment == null) { + meFragment = new MeFragment(); + fragmentTransaction.add(R.id.main_fragment, meFragment, MeFragment.TAG); + } + fragmentTransaction.show(meFragment); + } + if (!isDestroyed()) + fragmentTransaction.commitAllowingStateLoss(); + mCurrentMainPosition = position; + } + + private void setStateBarColor() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = getWindow(); +//设置状态栏的颜色,和你的app主题或者标题栏颜色设置一致就ok了 + window.setStatusBarColor(getResources().getColor(R.color.white)); + } + } + + @Override + public void exitRoom(RoomInfo roomInfo) { + closeOpenRoomAnimation(); + if (OpenBoxService.isAutoOpenBox) { + OpenBoxService.stop(this); + } + if (OpenHonourBoxService.isAutoOpenBox) { + OpenHonourBoxService.stop(this); + } + //ktv退出的时候需要用到 + if (RtcEngineManager.get().isOpenKtv() && roomInfo != null) { + KtvMusicManager.INSTANCE.deleteUserAllChooseMusic(roomInfo.getUid()).subscribe(); + RtcEngineManager.get().closeKtvModel(); + } + DaemonService.stop(MainActivity.this); + } + + private void showCarGuide() { + boolean showCarGuide = CommonPref.instance(this).getBoolean(SHOW_CAR_GUIDE, true); + if (showCarGuide) { + ShowCarGuideDialog showCarGuideDialog = ShowCarGuideDialog.newInstance("https://img.erbanyy.com/Fi1Vhqkkc9dh3RIPgy3jjWBtyWNE?imageslim"); + if (!isValid()) return; + showCarGuideDialog.show(getFragmentManager(), ShowCarGuideDialog.class.getSimpleName()); + CommonPref.instance(this).putBoolean(SHOW_CAR_GUIDE, false); + } + } + + /** + * lvzebiao at 2020/02/27 + * 绑定手机号流程更改,完善资料完成后,访问少男少女的接口的逻辑依旧保留,但不算登录流程结束 + * 登录流程结束,应该是完善资料-绑定手机号-最后获取最新的用户信息 + * 并且发出事件{@link LoadLoginUserInfoEvent} 后,才算登录流程成功,并终止 + */ + @SuppressLint("CheckResult") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentUserInfoCompleteEvent(CurrentUserInfoCompleteEvent event) { + //补全完信息后,获取导流房间数据 + HomeModel.get().loadRecommendRoom( + String.valueOf(AuthModel.get().getCurrentUid()) + ) + .subscribe(new BiConsumer() { + @Override + public void accept(UserRecommendRoomInfo userRecommendRoomInfo, Throwable throwable) throws Exception { + if (throwable != null) { + Logger.e(throwable.getMessage()); + return; + } + if (userRecommendRoomInfo.getRecommendRoomUid() > 0) { + onRecommendRoomWhenCompleteUserInformation(userRecommendRoomInfo); + } + } + }); + + //处理签到弹框 注释原因看上面备注 + //handleSign(); + //firstLoadedUserInfo(); + } + + /** + * 第一次完善用户信息时候,弹出推荐房间dialog + * + * @param userRecommendRoomInfo + */ + private void onRecommendRoomWhenCompleteUserInformation(UserRecommendRoomInfo userRecommendRoomInfo) { + RecommendRoomForNewerDialog dialog = new RecommendRoomForNewerDialog(this); + dialog.setActionListener(new RecommendRoomForNewerDialog.onActionListener() { + @Override + public void onGoIntoRoom(DialogInterface dialogInterface) { + AVRoomActivity.start(MainActivity.this, userRecommendRoomInfo.getRecommendRoomUid()); + dialogInterface.dismiss(); + } + + @Override + public void onCancel(DialogInterface dialogInterface) { + dialogInterface.dismiss(); + } + }); + dialog.show(); + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMarketVerifyUpdateEvent(MarketVerifyUpdateEvent event) { + //审核包隐藏tab + if (MarketVerifyModel.get().isMarketChecking()) { + mMainTabLayout.showOrHideTab(MainTabLayout.MAIN_TAB_POS_ATTENTION, View.GONE); + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveRecallStatus(CheckLostUserEvent event) { + //如果没有获取到当前登录用户的信息,不弹出提示 + if (UserModel.get().getCacheLoginUserInfo() == null) { + return; + } + + CheckLostUserInfo checkLostUserInfo = (CheckLostUserInfo) event.getData(); + + boolean goBackOnce = (boolean) SharedPreferenceUtils.get(RecallDialog.GO_BACK_ONCE, false); + + if (!goBackOnce && !event.isFailed() && checkLostUserInfo.isLostUser() && !checkLostUserInfo.isClaimedAward()) + RecallDialog.start(this); + } + + private void checkLostUser(long uid) { + RecallModel.get().checkLostUser(uid).subscribe(); + } + + private void startGuild() { + GuideActivity.start(this); + } + + public boolean isShowGameTab() { + return mCurrentMainPosition == MainTabLayout.MAIN_TAB_POS_GAME; + } + + public boolean isShowMainTab() { + return mCurrentMainPosition == MainTabLayout.MAIN_TAB_POS_HOME; + } + + public boolean isShowMsgTab() { + return mCurrentMainPosition == MainTabLayout.MAIN_TAB_POS_MSG; + } + + public boolean isShowMeTab() { + return mCurrentMainPosition == MainTabLayout.MAIN_TAB_POS_ME; + } + + /** + * 第一次加载到用户信息 + */ + private void firstLoadedUserInfo() { + //青少年弹窗处理 + PmDialogShowMrg.get().handle(new WeakReference<>(this)); + + //这里稍微晚点访问 + Single.timer(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .flatMap(new Function>() { + @Override + public SingleSource apply(Long aLong) throws Exception { + return handleChannelPageInfo(false); + } + }) + .subscribe(); + } + + public LimitEnterRoomHelper getLimitEnterRoomHelper() { + if (limitEnterRoomHelper == null) { + limitEnterRoomHelper = new LimitEnterRoomHelper(); + } + return limitEnterRoomHelper; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onImPushMsgPmLimitTimeEvent(ImPushMsgPmLimitTimeEvent event) { + //先判断Avroom存不存在,存在的话则不处理,avroom会处理 + WeakReference reference = ActivityStackManager.getInstance().getAvRoomActWeakRef(); + if (reference != null && reference.get() != null) { + return; + } + getLimitEnterRoomHelper().handleThisContext(this, event.getData(), true, this::handlePmExitRoom); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPmDismissAllLimitDialogEvent(PmDismissAllLimitDialogEvent event) { + if (limitEnterRoomHelper != null) { + limitEnterRoomHelper.dismissDialog(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onUnReadCount(UnReadCountEvent event) { + mMainTabLayout.setmUnReadDynamicCount(event.getTotal()); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void SquarePublish(SquareTaskEvent event) { + if (getDialogManager() != null) { + PublishActivity.start(getDialogManager()); + } + } + + private void handlePmExitRoom() { + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + closeOpenRoomAnimation(); + getMvpPresenter().exitRoom(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCloseMinRoomEvent(CloseMinRoomEvent event) { + //如果房间存在,就关闭 + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + handlePmExitRoom(); + } + } + + /** + * 处理开房限制时长 + */ + public void handleOpenRoomWhenPmLimit(String error) { + getLimitEnterRoomHelper().handleThisContext(this, error, false, this::handlePmExitRoom); + } + + /** + * 云信通知栏跳转的处理 + */ + private void handleNimIntent() { + Intent intent = getIntent(); + if (intent == null) { + return; + } + boolean isNimPush = intent.getBooleanExtra(NimMiddleActivity.EXTRA_IS_NIM_PUSH, false); + if (isNimPush && mMainTabLayout != null) { + mMainTabLayout.select(MainTabLayout.MAIN_TAB_POS_MSG); + } + } + + private Single handleChannelPageInfo(boolean isSplashOrLinkedme) { + return ChannelPageModel.get().handleSplashOrLinkedmeJump(isSplashOrLinkedme) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .doOnSuccess(info -> channelPageInfoRoute(info, isSplashOrLinkedme)) + .doOnError(throwable -> LogUtil.print(throwable.getMessage())); + } + + /** + * 处理渠道落地页 + */ + private void channelPageInfoRoute(ChannelPageInfo info, boolean isSplashOrLinkedme) { + if (info == null) { + return; + } + if (ChannelPageModel.get().isHasJumpChannelPage()) { + LogUtil.print("已经跳转过落地页了..."); + return; + } + ChannelPageModel.get().setTureJumpChannelPage(); + //如果是来自linkedme或者闪屏,则需要延迟下再启动 + //普通访问,事先已经有延迟,则直接启动 + long delay = isSplashOrLinkedme ? 300 : 10; + Single.timer(delay, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .doOnSuccess(aLong -> + RouterHandler.handle(context, info.getRouteType(), info.getRouteValue())) + .subscribe(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onNeedBindPhoneEvent(NeedBindPhoneEvent event) { + checkBindPhone(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/MiddleActivity.java b/app/src/main/java/com/yizhuan/erban/MiddleActivity.java new file mode 100644 index 000000000..46632be56 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/MiddleActivity.java @@ -0,0 +1,86 @@ +package com.yizhuan.erban; + +import android.os.Bundle; +import android.util.Log; + +import com.microquation.linkedme.android.LinkedME; +import com.microquation.linkedme.android.util.LinkProperties; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.linked.LinkedModel; +import com.yizhuan.xchat_android_core.linked.bean.LinkedInfo; +import com.yizhuan.xchat_android_core.statistic.LogFactory; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.LogProtocol; + +import java.util.HashMap; + +/** + * Created by chenran on 2017/8/5. + */ + +public class MiddleActivity extends BaseActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getIntent() != null) { + //获取与深度链接相关的值 + LinkProperties linkProperties = getIntent().getParcelableExtra(LinkedME.LM_LINKPROPERTIES); + if (linkProperties != null) { + Log.i("LinkedME-Demo", "Channel " + linkProperties.getChannel()); + Log.i("LinkedME-Demo", "control params " + linkProperties.getControlParams()); + Log.i("LinkedME-Demo", "link(深度链接) " + linkProperties.getLMLink()); + Log.i("LinkedME-Demo", "是否为新安装 " + linkProperties.isLMNewUser()); + //获取自定义参数封装成的hashmap对象,参数键值对由集成方定义 + + HashMap hashMap = linkProperties.getControlParams(); + LogUtil.print("linkedme", hashMap); + //根据key获取传入的参数的值,该key关键字View可为任意值,由集成方规定,请与web端商议,一致即可 + LinkedInfo linkedInfo = new LinkedInfo(); + linkedInfo.setNewUser(linkProperties.isLMNewUser()); + String roomuid = hashMap.get("roomuid"); + String uid = hashMap.get("uid"); + String channel = hashMap.get("linkedmeChannel"); + String type = hashMap.get("type"); + String familyId = hashMap.get("familyId"); + String url = hashMap.get("url"); + String worldId = hashMap.get("worldId"); + String dynamicId = hashMap.get("dynamicId"); + if (roomuid != null) { + linkedInfo.setRoomUid(roomuid); + } + if (uid != null) { + linkedInfo.setUid(uid); + } + if (type != null) { + linkedInfo.setType(type); + } + if (familyId != null) { + linkedInfo.setFamilyId(familyId); + } + if (url != null) { + linkedInfo.setUrl(url); + } + if (worldId != null) { + linkedInfo.setWorldId(worldId); + } + if (dynamicId != null) { + linkedInfo.setDynamicId(dynamicId); + } + //发送 log 到阿里 + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_VERBOSE, + LogProtocol.Topic.TOPIC_SYSTEM_LOG, + LogProtocol.Event.EVENT_LINK_ME + ) + .append("shareUid", uid) + .append("channel", channel)); + + + LinkedModel.get().setLinkedInfo(linkedInfo); + } + } + finish(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/NimMiddleActivity.java b/app/src/main/java/com/yizhuan/erban/NimMiddleActivity.java new file mode 100644 index 000000000..1c50b3642 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/NimMiddleActivity.java @@ -0,0 +1,82 @@ +package com.yizhuan.erban; + +import android.content.Intent; +import android.os.Bundle; + +import com.netease.nimlib.sdk.NimIntent; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.radish.signin.SignInActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenRoomNotiAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment; +import com.yizhuan.xchat_android_library.utils.UIUtils; + +import java.util.ArrayList; + +/** + * Created by chenran on 2017/8/5. + */ + +public class NimMiddleActivity extends BaseActivity { + + private static final String TAG = "NimMiddleActivity"; + /** + * 通知栏启动Main后,自动跳转到 msg tab + */ + public final static String EXTRA_IS_NIM_PUSH = "is_nim_push"; + + public static String EXTRA_FROM_NOTIFICATION = "from_notification"; + public static final String INTENT_ACTION_AVCHAT = "INTENT_ACTION_AVCHAT"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + if (intent != null) { + if (intent.hasExtra(NimIntent.EXTRA_NOTIFY_CONTENT)) { + parseNotifyIntent(intent); + return; + } else if (intent.hasExtra(EXTRA_FROM_NOTIFICATION) || intent.hasExtra(INTENT_ACTION_AVCHAT)) { + parseNormalIntent(intent); + } else { + parseNormalIntent(null); + } + } + } + + private void parseNotifyIntent(Intent intent) { + if (intent == null) { + return; + } + intent.putExtra(EXTRA_IS_NIM_PUSH, true); + MainActivity.start(NimMiddleActivity.this, intent); + ArrayList messages = (ArrayList) intent.getSerializableExtra(NimIntent.EXTRA_NOTIFY_CONTENT); + if (messages != null && messages.size() > 0) { + IMMessage imMessage = messages.get(messages.size() - 1); + if (imMessage.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment attachment = (CustomAttachment) imMessage.getAttachment(); + if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { + OpenRoomNotiAttachment noticeAttachment = (OpenRoomNotiAttachment) attachment; + if (noticeAttachment.getUid() > 0) { + AVRoomActivity.start(this, noticeAttachment.getUid()); + } + } else if (attachment instanceof OpenSignInAttachment) { + if (AuthModel.get().isImLogin() + && !UIUtils.isTopActivity(this, SignInActivity.class.getSimpleName())) { + SignInActivity.start(this); + } + } + } + } + finish(); + } + + private void parseNormalIntent(Intent intent) { + MainActivity.start(NimMiddleActivity.this, intent); + finish(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/UIHelper.java b/app/src/main/java/com/yizhuan/erban/UIHelper.java new file mode 100644 index 000000000..3eaa1e8fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/UIHelper.java @@ -0,0 +1,230 @@ +package com.yizhuan.erban; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.provider.Settings; +import android.support.v4.app.Fragment; + +import com.yizhuan.erban.audio.AudioRecordActivity; +import com.yizhuan.erban.audio.MyVoiceActivity; +import com.yizhuan.erban.audio.RecordingVoiceActivity; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.erban.ui.login.ForgetPswActivity; +import com.yizhuan.erban.ui.login.ModifyInfoActivity; +import com.yizhuan.erban.ui.login.RegisterActivity; +import com.yizhuan.erban.ui.setting.SettingActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.user.UserInfoModifyActivity; +import com.yizhuan.erban.ui.user.UserModifyPhotosActivity; +import com.yizhuan.erban.ui.wallet.JewelActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + + +/** + * ************************************************************************* + * + * @Version 1.0 + * @ClassName: UIHelper + * @Description: 应用程序UI工具包:封装UI相关的一些操作 + * @Author zhouxiangfeng + * @date 2013-8-6 下午1:39:11 + * ************************************************************************** + */ +public class UIHelper { +// +// /** +// * 登录 +// * +// * @param context +// */ +// public static void showLoginAct(Context context) { +// Intent intent = new Intent(context, LoginActivity.class); +// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); +// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); +// context.startActivity(intent); +// } +// +// /** +// * 显示 主界面 +// */ +// public static void showMyMainAct(Context context) { +// Intent intent = new Intent(context, Main2Activity.class); +// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); +// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); +// context.startActivity(intent); +// } + + + public static void showUserGuideAct(Context mContext) { + mContext.startActivity(new Intent(mContext, UserGuideActivity.class)); + } + + public static void showRegisterAct(Context mContext) { + mContext.startActivity(new Intent(mContext, RegisterActivity.class)); + } + + public static void showSettingAct(Context mContext) { + mContext.startActivity(new Intent(mContext, SettingActivity.class)); + } + + public static void showForgetPswAct(Context mContext) { + mContext.startActivity(new Intent(mContext, ForgetPswActivity.class)); + } + + public static void showAddInfoAct(Context mContext) { + Intent intent = new Intent(mContext, AddUserInfoActivity.class); + mContext.startActivity(intent); + + } + +// public static void showUserAvatarUpdateAct(Context mContext) { +// mContext.startActivity(new Intent(mContext, UserAvatarUpdateActivity.class)); +// } + + + //修改用户资料 + public static void showUserInfoModifyAct(Context mContext, long userId) { + Intent intent = new Intent(mContext, UserInfoModifyActivity.class); + intent.putExtra("userId", userId); + mContext.startActivity(intent); + } + + //修改用户资料 + public static void showUserInfoModifyAct(Activity mActivity, int requestCode, long userId) { + Intent intent = new Intent(mActivity, UserInfoModifyActivity.class); + intent.putExtra("userId", userId); + mActivity.startActivityForResult(intent, requestCode); + } + + //我的钱包 + public static void showWalletAct(Context mContext) { + Intent intent = new Intent(mContext, JewelActivity.class); + //intent.putExtra("userInfo",userInfo); + mContext.startActivity(intent); + } + + //侧边栏===>帮助 + public static void showUsinghelp(Context mContext) { + CommonWebViewActivity.start(mContext, UriProvider.IM_SERVER_URL + "/modules/guide/guide.html"); + } + + + public static void showUserInfoAct(Context mContext, long userId) { + Intent intent = new Intent(mContext, UserInfoActivity.class); + intent.putExtra("userId", userId); + mContext.startActivity(intent); + } + + public static void showAudioRecordAct(Context mContext) { + Intent intent = new Intent(mContext, AudioRecordActivity.class); + mContext.startActivity(intent); + } + + public static void showRecordVoiceAct(Activity mActivity, int requestCode, long voiceId) { + Intent intent = new Intent(mActivity, RecordingVoiceActivity.class); + intent.putExtra(RecordingVoiceActivity.EXTRA_VOICE_ID, voiceId); + mActivity.startActivityForResult(intent, requestCode); + } + + public static void showMyVoiceAct(Context mContext) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND, "我的-我的声音"); + + Intent intent = new Intent(mContext, MyVoiceActivity.class); + mContext.startActivity(intent); + } + + public static void showMyVoiceAct(Fragment mFragment, int requestCode, String label) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND, "我的-我的声音-" + label); + Intent intent = new Intent(mFragment.getActivity(), MyVoiceActivity.class); + mFragment.startActivityForResult(intent, requestCode); + } + + public static void showMyVoiceAct(Activity mActivity, int requestCode, String label) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND, "我的-我的声音-" + label); + Intent intent = new Intent(mActivity, MyVoiceActivity.class); + mActivity.startActivityForResult(intent, requestCode); + } + + public static void showModifyInfoAct(Activity mActivity, int requestCode, String title) { + Intent intent = new Intent(mActivity, ModifyInfoActivity.class); + intent.putExtra("title", title); + mActivity.startActivityForResult(intent, requestCode); + } + + public static void showModifyInfoAct(Activity mActivity, int requestCode, int modifyType) { + Intent intent = new Intent(mActivity, ModifyInfoActivity.class); + intent.putExtra(ModifyInfoActivity.MODIFY_TYPE, modifyType); + mActivity.startActivityForResult(intent, requestCode); + } + + public static void showModifyPhotosAct(Activity mActivity, long userId) { + Intent intent = new Intent(mActivity, UserModifyPhotosActivity.class); + intent.putExtra("userId", userId); + mActivity.startActivity(intent); + } + + public static void showMonsterResult(Context context, String monsterId) { + CommonWebViewActivity.start(context, UriProvider.IM_SERVER_URL + + "/modules/monster/index.html?monsterId=" + monsterId); + } + + /** + * 跳转到举报页 + * + * @param uid 被举报人 + */ + public static void showReportPage(Context context, long uid, String source) { + //被举报人的id + String url = UriProvider.getUserReportUrl() + "?reportUid=" + uid + "&source=" + source; + CommonWebViewActivity.start(context, url); + } + + /** + * 跳转推荐页h5 + */ + public static void showRecommendPosH5(Context context) { + String cardUrl = UriProvider.JAVA_WEB_URL + + "/modules/recommend-card/index.html"; + CommonWebViewActivity.start(context, cardUrl); + } + + + /** + * 启动应用的设置 + * + * @param context + */ + public static void startAppSettings(Context context) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + context.getPackageName())); + context.startActivity(intent); + } + + private static void startOtherApp(Context context, String pkgName, String launcherActivityName) { + ComponentName componet = new ComponentName(pkgName, launcherActivityName); + //pkgName 就是第三方应用的包名 + //launcherActivityName 就是第三方应用的进入的第一个Activity + Intent intent = new Intent(); + intent.setComponent(componet); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + public static void startWeixinApp(Context context) { + startOtherApp(context, "com.tencent.mm", "com.tencent.mm.ui.LauncherUI"); + } + + public static void startQQApp(Context context) { + startOtherApp(context, "com.tencent.mobileqq", "com.tencent.mobileqq.activity.SplashActivity"); + } + + public static void openContactUs(Context context) { + CommonWebViewActivity.start(context, UriProvider.IM_SERVER_URL + "/modules/contact/contact.html"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/UserGuideActivity.java b/app/src/main/java/com/yizhuan/erban/UserGuideActivity.java new file mode 100644 index 000000000..c220082bf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/UserGuideActivity.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.widget.ImageView; + +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.PreferencesUtils; + + +public class UserGuideActivity extends BaseActivity { +// private static final int[] images = {R.drawable.guide_one, R.drawable.guide_two, R.drawable.guide_three,}; + protected static final String TAG = "UserGuide"; + private ViewPager mViewPage; + private ImageView enterHome; + private GuideAdapter adapter; + + public static void start(Context context) { + Intent intent = new Intent(context, UserGuideActivity.class); + context.startActivity(intent); + } + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_user_guide); + initView(); + } + + private void initView() { + mViewPage = (ViewPager) findViewById(R.id.view_page); + enterHome = (ImageView) findViewById(R.id.enter_home); + adapter = new GuideAdapter(this); + mViewPage.setAdapter(new GuideAdapter(this)); + mViewPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if(position == adapter.getCount()-1){ + enterHome.setVisibility(View.VISIBLE); + }else{ + enterHome.setVisibility(View.GONE); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + enterHome.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PreferencesUtils.setFristUser(false); + MainActivity.start(UserGuideActivity.this); + finish(); + } + }); + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/application/ActivityLifeManager.java b/app/src/main/java/com/yizhuan/erban/application/ActivityLifeManager.java new file mode 100644 index 000000000..937147f4b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/application/ActivityLifeManager.java @@ -0,0 +1,73 @@ +package com.yizhuan.erban.application; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; +import android.util.Log; + +import com.yizhuan.erban.location.LocationManager; +import com.yizhuan.erban.module_hall.secretcode.PwdCodeMgr; +import com.yizhuan.erban.radish.signin.SignDialogTimeManager; +import com.yizhuan.xchat_android_core.auth.AuthModel; + +/** + * activity的管理 + * create by lvzebiao @2019/3/13 + */ +public class ActivityLifeManager implements Application.ActivityLifecycleCallbacks { + + private int count = 0; + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + ActivityStackManager.getInstance().addActivity(activity); + } + + @Override + public void onActivityStarted(Activity activity) { + if (count == 0) { + //应用回到前台了 + //这里进行暗号的判断 + PwdCodeMgr.get().handlePopPwdCodeWindow(activity); + if (AuthModel.get().isImLogin()) { + SignDialogTimeManager.checkSignDialog(activity, true); + LocationManager.uploadLocation(activity); + } + } + count++; + } + + @Override + public void onActivityStopped(Activity activity) { + count--; + if (count < 0) { + count = 0; + } + if (count == 0) { + //应用隐藏到后台了 + } + } + + @Override + public void onActivityResumed(Activity activity) { + ActivityStackManager.getInstance().setTopUpgradeActivity(activity); + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + ActivityStackManager.getInstance().removeActivity(activity); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/application/ActivityStackManager.java b/app/src/main/java/com/yizhuan/erban/application/ActivityStackManager.java new file mode 100644 index 000000000..b334ea18c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/application/ActivityStackManager.java @@ -0,0 +1,55 @@ +package com.yizhuan.erban.application; + +import android.app.Activity; + + +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.utils.ActWhiteListMrg; + +import java.lang.ref.WeakReference; + +import lombok.Getter; + + +/** + * create by lvzebiao @2019/8/8 + */ +public class ActivityStackManager { + + /** + * 用于保持最顶的Activity实例,排除中转的activity + * 比如{@link com.yizhuan.erban.MiddleActivity} + */ + @Getter + private WeakReference topUpgradeWeakRef; + + @Getter + private WeakReference avRoomActWeakRef; + + public void setTopUpgradeActivity(Activity activity) { + if (!ActWhiteListMrg.isTempActivity(activity)) { + topUpgradeWeakRef = new WeakReference<>(activity); + } + } + + public void addActivity(Activity activity){ + if (activity instanceof AVRoomActivity) { + avRoomActWeakRef = new WeakReference<>(activity); + } + } + + public void removeActivity(Activity activity){ + if (activity instanceof AVRoomActivity) { + avRoomActWeakRef = null; + } + } + + private static final class Helper { + public static final ActivityStackManager INSTANCE = new ActivityStackManager(); + } + + public static ActivityStackManager getInstance() { + return Helper.INSTANCE; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/application/GlobalHandleManager.java b/app/src/main/java/com/yizhuan/erban/application/GlobalHandleManager.java new file mode 100644 index 000000000..85e062dd4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/application/GlobalHandleManager.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.application; + +import android.app.Activity; + +import com.tongdaxing.erban.upgrade.AppUpgradeHelper; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.ui.widget.lottery_dialog.LotteryDialogManager; +import com.yizhuan.xchat_android_core.activity.bean.LotteryInfo; +import com.yizhuan.xchat_android_core.upgrade.event.ImPushUpdateAppEvent; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.lang.ref.WeakReference; + +/** + * 全局处理,比如App弹窗 + * create by lvzebiao @2019/8/14 + */ +public class GlobalHandleManager { + + private GlobalHandleManager() { + + } + + private static final class Helper { + private static final GlobalHandleManager INSTANCE = new GlobalHandleManager(); + } + + public static GlobalHandleManager get() { + return Helper.INSTANCE; + } + + public void init() { + EventBus.getDefault().register(this); + } + + public void unInit() { + EventBus.getDefault().unregister(this); + } + + public Activity getActivity() { + WeakReference weakReference = ActivityStackManager.getInstance() + .getTopUpgradeWeakRef(); + if (weakReference == null || weakReference.get() == null) { + return null; + } + return weakReference.get(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onImPushUpdateAppEvent(ImPushUpdateAppEvent event) { + Activity activity = getActivity(); + if (activity == null) return; + if (ActivityUtil.isCanShowAppCompatDialog(activity) && activity instanceof RxAppCompatActivity) { + AppUpgradeHelper.checkAppUpgrade((RxAppCompatActivity) activity, false, true); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveLotteryActivity(LotteryInfo lotteryInfo) { + Activity activity = getActivity(); + if (activity == null) return; + LotteryDialogManager.checkLotteryDialog(activity); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java b/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java new file mode 100644 index 000000000..569b5e0f7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/application/XChatApplication.java @@ -0,0 +1,681 @@ +package com.yizhuan.erban.application; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.app.Application; +import android.content.Context; +import android.graphics.Color; +import android.net.http.HttpResponseCache; +import android.os.Build; +import android.os.Environment; +import android.os.StrictMode; +import android.support.multidex.MultiDex; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.Log; + +import com.alibaba.security.rp.RPSDK; +import com.alipay.sdk.app.EnvUtils; +import com.baidu.mobstat.StatService; +import com.bumptech.glide.request.target.ViewTarget; +import com.ishumei.smantifraud.SmAntiFraud; +import com.llew.huawei.verifier.LoadedApkHuaWei; +import com.mcxiaoke.packer.helper.PackerNg; +import com.microquation.linkedme.android.LinkedME; +import com.mob.MobSDK; +import com.netease.mobsec.rjsb.watchman; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.SDKOptions; +import com.netease.nimlib.sdk.StatusBarNotificationConfig; +import com.netease.nimlib.sdk.mixpush.MixPushConfig; +import com.netease.nimlib.sdk.msg.MessageNotifierCustomization; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.orhanobut.logger.AndroidLogAdapter; +import com.orhanobut.logger.Logger; +import com.scwang.smartrefresh.header.MaterialHeader; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.footer.ClassicsFooter; +import com.squareup.leakcanary.LeakCanary; +import com.squareup.leakcanary.RefWatcher; +import com.tencent.bugly.crashreport.CrashReport; +import com.umeng.analytics.MobclickAgent; +import com.umeng.commonsdk.UMConfigure; +import com.yizhuan.erban.BuildConfig; +import com.yizhuan.erban.MiddleActivity; +import com.yizhuan.erban.NimMiddleActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.module_hall.HallDataManager; +import com.yizhuan.erban.radish.wallet.RadishWalletManager; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.Env; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.channel.ChannelModel; +import com.yizhuan.xchat_android_core.customer_server.CustomerServerModel; +import com.yizhuan.xchat_android_core.domain.model.DomainModel; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment; +import com.yizhuan.xchat_android_core.interceptor.DomainInterceptor; +import com.yizhuan.xchat_android_core.interceptor.NoParamsInterceptor; +import com.yizhuan.xchat_android_core.interceptor.ParamsInterceptor; +import com.yizhuan.xchat_android_core.manager.IMMessageManager; +import com.yizhuan.xchat_android_core.manager.IMSystemMsgManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.mentoring_relationship.model.MentoringRelationshipModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.public_chat_hall.model.PublicChatHallModel; +import com.yizhuan.xchat_android_core.radish.RadishModel; +import com.yizhuan.xchat_android_core.radish.signin.bean.ImNotice; +import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.net.ErBanAllHostnameVerifier; +import com.yizhuan.xchat_android_library.net.rxnet.RxNet; +import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil; +import com.yizhuan.xchat_android_library.utils.AppUtils; +import com.yizhuan.xchat_android_library.utils.DeviceUuidFactory; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.ProcessUtil; +import com.yizhuan.xchat_android_library.utils.SystemUtils; +import com.yizhuan.xchat_android_library.utils.VersionUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.reactivex.plugins.RxJavaPlugins; +import io.realm.Realm; +import io.realm.RealmConfiguration; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI; + +/** + * @author chenran + * @date 2017/2/11 + */ + +public class XChatApplication extends Application { + public static final String TAG = "XChatApplication"; + private static XChatApplication instance; + private RefWatcher mRefWatcher; + + public static XChatApplication instance() { + return instance; + } + + //生命周期监听 + private ActivityLifeManager lifeManager; + + //static 代码段可以防止内存泄露 + static { + SmartRefreshLayout.setDefaultRefreshHeaderCreater( + (context, layout) -> { +// layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局设置主题颜色 + layout.setEnableHeaderTranslationContent(false); + MaterialHeader materialHeader = new MaterialHeader(context); + materialHeader.setShowBezierWave(false); + return materialHeader; + }); + SmartRefreshLayout.setDefaultRefreshFooterCreater( + (context, layout) -> new ClassicsFooter(context).setDrawableSize(20)); + } + + @Override + public void onCreate() { + Log.i("xj-time", System.currentTimeMillis() + ""); + super.onCreate(); + + instance = this; + String channel = PackerNg.getChannel(this); + initEnv(channel); + //延迟初始化云信 + NIMClient.init(this, null, options()); + + //logger 配置 + Logger.addLogAdapter(new AndroidLogAdapter() { + @Override + public boolean isLoggable(int priority, String tag) { + return isDebug(); + } + }); + + if (inMainProcess(this)) { + + + RxJavaPlugins.setErrorHandler(throwable -> { + throwable.printStackTrace(); + // print it + Log.e(TAG, "the subscribe() method default error handler", throwable); + }); + //fixed: Glide Exception:"You must not call setTag() on a view Glide is targeting" + ViewTarget.setTagId(R.id.tag_glide); + + // 初始化 sp + SharedPreferenceUtils.init(this); + + init(channel); + + initLinkedMe(); + + if (!TextUtils.isEmpty(channel)) { + CrashReport.setAppChannel(this, channel); + } + + if (!isDebug()) { + CrashReport.initCrashReport(this.getApplicationContext(), XChatConstants.BUGLY_KEY_RELEASE, false); + } else { + CrashReport.initCrashReport(this.getApplicationContext(), XChatConstants.BUGLY_KEY_DEBUG, true); + } + //生命周期监听 + if (lifeManager == null) { + lifeManager = new ActivityLifeManager(); + } + registerActivityLifecycleCallback(lifeManager); + + + } + dealHuaWeiCrash(); + + } + + /** + * 初始化linkedMe + */ + private void initLinkedMe() { + LinkedME.getInstance(this, XChatConstants.LINKED_ME_KEY); + if (isDebug()) { + //设置debug模式下打印LinkedME日志 + LinkedME.getInstance().setDebug(); + } + //初始时请设置为false + LinkedME.getInstance().setImmediate(false); + //设置处理跳转逻辑的中转页,MiddleActivity详见后续配置 + LinkedME.getInstance().setHandleActivity(MiddleActivity.class.getName()); + } + + private void initEnv(String channel) { + BasicConfig.INSTANCE.setAppContext(this.getApplicationContext()); + + //首先初始化环境 + Env.initEnv(BuildConfig.BUILD_TYPE, BuildConfig.DEBUG); + + //切换生产坏境和测试环境 true/测试环境 false/生产环境 + BasicConfig.INSTANCE.setDebuggable(Env.isDebug()); + BasicConfig.INSTANCE.setChannel(channel); + + BasicConfig.INSTANCE.setRootDir(Constants.ERBAN_DIR_NAME); + BasicConfig.INSTANCE.setLogDir(Constants.LOG_DIR); + BasicConfig.INSTANCE.setConfigDir(Constants.CONFIG_DIR); + BasicConfig.INSTANCE.setVoiceDir(Constants.VOICE_DIR); + BasicConfig.INSTANCE.setCacheDir(Constants.CACHE_DIR); + BasicConfig.INSTANCE.setImageDir(Constants.IMAGE_CACHE_DIR); + } + + + private void dealHuaWeiCrash() { + String brand = Build.BRAND; + String manufacturer = Build.MANUFACTURER; + if (!TextUtils.isEmpty(brand) && ( + "HUAWEI".toLowerCase().equals(brand.toLowerCase()) + || "HONOR".toLowerCase().equals(brand.toLowerCase()) + || "HUAWEI".equals(manufacturer))) { + LoadedApkHuaWei.hookHuaWeiVerifier(this); + } + } + + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + // you must install multiDex whatever tinker is installed! + MultiDex.install(base); + } + + + @Override + public void onTerminate() { + super.onTerminate(); + CrashReport.closeBugly(); + if (lifeManager != null) { + unregisterActivityLifecycleCallbacks(lifeManager); + } + GlobalHandleManager.get().unInit(); + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) { + this.registerActivityLifecycleCallbacks(callbacks); + } + + /** + * 云信配置 + * + * @return + */ + public SDKOptions options() { + SDKOptions options = new SDKOptions(); + options.disableAwake = true; + options.asyncInitSDK = true; + if (isDebug()) { + options.checkManifestConfig = true; + } + // 如果将新消息通知提醒托管给 SDK 完成,需要添加以下配置。否则无需设置。 + StatusBarNotificationConfig config = new StatusBarNotificationConfig(); + // 点击通知栏跳转到该Activity + config.notificationEntrance = NimMiddleActivity.class; +// config.notificationSmallIconId = R.drawable.icon_msg_normal; + // 呼吸灯配置 + config.ledARGB = Color.GREEN; + config.ledOnMs = 1000; + config.ledOffMs = 1500; + // 通知铃声的uri字符串 + config.notificationSound = "android.resource://com.netease.nim.demo/raw/msg"; + options.statusBarNotificationConfig = config; + // 定制通知栏提醒文案(可选,如果不定制将采用SDK默认文案) + options.messageNotifierCustomization = messageNotifierCustomization; + + options.appKey = Constants.nimAppKey; + + // 配置保存图片,文件,log 等数据的目录 + // 如果 options 中没有设置这个值,SDK 会使用下面代码示例中的位置作为 SDK 的数据目录。 + // 该目录目前包含 log, file, image, audio, video, thumb 这6个目录。 + // 如果第三方 APP 需要缓存清理功能, 清理这个目录下面个子目录的内容即可。 + String sdkPath = null; + try { + sdkPath = Environment.getExternalStorageDirectory() + "/" + this.getPackageName() + "/nim"; + } catch (ArrayIndexOutOfBoundsException e) { + + } + options.sdkStorageRootPath = sdkPath; + + // 配置是否需要预下载附件缩略图,默认为 true + options.preloadAttach = true; + + // 配置附件缩略图的尺寸大小。表示向服务器请求缩略图文件的大小 + // 该值一般应根据屏幕尺寸来确定, 默认值为 Screen.width / 2 + int widthPixels = this.getResources().getDisplayMetrics().widthPixels; + options.thumbnailSize = widthPixels / 2; +// // save cache,留做切换账号备用 + DemoCache.setNotificationConfig(config); + + MixPushConfig mixPushConfig = new MixPushConfig(); + mixPushConfig.hwCertificateName = "tutuHuaweiAndroid"; + mixPushConfig.mzAppId = "118040"; + mixPushConfig.mzAppKey = "8ff2b4ccd52040399af1c3d526db32b2"; + mixPushConfig.mzCertificateName = "tutuMeizuAndroid"; + mixPushConfig.xmAppId = "2882303761517873288"; + mixPushConfig.xmAppKey = "5331787348288"; + mixPushConfig.xmCertificateName = "tutuXiaomiAndroid"; + options.mixPushConfig = mixPushConfig; + + return options; + } + + private MessageNotifierCustomization messageNotifierCustomization = new MessageNotifierCustomization() { + @Override + public String makeNotifyContent(String nick, IMMessage message) { + if (message.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment customAttachment = (CustomAttachment) message.getAttachment(); + if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { + return message.getFromNick(); + } else if (customAttachment instanceof OpenSignInAttachment) { + return getContentFromOpenSignIn(customAttachment); + } + } + // 采用SDK默认文案 + return "收到一条消息"; + } + + @Override + public String makeTicker(String nick, IMMessage message) { + if (message.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment customAttachment = (CustomAttachment) message.getAttachment(); + if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { + return message.getFromNick(); + } else if (customAttachment instanceof OpenSignInAttachment) { + return getContentFromOpenSignIn(customAttachment); + } + } + // 采用SDK默认文案 + return "收到一条消息"; + } + + private String getContentFromOpenSignIn(CustomAttachment attachment) { + String result = null; + if (attachment instanceof OpenSignInAttachment) { + ImNotice notice = ((OpenSignInAttachment) attachment).getImNotice(); + if (notice != null) { + result = notice.getContent(); + } + } + if (TextUtils.isEmpty(result)) { + result = "收到一条消息"; + } + return result; + } + + @Override + public String makeRevokeMsgTip(String s, IMMessage imMessage) { + return null; + } + }; + + /** + * 判断当前进程是否主进程 + * + * @param context + * @return + */ + private static boolean inMainProcess(Context context) { + String packageName = context.getPackageName(); + String processName = getProcessName(context); + return packageName.equals(processName); + } + + /** + * 获取当前进程名 + * + * @param context + * @return 进程名 + */ + public static String getProcessName(Context context) { + String processName = null; + + // ActivityManager + ActivityManager am = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)); + + while (true) { + for (ActivityManager.RunningAppProcessInfo info : am.getRunningAppProcesses()) { + if (info.pid == android.os.Process.myPid()) { + processName = info.processName; + break; + } + } + + // go home + if (!TextUtils.isEmpty(processName)) { + return processName; + } + + // take a rest and again + try { + Thread.sleep(100L); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + /** + * 初始化RxNet + * + * @param context + * @param url + */ + @SuppressLint("CheckResult") + public void initRxNet(Context context, String url) { + Map httpParams = new ArrayMap<>(); + httpParams.put("os", "android"); + httpParams.put("osVersion", Build.VERSION.RELEASE); + httpParams.put("app", "qingxun"); + httpParams.put("ispType", String.valueOf(SystemUtils.getIspType(context))); + httpParams.put("netType", String.valueOf(SystemUtils.getNetworkType(context))); + httpParams.put("model", SystemUtils.getPhoneModel()); + httpParams.put("appVersion", VersionUtil.getLocalName(context)); + httpParams.put("appVersionCode", String.valueOf(AppUtils.getVersionCode(context))); + httpParams.put("deviceId", DeviceUuidFactory.getDeviceId(context)); + httpParams.put("channel", AppMetaDataUtil.getChannelID()); + RxNet.init(context) + .debug(isDebug()) + .setBaseUrl(url) + .addInterceptors(new ParamsInterceptor(httpParams)) + .addInterceptors(new NoParamsInterceptor())//注意:拦截器的添加顺序,请求的拦截顺序 + //.addInterceptors(new DomainInterceptor()) + .certificates() + .hostnameVerifier(new ErBanAllHostnameVerifier()) + .build(); + //单例的model 初始化 + initModel(); + } + + public void initDomain(Context context, String url) { + // 从缓存中读出上一次可用的域名 + String availableHost = (String) SharedPreferenceUtils.get(DomainModel.KEY_AVAILABLE_HOST, ""); + LogUtil.e(TAG, "initDomain: 从缓存中读出上一次可用的域名: " + availableHost); + LogUtil.e(TAG, "initDomain: 编译时生成的域名: " + url); + // 如果缓存域名为空,则使用 BuildConfig 里面的域名 + String h5Url = TextUtils.isEmpty(availableHost) ? url : DomainModel.getInstance().getBaseUrl(availableHost); + // 强行用从缓存里读出来的域名给 H5 调用 + UriProvider.initUri(h5Url, h5Url, h5Url); + // 先初始化 RxNet,否则后面的 initModel 会有各种问题 + initRxNet(context, url); + // 从内存里获得硬编码的域名列表 + List domainList = DomainModel.getInstance().getDomainList(); + LogUtil.e(TAG, "initDomain: 从内存里获得预配置的域名文件"); + if (!ListUtils.isListEmpty(domainList)) { + for (String domain : domainList) { + LogUtil.e(TAG, "initDomain: 域名: " + domain); + } + } else { + LogUtil.e(TAG, "initDomain: 预设置域名为空"); + } + // 从缓存中读出之前从 client/init 里得到的候选域名名单 + List lastInitDomainList = DemoCache.readInitDataApiHost(); + LogUtil.e(TAG, "initDomain: 从缓存中读出之前从 client/init 里得到的候选域名名单"); + if (!ListUtils.isListEmpty(lastInitDomainList)) { + for (String domain : lastInitDomainList) { + LogUtil.e(TAG, "initDomain: 域名: " + domain); + } + } else { + LogUtil.e(TAG, "initDomain: 从缓存中读出之前从 client/init 里得到的候选域名名单为空"); + } + // 默认把初始域名插到检测列表的头部 + domainList.add(0, url); + // 候选域名列表插到检测列表的尾部 + if (!ListUtils.isListEmpty(lastInitDomainList)) { + domainList.addAll(lastInitDomainList); + } + LogUtil.e(TAG, "initDomain: 组合域名列表"); + for (String domain : domainList) { + // 检测可用的域名 + DomainModel.getInstance() + .analyseDomain(domain) + .subscribe(); + } + } + + private void init(String channel) { + initNimUIKit(); + initYiDun(); + initShuMeiTianWang(channel); + MobSDK.init(this); + UriProvider.initUri(BuildConfig.BASE_URL_DEBUG, BuildConfig.BASE_URL_STAGING, BuildConfig.BASE_URL_RELEASE); + try { + /** svga动画缓存路径 */ + File cacheDir = new File(this.getApplicationContext().getExternalCacheDir(), "http"); + if (!cacheDir.exists()) cacheDir.mkdirs(); + HttpResponseCache.install(cacheDir, 1024 * 1024 * 128); + } catch (IOException e) { + Log.e(TAG, "testtest", e); + } + // url +// if (Env.getCurrentEnv() == Env.EnvType.Staging) { +// // 预发布环境下不走动态域名的逻辑 +// initRxNet(BasicConfig.INSTANCE.getAppContext(), BuildConfig.BASE_URL_STAGING); +// } else { +// initDomain(BasicConfig.INSTANCE.getAppContext(), UriProvider.JAVA_WEB_URL); +// } + initRxNet(BasicConfig.INSTANCE.getAppContext(), UriProvider.JAVA_WEB_URL); + + //内存泄漏监控 + setupLeakCanary(); + ConnectiveChangedReceiver.getInstance().init(this.getApplicationContext()); + /** + * 使用到realm 数据库,这里配置数据库 这里必须先于模块初始化前进行初始化配置 + */ + Realm.init(BasicConfig.INSTANCE.getAppContext()); + RealmConfiguration config = new RealmConfiguration.Builder() + .name("qingxun.realm") + .deleteRealmIfMigrationNeeded() + .build(); + Realm.setDefaultConfiguration(config); + + + LogUtil.i(TAG, channel); + initBaiduStatistic(channel); + initUmengAppStatistic(channel); + + if (isDebug()) { + //禁掉沙盒模式 + //EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX); + } + + RPSDK.initialize(getApplicationContext()); + } + + /** + * 一些单例的 model + */ + private void initModel() { + DynamicFaceModel.get().init(); +// RedPacketModel.get(); + PayModel.get(); + UserModel.get(); + //ui层的萝卜钱包 + RadishWalletManager.get(); + //model层的 + RadishModel.get(); + + IMMessageManager.get().init(); + IMSystemMsgManager.get().init(); + + FamilyModel.Instance(); + AuthModel.get(); + + ChannelModel.get(); + MarketVerifyModel.get(); + GiftModel.get(); + PublicChatHallModel.get(); + // 模厅 + HallDataManager.get().application(); +// HallModel.get(); + // 师徒 + MentoringRelationshipModel.get(); + + //初始化客服系统 + CustomerServerModel.getInstance().init(this); + //全局处理 + GlobalHandleManager.get().init(); + } + + private void initBaiduStatistic(String channel) { + // 百度统计初始化 + StatService.setAppKey(Constants.BAIDU_APPKEY); + StatService.setAppChannel(this.getApplicationContext(), channel, true); + StatService.setOn(this.getApplicationContext(), StatService.EXCEPTION_LOG); + StatService.setSessionTimeOut(30); + StatService.setDebugOn(isDebug()); + } + + private void initUmengAppStatistic(String channel) { + // 友盟统计初始化 + UMConfigure.init(this.getApplicationContext(), XChatConstants.UMENG_APP_KEY, + channel, UMConfigure.DEVICE_TYPE_PHONE, null); + // 选用MANUAL页面采集模式 + MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.MANUAL); + // 支持在子进程中统计自定义事件 + UMConfigure.setProcessEvent(true); + // 日志加密 + UMConfigure.setEncryptEnabled(true); + // 集成测试 + UMConfigure.setLogEnabled(isRealDebug()); + } + + private void initNimUIKit() { + // 初始化 + NimUIKit.init(this); + } + + private void initYiDun() { + // 网易易盾初始化 + watchman.init(this, XChatConstants.YI_DUN_PRODUCT_NUMBER); + } + + private void initShuMeiTianWang(String channel) { + // 数美天网初始化 + if (Objects.equals(ProcessUtil.getCurProcessName(this), this.getPackageName())) { + SmAntiFraud.SmOption option = new SmAntiFraud.SmOption(); + String DEBUG_ORG = XChatConstants.SHU_MEI_TIAN_WANG_ORGANIZATION;// organization 代码 不要传 AccessKey + option.setOrganization(DEBUG_ORG); + option.setChannel(channel);//渠道代码 + SmAntiFraud.create(this, option); + } + } + + private void setupLeakCanary() { + if (!BasicConfig.INSTANCE.isDebuggable()) { + return; + } + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return; + } +// enabledStrictMode(); + mRefWatcher = LeakCanary.install(this); + } + + private static void enabledStrictMode() { + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() + .detectAll() //检测所有的想检测的 +// .detectCustomSlowCalls() //自定义的耗时调用 +// .detectDiskReads() /*检测磁盘读操作*/ +// .detectDiskWrites() /*检测磁盘写入操作*/ +// .detectNetwork() //检测网络 +// .detectResourceMismatches() + .penaltyLog() + .penaltyDeath() + .build()); + + StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() + .detectAll()/*也可以采用detectAll()来检测所有想检测的东西*/ +// .detectActivityLeaks()/*检测Activity内存泄露*/ +// .detectLeakedClosableObjects()/*检测未关闭的Closable对象*/ +// .detectLeakedSqlLiteObjects() /*检测Sqlite对象是否关闭*/ + .penaltyLog() + .penaltyDeath() + .build() + ); + } + + public static RefWatcher getRefWatcher(Context context) { + return instance().mRefWatcher; + } + + /** + * debug 环境 受到实验室模式影响 + */ + public static boolean isDebug() { + return Env.isDebug(); + } + + /** + * 是否是真实的debug的环境 不受实验室模式影响 + * + * @return + */ + public static boolean isRealDebug() { + return Env.isRealDebug(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/AudioRecordActivity.java b/app/src/main/java/com/yizhuan/erban/audio/AudioRecordActivity.java new file mode 100644 index 000000000..f457e580e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/AudioRecordActivity.java @@ -0,0 +1,383 @@ +package com.yizhuan.erban.audio; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Chronometer; + +import com.netease.nimlib.sdk.media.player.AudioPlayer; +import com.netease.nimlib.sdk.media.player.OnPlayListener; +import com.netease.nimlib.sdk.media.record.AudioRecorder; +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback; +import com.netease.nimlib.sdk.media.record.RecordType; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityAudiorecordBinding; +import com.yizhuan.xchat_android_core.audio.AudioPlayAndRecordManager; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import org.greenrobot.eventbus.EventBus; + +import java.io.File; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author zhouxiangfeng + * @date 2017/5/25 + */ +@ActLayoutRes(R.layout.activity_audiorecord) +public class AudioRecordActivity extends BaseBindingActivity { + + private static final String TAG = "AudioRecordActivity"; + + public static final String AUDIO_FILE = "AUDIO_FILE"; + public static final String AUDIO_DURA = "AUDIO_DURA"; + + private String audioUrl; + private AudioPlayer audioPlayer; + private AudioPlayAndRecordManager audioManager; + private AudioRecorder recorder; + + protected void init() { + audioManager = AudioPlayAndRecordManager.getInstance(); + audioPlayer = audioManager.getAudioPlayer(null, onPlayListener); + onSetListener(); + } + + private void onSetListener() { + mBinding.llRecord.setOnClickListener(this); + mBinding.ivTryListen.setOnClickListener(this); + mBinding.ivRetryRecord.setOnClickListener(this); + mBinding.ivRecordSave.setOnClickListener(this); + mBinding.ivRecord.setOnTouchListener((v, event) -> { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + RoomInfo current = AvRoomDataManager.get().mCurrentRoomInfo; + if (current != null) { + getDialogManager().showOkCancelDialog("当前正在房间无法录音,是否关闭房间?", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + AvRoomModel.get().exitRoom(null); + } + }); + } else { + startVoice(); + } + return true; + case MotionEvent.ACTION_UP: + audioManager.stopRecord(false); + return true; + default: + } + return false; + }); + + mBinding.imgBack.setOnClickListener(v -> finish()); + } + + private void startVoice() { + if (audioState == STATE_RECORD_RECORDING) { + toast("已经在录音..."); + } else if (audioState == STATE_RECORD_NORMAL) { + audioState = STATE_RECORD_RECORDING; + showByState(audioState); + startChronometer(); + recorder = audioManager.getAudioRecorder(AudioRecordActivity.this, onRecordCallback); + audioManager.startRecord(); + } + } + + private void startChronometer() { + mBinding.tvChronometer.setVisibility(View.VISIBLE); + mBinding.tvChronometer.setFormat(""); + value = -1; + mBinding.tvChronometer.setOnChronometerTickListener(chronometerTickListener); + mBinding.tvChronometer.setBase(0); + mBinding.tvChronometer.start(); + } + + + private int audioState = STATE_RECORD_NORMAL; + + public static final int STATE_RECORD_RECORDING = 1; + public static final int STATE_RECORD_SUCCESS = 2; + public static final int STATE_RECORD_NORMAL = 0; + + private File audioFile; + + private int audioDura; + + IAudioRecordCallback onRecordCallback = new IAudioRecordCallback() { + @Override + public void onRecordReady() { + Log.d(TAG, "onRecordReady"); + } + + @Override + public void onRecordStart(File file, RecordType recordType) { + Log.d(TAG, "onRecordStart : " + file.getPath() + "type: " + recordType.name()); + } + + @Override + public void onRecordSuccess(File file, long l, RecordType recordType) { + double dura = (double) l / 1000; + audioDura = (int) Math.round(dura); + Log.d(TAG, "onRecordSuccess : " + file.getPath() + "lenth :" + audioDura + "type : " + recordType.name()); + toast("录制完成"); + audioFile = file; + audioState = STATE_RECORD_SUCCESS; + showByState(audioState); + } + + @Override + public void onRecordFail() { + Log.d(TAG, "onRecordFail"); + toast("录制失败,录音时间过短"); + + audioState = STATE_RECORD_NORMAL; + showByState(audioState); + } + + @Override + public void onRecordCancel() { + Log.d(TAG, "onRecordCancel"); + audioState = STATE_RECORD_NORMAL; + showByState(audioState); + } + + @Override + public void onRecordReachedMaxTime(int i) { + Log.d(TAG, "onRecordReachedMaxTime"); + double dura = (double) i / 1000; + int max = (int) Math.round(dura); + toast("录音时间过长"); + } + }; + + private void showByState(int state) { + if (state == STATE_RECORD_NORMAL) { + + mBinding.ivRecord.setImageResource(R.drawable.icon_record); + mBinding.ivRecord.setVisibility(View.VISIBLE); + mBinding.ivRecordSave.setVisibility(View.GONE); + mBinding.tvState.setVisibility(View.VISIBLE); + mBinding.tvState.setText("长按录音"); + mBinding.tvChronometer.setVisibility(View.INVISIBLE); + mBinding.ivRetryRecord.setVisibility(View.GONE); + mBinding.ivTryListen.setVisibility(View.GONE); + + } else if (state == STATE_RECORD_RECORDING) { + + mBinding.ivRecord.setImageResource(R.drawable.icon_recording); + mBinding.ivRecord.setVisibility(View.VISIBLE); + mBinding.ivRecordSave.setVisibility(View.GONE); + mBinding.tvState.setVisibility(View.VISIBLE); + mBinding.tvState.setText("录制中"); + mBinding.tvChronometer.setVisibility(View.VISIBLE); + mBinding.ivRetryRecord.setVisibility(View.GONE); + mBinding.ivTryListen.setVisibility(View.GONE); + + } else if (state == STATE_RECORD_SUCCESS) { + mBinding.ivRecord.setVisibility(View.GONE); + mBinding.ivRecordSave.setVisibility(View.VISIBLE); + mBinding.tvState.setVisibility(View.INVISIBLE); + mBinding.ivRetryRecord.setVisibility(View.VISIBLE); + mBinding.tvChronometer.setVisibility(View.INVISIBLE); + mBinding.tvChronometer.stop(); + mBinding.ivTryListen.setVisibility(View.VISIBLE); + + } + } + + OnPlayListener onPlayListener = new OnPlayListener() { + + @Override + public void onPrepared() { + Log.d(TAG, "onPrepared"); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen_pause); + } + + @Override + public void onCompletion() { + Log.d(TAG, "onCompletion"); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen); + } + + @Override + public void onInterrupt() { + Log.d(TAG, "onInterrupt"); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen_pause); + } + + @Override + public void onError(String s) { + Log.d(TAG, "onError :" + s); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen); + } + + @Override + public void onPlaying(long l) { + Log.d(TAG, "onPlaying :" + l); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen_pause); + } + }; + + + @SuppressLint("CheckResult") + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_record: + break; + + case R.id.iv_retry_record: + audioState = STATE_RECORD_NORMAL; + showByState(audioState); + if (null != recorder) { + recorder.destroyAudioRecorder(); + recorder = null; + } + break; + case R.id.iv_try_listen: +// MLog.debug("result_url", "play audioFilePath: " + audioFile.getPath()); + if (!audioManager.isPlaying()) { + if (null != audioFile && audioFile.exists()) { + MLog.debug(TAG, "play audioFilePath: " + audioFile.getPath()); + audioPlayer.setDataSource(audioFile.getPath()); + audioManager.play(); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen_pause); + } + } else { + audioManager.stopPlay(); + mBinding.ivTryListen.setImageResource(R.drawable.icon_try_listen); + } + break; + case R.id.iv_record_save: + if (null != audioFile) { + Log.i("result_url", "upload before:" + audioFile.getAbsolutePath()); + getDialogManager().showProgressDialog(AudioRecordActivity.this, "请稍后..."); + FileModel.get() + .uploadFile(audioFile.getAbsolutePath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + break; + default: + } + } + + long value = -1; + + Chronometer.OnChronometerTickListener chronometerTickListener = new Chronometer.OnChronometerTickListener() { + + @Override + public void onChronometerTick(Chronometer chronometer) { + if (value == -1) { + // chronometer.setBase(0); // the base time value + value = chronometer.getBase(); + } else { + value++; // timer add + } + if (value > 10) { + audioManager.stopRecord(false); + return; + } + + String time; + if (value < 10) { + time = "00:0" + value; + } else { + time = "00:" + value; + } + chronometer.setText(time); + } + }; + + @Override + protected void onDestroy() { + if (audioManager.isPlaying()) { + audioManager.stopPlay(); + } + if (onPlayListener != null) { + onPlayListener = null; + } + if (audioPlayer != null) { + audioPlayer.setOnPlayListener(null); + } + if (audioManager != null) + audioManager.release(); + super.onDestroy(); + } + + private void onUpload(String url) { + audioUrl = url; + Log.i("result_url", "upload success:" + audioUrl); + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setUserVoice(audioUrl); + user.setVoiceDura(audioDura); + UserModel.get().requestUpdateUserInfo(user).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(UserInfo userInfo) { + onRequestUserInfoUpdate(); + } + + @Override + public void onError(Throwable e) { + onRequestUserInfoUpdateError(e.getMessage()); + } + }); + } + + private void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + private void onRequestUserInfoUpdate() { + audioState = STATE_RECORD_NORMAL; + showByState(audioState); + getDialogManager().dismissDialog(); + + Intent intent = new Intent(); + intent.putExtra(AUDIO_FILE, audioUrl); + intent.putExtra(AUDIO_DURA, audioDura); + setResult(RESULT_OK, intent); + finish(); + } + + private void onRequestUserInfoUpdateError(String error) { + toast(error); + getDialogManager().dismissDialog(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/MyVoiceActivity.java b/app/src/main/java/com/yizhuan/erban/audio/MyVoiceActivity.java new file mode 100644 index 000000000..6e4dee8c1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/MyVoiceActivity.java @@ -0,0 +1,231 @@ +package com.yizhuan.erban.audio; + +import android.Manifest; +import android.content.Intent; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.adapter.MyVoiceListAdapter; +import com.yizhuan.erban.audio.helper.AudioPlayerHelper; +import com.yizhuan.erban.audio.presenter.MyVoicePresenter; +import com.yizhuan.erban.audio.view.IMyVoiceView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.HorizontalDecoration; +import com.yizhuan.xchat_android_core.audio.bean.UserVoiceInfo; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.music.model.PlayerModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * 我的声音页面 + */ +@CreatePresenter(MyVoicePresenter.class) +public class MyVoiceActivity extends BaseMvpActivity + implements IMyVoiceView { + + public static final int REQUEST_CODE_RECORDING_VOICE = 1; + + @BindView(R.id.recycler_view) + RecyclerView recyclerView; + + private MyVoiceListAdapter adapter;// 审核通过列表 + private boolean isPlaying; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_my_voice); + ButterKnife.bind(this); + getMvpPresenter().attachMvpView(this); + + AudioPlayerHelper.get().onCreate(); + initTitleBar("我的声音"); + initView(); + getMvpPresenter().getUserVoiceInfo(); + } + + private void initView() { + if (adapter == null) { + adapter = new MyVoiceListAdapter(null); + } + recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + recyclerView.addItemDecoration(new HorizontalDecoration(UIUtil.dip2px(context, 15), false, false)); + recyclerView.setAdapter(adapter); + adapter.setOnVerifiedVoiceItemClickListener((isChange, voice) -> { + if (AudioPlayerHelper.get().isPlaying()) { + // 正在播放声音时:点了同一个声音,则停止播放;点了别的声音,则先停止播放 再播放新点击的声音 + stopVoice(); + isPlaying = false; + if (isChange) { + playVoice(voice); + } + } else { + isPlaying = true; + // 没有在播放声音时候,即正常状态 + playVoice(voice); + } + }); + adapter.setOnItemChildClickListener((adapter1, view, position) -> { + UserVoiceInfo item = (UserVoiceInfo) adapter1.getItem(position); + if (view.getId() == R.id.tv_re_recording) { + checkPermission(Manifest.permission.RECORD_AUDIO) + .subscribe(result -> { + if (result) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND_RERECORD, "我的声音-重新录制"); + UIHelper.showRecordVoiceAct(MyVoiceActivity.this, + MyVoiceActivity.REQUEST_CODE_RECORDING_VOICE, item.getId());// 点击跳转到录制声音页面 + } + }); + } + }); + } + + private void playVoice(String voice) { +// RtcEngineManager.get().setOpenVoiceMatchActivity(true); +// PlayerModel.get().pause(); + AudioPlayerHelper.get().playInThread(voice, new com.yizhuan.erban.audio.helper.OnPlayListener() { + @Override + public void onError(String error) { + if (adapter != null) { + adapter.changePlayState(false);// 播放出错 + } + } + + @Override + public void onPrepared() { + if (adapter != null) { + adapter.changePlayState(true);// 准备完毕开始播放 + } + } + + @Override + public void onPlaying(long currDuration) { + + } + + @Override + public void onCompletion() { +// RtcEngineManager.get().setOpenVoiceMatchActivity(false); +// PlayerModel.get().play(null); + if (adapter != null) { + adapter.changePlayState(false);// 播放完成 + } + } + }); + } + + private void stopVoice() { +// RtcEngineManager.get().setOpenVoiceMatchActivity(false); +// PlayerModel.get().play(null); + AudioPlayerHelper.get().endPlay(); + adapter.changePlayState(false);// 点击停止播放 + } + + @Override + public void initTitleBar(String title) { + mTitleBar = findViewById(R.id.title_bar); + if (mTitleBar != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && needSteepStateBar()) { + mTitleBar.setImmersive(true); + } else { + mTitleBar.setImmersive(false); + } + mTitleBar.setTitle(title); + mTitleBar.setBackgroundColor(Color.TRANSPARENT); + mTitleBar.setTitleColor(Color.WHITE); + mTitleBar.setLeftImageResource(R.drawable.arrow_left_white); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } + + @Override + public void showNoData() { + if (!checkActivityValid()) { + return; + } + View status = findViewById(R.id.status_layout); + if (status == null) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_green_with_button, + R.drawable.icon_common_failure_green, "你还没有录制声音哦,赶快去录制一个吧~", () -> { + checkPermission(Manifest.permission.RECORD_AUDIO) + .subscribe(result -> { + if (result) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND_RECORD, "我的声音-去录制"); + // 录制入口 + UIHelper.showRecordVoiceAct(this, REQUEST_CODE_RECORDING_VOICE, -1); + } + }); + }); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + protected void onPause() { + super.onPause(); + AudioPlayerHelper.get().onPause(); + adapter.changePlayState(false);// onPause() 停止播放 + } + + @Override + protected void onDestroy() { + super.onDestroy(); +// if (isPlaying) { +// PlayerModel.get().play(null); +// } +// RtcEngineManager.get().setOpenVoiceMatchActivity(false); + AudioPlayerHelper.get().onDestroy(); + adapter.changePlayState(false);// onDestroy() 停止播放 + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_CODE_RECORDING_VOICE) { + setResult(RESULT_OK, data);// 传给上一个 + getMvpPresenter().getUserVoiceInfo(); + } + } + } + + @Override + public void showVoiceInfo(List voiceList) { + if (ListUtils.isListEmpty(voiceList)) { + showNoData(); + } else { + hideStatus(); + adapter.setNewData(voiceList);// 审核通过列表 + } + } + + @Override + public void showLoadingView() { + getDialogManager().showProgressDialog(context, "请稍后..."); + } + + @Override + public void hideLoadingView() { + getDialogManager().dismissDialog(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/RecordingVoiceActivity.java b/app/src/main/java/com/yizhuan/erban/audio/RecordingVoiceActivity.java new file mode 100644 index 000000000..86bdf41dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/RecordingVoiceActivity.java @@ -0,0 +1,480 @@ +package com.yizhuan.erban.audio; + +import android.Manifest; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.util.Log; +import android.view.View; +import android.widget.Chronometer; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.audio.adapter.CardAdapter; +import com.yizhuan.erban.audio.helper.AudioPlayerHelper; +import com.yizhuan.erban.audio.presenter.RecordingVoicePresenter; +import com.yizhuan.erban.audio.view.IRecordingVoiceView; +import com.yizhuan.erban.audio.widget.OnSwipeListener; +import com.yizhuan.erban.audio.widget.RingProgressView; +import com.yizhuan.erban.audio.widget.VoiceCardConfig; +import com.yizhuan.erban.audio.widget.VoiceCardItemTouchHelperCallback; +import com.yizhuan.erban.audio.widget.VoiceCardLayoutManager; +import com.yizhuan.erban.audio.widget.VoiceCardRecyclerView; +import com.yizhuan.erban.audio.widget.VoiceWave; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.audio.bean.VoiceCardInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import butterknife.BindView; +import butterknife.ButterKnife; + +import static com.yizhuan.erban.audio.presenter.RecordingVoicePresenter.STATE_RECORD_NORMAL; +import static com.yizhuan.erban.audio.presenter.RecordingVoicePresenter.STATE_RECORD_RECORDING; +import static com.yizhuan.erban.audio.presenter.RecordingVoicePresenter.STATE_RECORD_SUCCESS; + +/** + * 录制声音页面 + */ +@CreatePresenter(RecordingVoicePresenter.class) +public class RecordingVoiceActivity extends BaseMvpActivity + implements IRecordingVoiceView, View.OnClickListener { + + public static final String EXTRA_VOICE_ID = "voice_id"; + + public static final String AUDIO_FILE = "AUDIO_FILE"; + public static final String AUDIO_DURA = "AUDIO_DURA"; + + /*时长限制:大于等于5s,小于等于60s*/ + public static final int MIN_RECORD_VOICE_DURATION = 5;// 最少5秒 + public static final int MAX_RECORD_VOICE_DURATION = 60;// 最多60秒 + + @BindView(R.id.recycler_view_card) + VoiceCardRecyclerView recyclerViewCard; + @BindView(R.id.tv_record_hint) + TextView tvRecordHint; + @BindView(R.id.tv_record_chronometer) + Chronometer tvRecordChronometer; + @BindView(R.id.tv_record_left_icon) + TextView tvRecordLeftIcon; + @BindView(R.id.view_progress) + RingProgressView viewProgress; + @BindView(R.id.iv_record_center_icon) + ImageView ivRecordCenterIcon; + @BindView(R.id.tv_record_right_icon) + TextView tvRecordRightIcon; + @BindView(R.id.voice_wave) + VoiceWave voiceWave; + + private CardAdapter cardAdapter; + private long lastClickTime; + private List voiceCardInfoList; + + private Drawable playDrawable, pauseDrawable; + private ItemTouchHelper touchHelper; + private VoiceCardItemTouchHelperCallback itemTouchHelperCallback; + + private long changeVoiceId = -1;// 被重新录制的声音的ID + private RecordingVoiceHandler voiceHandler; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_recording_voice); + ButterKnife.bind(this); + getMvpPresenter().attachMvpView(this); + + AudioPlayerHelper.get().onCreate(); + initTitleBar("录制声音"); + + initView(); + initData(); + setListener(); + } + + private void initView() { + lastClickTime = System.currentTimeMillis(); + voiceCardInfoList = new ArrayList<>(); + cardAdapter = new CardAdapter(voiceCardInfoList); + recyclerViewCard.setItemAnimator(new DefaultItemAnimator()); + recyclerViewCard.setAdapter(cardAdapter); + itemTouchHelperCallback = new VoiceCardItemTouchHelperCallback(); + itemTouchHelperCallback.setOnSwipedListener(new OnSwipeListener() { + @Override + public void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction) { + Log.e("OnSwipeListener", "onSwiping--->" + "VH = " + viewHolder + + " 滑动进度的比例 = " + ratio + + " 卡片的滑动方向 = " + (direction == VoiceCardConfig.SWIPING_LEFT ? "左边" : direction == VoiceCardConfig.SWIPING_RIGHT ? "右边" : "未知方向")); + viewHolder.itemView.setAlpha(1 - Math.abs(ratio) * 0.2f); + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int pos, int direction) { + Log.e("OnSwipeListener", "onSwiped--->" + "VH = " + viewHolder + + " 滑出去的卡片的索引 = " + pos + + " 卡片的滑动方向 = " + (direction == VoiceCardConfig.SWIPED_LEFT ? "左边" : direction == VoiceCardConfig.SWIPED_RIGHT ? "右边" : "未知方向")); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND_TEXT_SWITCH, "我的声音-切换文案"); + viewHolder.itemView.setAlpha(1f); + cardAdapter.removeItem(pos); + if (cardAdapter.getItemCount() < VoiceCardConfig.DEFAULT_SHOW_ITEM) { + recyclerViewCard.post(() -> getMvpPresenter().getCardInfo()); + } + } + }); + touchHelper = new ItemTouchHelper(itemTouchHelperCallback); + VoiceCardLayoutManager cardLayoutManager = new VoiceCardLayoutManager(recyclerViewCard, touchHelper); + recyclerViewCard.setLayoutManager(cardLayoutManager); + // 这里开始就把 它 自己的 onTouchListener 给 RecyclerView,然后用 GestureDetectorCompat 来处理那些分发下来的事件。 + // 也就是说要防止快速点击,1要防止按钮的快速点击 2要防止动画过程中 GestureDetectorCompat 继续响应你的快速点击手势 + // 1处理就直接disable那个按钮 2就是拦截掉 RecyclerView 的 onTouchEvent 方法 用 mLayoutFrozen 属性,直接用这个就行了 我试试看 + touchHelper.attachToRecyclerView(recyclerViewCard); + cardAdapter.setOnVoiceCardChangeButtonClickListener(new CardAdapter.OnVoiceCardChangeButtonClickListener() { + @Override + public void onVoiceCardChange(RecyclerView.ViewHolder viewHolder) { + long currTime = System.currentTimeMillis(); + if (currTime - lastClickTime < 1000) { + return; + } + lastClickTime = currTime; + recyclerViewCard.setLayoutFrozen(true); + recyclerViewCard.post(new Runnable() { + @Override + public void run() { + ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0.0F, 1.0F); + mValueAnimator.setTarget(viewHolder.itemView); + mValueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + touchHelper.startSwipe(viewHolder); + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + } + }); + mValueAnimator.addUpdateListener(valueAnimator -> { + float fraction = valueAnimator.getAnimatedFraction(); + if (fraction == 1) { + itemTouchHelperCallback.onSwiped(viewHolder, ItemTouchHelper.LEFT); + recyclerViewCard.setLayoutFrozen(false); + } else { + itemTouchHelperCallback.onChildDraw(recyclerViewCard.getCanvas(), + recyclerViewCard, viewHolder, + -viewHolder.itemView.getWidth() * fraction, + viewHolder.itemView.getTranslationY(), 1, false); + } + }); + mValueAnimator.setDuration(500); + mValueAnimator.start(); + } + }); + } + }); + + playDrawable = ContextCompat.getDrawable(context, R.drawable.ic_recording_listener); + pauseDrawable = ContextCompat.getDrawable(context, R.drawable.ic_recording_pause); + + refreshButtonView(STATE_RECORD_NORMAL); + } + + private void initData() { + if (getIntent() != null) { + changeVoiceId = getIntent().getLongExtra(EXTRA_VOICE_ID, changeVoiceId); + } + + getMvpPresenter().initResource(); + getMvpPresenter().getCardInfo(); + } + + private void setListener() { + tvRecordLeftIcon.setOnClickListener(this); + ivRecordCenterIcon.setOnClickListener(this); + tvRecordRightIcon.setOnClickListener(this); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = findViewById(R.id.title_bar); + if (mTitleBar != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && needSteepStateBar()) { + mTitleBar.setImmersive(true); + } else { + mTitleBar.setImmersive(false); + } + mTitleBar.setTitle(title); + mTitleBar.setBackgroundColor(Color.TRANSPARENT); + mTitleBar.setTitleColor(Color.WHITE); + mTitleBar.setLeftImageResource(R.drawable.arrow_left_white); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } + + @Override + protected void onLeftClickListener() { + getMvpPresenter().leaveThePage(); + } + + @Override + public void onBackPressed() { + onLeftClickListener();// 物理返回 + } + + @Override + protected void onPause() { + super.onPause(); + getMvpPresenter().pausePage(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getMvpPresenter().releaseResource(); + } + + @SuppressLint("CheckResult") + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.tv_record_left_icon) { + getMvpPresenter().reRecord(); + } else if (id == R.id.iv_record_center_icon) { + if (!(ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)) { + checkPermission(Manifest.permission.RECORD_AUDIO) + .subscribe(aBoolean -> { + if (aBoolean) { + getMvpPresenter().clickCenterIcon(); + } else { + toast("请给予应用必要权限,让程序可正常工作。"); + } + }); + return; + } + getMvpPresenter().clickCenterIcon(); + } else if (id == R.id.tv_record_right_icon) { + getMvpPresenter().clickRightIcon(); + } + } + + @Override + public void addCardInfo(List cardInfoList) { + voiceCardInfoList.addAll(cardInfoList); + cardAdapter.notifyDataSetChanged(); + } + + @Override + public Long getCardPiaId() { + VoiceCardInfo itemInfo = cardAdapter.getFistItemInfo(); + if (itemInfo == null) { + return null; + } else { + return itemInfo.getId(); + } + } + + @Override + public void refreshButtonView(int state) { + switch (state) { + case STATE_RECORD_NORMAL:// 正常默认情况下 + viewProgress.setVisibility(View.INVISIBLE); + ivRecordCenterIcon.post(() -> ivRecordCenterIcon.setImageResource(R.drawable.ic_recording)); + tvRecordHint.setText("按下录音"); + tvRecordHint.setVisibility(View.VISIBLE); + tvRecordChronometer.setVisibility(View.INVISIBLE); + tvRecordLeftIcon.setVisibility(View.INVISIBLE); + tvRecordRightIcon.setVisibility(View.INVISIBLE); + break; + case STATE_RECORD_RECORDING:// 正在录音时 + viewProgress.setVisibility(View.VISIBLE); + ivRecordCenterIcon.post(() -> ivRecordCenterIcon.setImageResource(R.drawable.ic_recording_end)); + tvRecordHint.setVisibility(View.GONE); + tvRecordChronometer.setVisibility(View.VISIBLE); + tvRecordLeftIcon.setVisibility(View.INVISIBLE); + tvRecordRightIcon.setVisibility(View.INVISIBLE); + break; + case STATE_RECORD_SUCCESS:// 已经录制时 + viewProgress.setVisibility(View.INVISIBLE); + ivRecordCenterIcon.post(() -> ivRecordCenterIcon.setImageResource(R.drawable.ic_recording_finish)); + tvRecordHint.setVisibility(View.GONE); + tvRecordChronometer.setVisibility(View.VISIBLE); + tvRecordLeftIcon.setVisibility(View.VISIBLE); + tvRecordRightIcon.post(() -> + tvRecordRightIcon.setCompoundDrawablesWithIntrinsicBounds(null, playDrawable, null, null)); + tvRecordRightIcon.setText("试听"); + tvRecordRightIcon.setVisibility(View.VISIBLE); + break; + } + } + + @Override + public void refreshListenerButton(boolean isPlaying) { + tvRecordRightIcon.setText(isPlaying ? "暂停" : "试听"); + tvRecordRightIcon.post(() -> + tvRecordRightIcon.setCompoundDrawablesWithIntrinsicBounds(null, isPlaying ? pauseDrawable : playDrawable, null, null)); + } + + @Override + public void startChronometer() { + tvRecordHint.setVisibility(View.GONE); + tvRecordChronometer.setVisibility(View.VISIBLE); +// tvRecordChronometer.setFormat(""); + tvRecordChronometer.setOnChronometerTickListener(chronometer -> { + long elapsedMillis = SystemClock.elapsedRealtime() - chronometer.getBase(); + int second = (int) (elapsedMillis / 1000); + String showStr = String.format(Locale.getDefault(), "%ds / %ds", second, MAX_RECORD_VOICE_DURATION); + chronometer.setText(showStr); +// Log.e("RecordingView", "elapsedMillis = " + elapsedMillis +// + " second = " + second +// + " show = " + showStr); + viewProgress.post(() -> { + int currentProgress = 100 * second / MAX_RECORD_VOICE_DURATION; + viewProgress.setCurrentProgress(currentProgress); + }); + + if (second >= MAX_RECORD_VOICE_DURATION) { + getMvpPresenter().stopRecord();// 录制时长超过上限时,停止录制 + } + + }); + tvRecordChronometer.setBase(SystemClock.elapsedRealtime()); + tvRecordChronometer.start(); + } + + @Override + public void stopChronometer() { + tvRecordChronometer.stop(); + } + + @Override + public void showConfirmDialogWithLeave() { + getDialogManager().showOkCancelDialog("提示", + getString(R.string.voice_tips_save_voice), + "继续录音", "确认返回", false, true, new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + + } + + @Override + public void onCancel() { + finishView(null);// 声音未保存确认退出页面 + } + }); + } + + @Override + public void finishView(Intent intent) { + if (intent != null) { + setResult(RESULT_OK, intent); + } + finish(); + } + + @Override + public void showConfirmDialogWithExitRoom() { + getDialogManager().showOkCancelDialog("当前正在房间无法录音,是否关闭房间?", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + AvRoomModel.get().exitRoom(null); + } + }); + } + + @Override + public void showLoadingView() { + runOnUiThread(() -> getDialogManager().showProgressDialog(context, "请稍后...")); + } + + @Override + public void hideLoadingView() { + runOnUiThread(() -> getDialogManager().dismissDialog()); + } + + @Override + public Long getChangeVoiceId() { + if (changeVoiceId == -1) { + return null; + } + return changeVoiceId; + } + + @Override + public void refreshVoiceWave(double db) { + if (voiceHandler != null) { + voiceHandler.sendEmptyMessage((int) db); + } + } + + @Override + public void showVoiceWave() { + voiceWave.setVisibility(View.VISIBLE); + voiceWave.startAnim(); + voiceHandler = new RecordingVoiceHandler(this); + // 解决了内存泄漏,延迟5分钟后发送 + voiceHandler.sendEmptyMessage(0); + } + + @Override + public void hideVoiceWave() { + voiceWave.stopAnim(); + voiceWave.setVisibility(View.INVISIBLE); + if (voiceHandler != null) { + voiceHandler.removeCallbacksAndMessages(null); + } + } + + @Override + public void showCountDown(int duration) { + tvRecordChronometer.setVisibility(View.VISIBLE); + String showStr = String.format(Locale.getDefault(), "%ds / %ds", duration, MAX_RECORD_VOICE_DURATION); + tvRecordChronometer.setText(showStr); + } + + private static class RecordingVoiceHandler extends Handler { + // 持有弱引用 Activity,GC回收时会被回收掉. + private final WeakReference mActivity; + + RecordingVoiceHandler(RecordingVoiceActivity activityWeakReference) { + mActivity = new WeakReference<>(activityWeakReference); + } + + @Override + public void handleMessage(Message msg) { + RecordingVoiceActivity activity = mActivity.get(); + super.handleMessage(msg); + if (activity != null) { + activity.voiceWave.setVolume(msg.what); + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/VoiceMatchActivity.java b/app/src/main/java/com/yizhuan/erban/audio/VoiceMatchActivity.java new file mode 100644 index 000000000..33a246e41 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/VoiceMatchActivity.java @@ -0,0 +1,681 @@ +package com.yizhuan.erban.audio; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.constraint.Group; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.TranslateAnimation; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGAImageView; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.helper.AudioPlayerHelper; +import com.yizhuan.erban.audio.helper.OnPlayListener; +import com.yizhuan.erban.audio.helper.OnRefreshListener; +import com.yizhuan.erban.audio.helper.SvgaCacheManager; +import com.yizhuan.erban.audio.helper.VmSoundManager; +import com.yizhuan.erban.audio.helper.VoiceMacthHelper; +import com.yizhuan.erban.audio.view.BottleContainer; +import com.yizhuan.erban.audio.view.IBottleOpListener; +import com.yizhuan.erban.audio.widget.VoiceBottleFilterGenderBottomDialog; +import com.yizhuan.erban.audio.widget.VoiceLine; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.xchat_android_core.audio.AudioModel; +import com.yizhuan.xchat_android_core.audio.bean.HistoryVoiceInfo; +import com.yizhuan.xchat_android_core.audio.bean.VoiceMatchInfo; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.music.model.PlayerModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; + + +/** + * create by lvzebiao @2019/6/6 + */ +public class VoiceMatchActivity extends BaseActivity implements View.OnClickListener { + + public static final String KEY_VOICE_MUST_LIMIT = "voice_must_limit_";// 是否受限,限制喜欢和不喜欢3次 + public static final String KEY_VOICE_LIMIT_COUNT = "voice_limit_count_of_";// 限制不喜欢的次数 + public static final int REQUEST_CODE_RECORDING_VOICE_WITH_HAS_LIMIT = 1; + public static final int REQUEST_CODE_RECORDING_VOICE_WITH_SYNC_HISTORY_VOICE = 2; + public static final int REQUEST_CODE_RECORDING_VOICE_WITH_MY_VOICE = 3; + + @BindView(R.id.title_bar) + TitleBar titleBar; + @BindView(R.id.fl_group_content) + BottleContainer bottleContainer; + @BindView(R.id.fl_status_parent) + FrameLayout flStatusParent; + @BindView(R.id.iv_group_dont_like) + ImageView ivDontLike; + @BindView(R.id.iv_group_like) + ImageView ivLike; + @BindView(R.id.group_voice_layout) + Group groupVoiceLayout; + @BindView(R.id.svga_group_voice_like) + SVGAImageView svgaGroupVoiceLike; + @BindView(R.id.layout_my_voice_entrance) + FrameLayout layoutMyVoiceEntrance; + @BindView(R.id.tv_my_voice_entrance) + TextView tvMyVoiceEntrance; + + private ImageView playIcon; + private VoiceLine voiceLine; + + private boolean isLoading; + private boolean isFirst;// 记录是否首次进入页面 + + private VoiceMacthHelper helper = new VoiceMacthHelper(); + + private int filterGender;// 当前筛选的性别 + private VoiceBottleFilterGenderBottomDialog filterGenderBottomDialog; + private TranslateAnimation showAnim; + private AlphaAnimation alphaAnimation; + + public static void start(Context context) { + Intent intent = new Intent(context, VoiceMatchActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_voice_match); + ButterKnife.bind(this); + VmSoundManager.get().onCreate(); + AudioPlayerHelper.get().onCreate(); + SvgaCacheManager.get().onCreate(); + initTitleBar("声音瓶子", true); + + initView(); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + hideStatus(); + toast("用户信息为空,请重新登录"); + finish(); + return; + } + int oppositeGender = userInfo.getGender() == 1 ? 2 : 1; + filterGender = (int) SharedPreferenceUtils.get("voice_match_filter_gender_" + AuthModel.get().getCurrentUid(), oppositeGender); + isFirst = true; + loadingData(filterGender);// 进入页面加载数据 + + /*展示我的声音的入口动画*/ + showMyVoiceEntranceAnim(); + + layoutMyVoiceEntrance.setOnClickListener(this); + + bottleContainer.setOpListener(new IBottleOpListener() { + + @Override + public void onLimit(boolean isRight) { + showDialogWithHasLimit(isRight); + } + + @Override + public void onLikeOrUnLike(VoiceMatchInfo info, boolean isRight, boolean needLoading) { + if (needLoading) { + groupVoiceLayout.setVisibility(View.INVISIBLE); + } + likeOrUnlikeVoice(info, isRight, needLoading); + playLikeOrUnLikeBtnAnim(isRight, false); + } + }); + } + + private void initView() { + ivDontLike.setOnClickListener(this); + svgaGroupVoiceLike.setOnClickListener(this); + } + + private void showMyVoiceEntranceAnim() { + if (layoutMyVoiceEntrance.getAnimation() != null) { + layoutMyVoiceEntrance.getAnimation().cancel(); + layoutMyVoiceEntrance.clearAnimation(); + } + if (tvMyVoiceEntrance.getAnimation() != null) { + tvMyVoiceEntrance.getAnimation().cancel(); + tvMyVoiceEntrance.clearAnimation(); + } + layoutMyVoiceEntrance.post(() -> { + if (showAnim == null) { + int width = layoutMyVoiceEntrance.getWidth(); + showAnim = new TranslateAnimation(0, width / 3 * 1.8f, 1, 1); + showAnim.setStartOffset(2000); + showAnim.setDuration(600); + showAnim.setInterpolator(new AccelerateDecelerateInterpolator()); + showAnim.setFillAfter(true); + } + if (alphaAnimation == null) { + alphaAnimation = new AlphaAnimation(1, 0); + alphaAnimation.setStartOffset(2000); + alphaAnimation.setDuration(600); + alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); + alphaAnimation.setFillAfter(true); + } + layoutMyVoiceEntrance.startAnimation(showAnim); + tvMyVoiceEntrance.startAnimation(alphaAnimation); + }); + } + + /** + * 显示引导图的时机 + * 1. 首次进入页面(isNeedHiGuide) + * 2. 请求数据且数据不为空时 + */ + private void showGuide() { + /*引导图*/ + svgaGroupVoiceLike.postDelayed(() -> { + if (!ActivityUtil.isValidContext(context)) { + return; + } + TuTuGuideHelper guideHelper = new TuTuGuideHelper(context); + guideHelper.createHiGuide(() -> guideHelper.createVoiceMatchGuide(svgaGroupVoiceLike, layoutMyVoiceEntrance)); + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_VOICE_MATCH); + }, 500); + } + + private void queryHistoryVoice() { + AudioModel.get().queryHistoryVoice(AuthModel.get().getCurrentUid()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(HistoryVoiceInfo historyVoiceInfo, String error) { + super.accept(historyVoiceInfo, error); + if (error == null) { + if (historyVoiceInfo != null) { + HistoryVoiceInfo.HistoryVoiceBean historyVoice = historyVoiceInfo.getHistoryVoice();// 是否在旧版录制过打招呼 + boolean hasVoice = historyVoiceInfo.isHasVoice();// 是否已录制声音,包括待审核、审核通过 + if (historyVoice != null) {// 存在旧版的个人介绍声音:是否使用原来的打招呼或重新录制 + showDialogWithSyncHistoryVoice(historyVoice); + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true);// 存在旧版个人介绍声音,设置受限 + } else {// 没有在旧版的打招呼中录制过声音 + if (hasVoice) {// 录制过声音 + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), false);// 没有在旧版录制过个人介绍 且 录制过声音瓶子,设置不受限 + } else {// 没有录制过声音 + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true);// 没有在旧版录制过个人介绍 且 没有录制过声音瓶子,设置受限 + } + } + } else { + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true);// 请求成功但返回数据为空,设置受限 + } + } else { + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true);// 请求失败,设置受限 + } + } + }); + } + + private void showDialogWithSyncHistoryVoice(HistoryVoiceInfo.HistoryVoiceBean voiceInfo) { + VmSoundManager.get().onPause(null);// 显示弹框的时候 暂停播放 + // 弹窗:是否使用原来的打招呼或重新录制 + View syncHistoryVoiceView = LayoutInflater.from(context).inflate(R.layout.dialog_custom_voice_match_sync_history_voice, null); + LinearLayout voiceBar = syncHistoryVoiceView.findViewById(R.id.layout_voice_bar); + playIcon = syncHistoryVoiceView.findViewById(R.id.iv_voice_bar_play); + if (voiceLine != null) { + voiceLine.stopAnim(); + } + voiceLine = syncHistoryVoiceView.findViewById(R.id.layout_voice_line); + TextView voiceDuration = syncHistoryVoiceView.findViewById(R.id.tv_voice_duration); + voiceDuration.setText(String.format(Locale.getDefault(), "%ds", voiceInfo.getVoiceLength())); + + voiceBar.setOnClickListener(view -> { + VmSoundManager.get().onPause(status -> { + if (status == VmSoundManager.ConstantStatus.playing || + status == VmSoundManager.ConstantStatus.preparing) { + bottleContainer.onlySetPlayOrStopIconForBigBottle(true); + } + }); + if (AudioPlayerHelper.get().isPlaying()) { + stopVoice(); + } else { + playVoice(voiceInfo.getVoiceUrl()); + } + }); + getDialogManager().showOkCancelCustomDialog(syncHistoryVoiceView, "确定使用", "重新录制", + false, new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + // 确定使用旧版打招呼的声音上传到声音瓶子 + stopVoice(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_USE_OLD_POP, "声音瓶子-询问使用弹窗-确定使用"); + syncHistoryVoice(voiceInfo.getId()); + } + + @Override + public void onCancel() { + // 跳转到录制页面 + //跳转界面时停止播放声音 + stopVoice(); + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_USE_OLD_POP, "声音瓶子-询问使用弹窗-重新录制"); + UIHelper.showRecordVoiceAct(VoiceMatchActivity.this, REQUEST_CODE_RECORDING_VOICE_WITH_SYNC_HISTORY_VOICE, voiceInfo.getId()); + + } + }); + } + + private void playVoice(String voice) { + AudioPlayerHelper.get().playInThread(voice, new OnPlayListener() { + @Override + public void onError(String error) { + refreshVoiceBarLayout(false);// 播放出错 + } + + @Override + public void onPrepared() { + refreshVoiceBarLayout(true);// 准备完毕开始播放 + } + + @Override + public void onPlaying(long currDuration) { + + } + + @Override + public void onCompletion() { + refreshVoiceBarLayout(false);// 播放完成 + } + }); + } + + private void stopVoice() { + AudioPlayerHelper.get().endPlay(); + refreshVoiceBarLayout(false);// 点击停止播放 + } + + private void refreshVoiceBarLayout(boolean isPlaying) { + if (playIcon != null) { + playIcon.post(() -> + // 切换图标 + playIcon.setImageResource(isPlaying ? + R.drawable.ic_voice_bar_pause : R.drawable.ic_voice_bar_play)); + } + if (voiceLine != null) { + voiceLine.stopAnim(); + if (isPlaying) { + voiceLine.startAnim(); + } else { + voiceLine.stopAnim(); + } + } + } + + private void syncHistoryVoice(long voiceId) { + getDialogManager().showProgressDialog(context, "正在提交...", false); + AudioModel.get().syncHistoryVoice(AuthModel.get().getCurrentUid(), voiceId) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error == null) { + getDialogManager().dismissDialog(); + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), false);// 同步历史声音到瓶子成功,设置不受限 + } else { + getDialogManager().dismissDialog(); + SingleToastUtil.showToast(error); + } + } + }); + VmSoundManager.get().onResume(status -> { + if (status == VmSoundManager.ConstantStatus.playing || + status == VmSoundManager.ConstantStatus.preparing) { + bottleContainer.onlySetPlayOrStopIconForBigBottle(false); + } + }); + } + + @Override + public void initTitleBar(String title, boolean whiteModel) { + super.initTitleBar(title, whiteModel); + titleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_voice_match_filter_gender) { + @Override + public void performAction(View view) { + if (isLoading) { + return; + } + // 筛选性别 + if (filterGenderBottomDialog == null) { + filterGenderBottomDialog = new VoiceBottleFilterGenderBottomDialog(context, filterGender, gender -> { + String label = gender == 1 ? "男生" : gender == 2 ? "女生" : "不限"; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_CHOICE_SEX, "声音瓶子-选择性别-" + label); + + filterGender = gender; + SharedPreferenceUtils.put("voice_match_filter_gender_" + AuthModel.get().getCurrentUid(), filterGender); + //重新加载数据时,停止掉声音播放 + VmSoundManager.get().getHelper().endPlay(); + loadingData(gender);// 筛选性别 重新加载数据 + }); + } + filterGenderBottomDialog.show(); + } + }); + } + + /** + * @param filterGender 1:男 2:女 + */ + private void loadingData(int filterGender) { + if (isLoading) { + return; + } + groupVoiceLayout.setVisibility(View.INVISIBLE); + showVoiceStatusLoadingView(); + isLoading = true; + + SvgaCacheManager.get().initSvga(context) + .observeOn(AndroidSchedulers.mainThread()) + .flatMap((Function>>) + s -> AudioModel.get().getVoiceMatchList(filterGender, 10)) + .delay(300, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List voiceMatchInfos, String error) { + super.accept(voiceMatchInfos, error); + if (isFinishing() || isDestroyed()) { + return; + } + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_VOICE_MATCH) + && !ListUtils.isListEmpty(voiceMatchInfos)) { + showGuide();// 首次进入页面(isNeedHiGuide)且 请求成功数据不为空时,显示引导图 + } + if (voiceMatchInfos != null) { + if (voiceMatchInfos.size() == 0) { + groupVoiceLayout.setVisibility(View.INVISIBLE); + showVoiceStatusView(new VoiceRefreshListener(), R.drawable.icon_voice_no_bottle, "暂时还没有更多声音瓶子"); + } else { + hideVoiceStatusView(); + groupVoiceLayout.setVisibility(View.VISIBLE); + bottleContainer.initData(voiceMatchInfos); + } + } else { + groupVoiceLayout.setVisibility(View.INVISIBLE); + showVoiceStatusView(new VoiceRefreshListener(), R.drawable.icon_voice_net_error, "网络出问题了"); + } + if (isFirst) { + queryHistoryVoice(); + isFirst = false; + } + isLoading = false; + } + }); + } + + /** + * 状态页面:网络出错 / 无数据 + */ + private void showVoiceStatusView(OnRefreshListener listener, int statusImageId, String statusText) { + hideVoiceStatusView(); + View view = View.inflate(context, R.layout.fragment_voice_status, null); + ImageView ivStatusImage = view.findViewById(R.id.iv_status_image); + ivStatusImage.setImageResource(statusImageId); + TextView tvStatusText = view.findViewById(R.id.tv_status_text); + tvStatusText.setText(statusText); + View stvRefresh = view.findViewById(R.id.stv_refresh); + if (listener != null) { + stvRefresh.setVisibility(View.VISIBLE); + stvRefresh.setOnClickListener(v -> listener.refresh()); + } else { + stvRefresh.setVisibility(View.GONE); + } + flStatusParent.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + + + private VoiceLine loadingLine; + + private void releaseLoadingLine() { + if (loadingLine != null) { + loadingLine.stopAnim(); + } + } + + /** + * 状态页:正在加载 + */ + private void showVoiceStatusLoadingView() { + hideVoiceStatusView(); + View view = View.inflate(context, R.layout.fragment_voice_status_loading, null); + releaseLoadingLine(); + loadingLine = view.findViewById(R.id.voice_line); + loadingLine.post(loadingLine::startAnim); + TextView tvStatusText = view.findViewById(R.id.tv_status_text); + tvStatusText.setText("努力捕获声音瓶子…"); + flStatusParent.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + + /** + * 清除状态页 + */ + private void hideVoiceStatusView() { + flStatusParent.removeAllViews(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + bottleContainer.onDestroy(); + + VmSoundManager.get().onDestroy(); + AudioPlayerHelper.get().onDestroy(); + SvgaCacheManager.get().onDestroy(); + + if (showAnim != null) { + showAnim.cancel(); + showAnim = null; + } + if (alphaAnimation != null) { + alphaAnimation.cancel(); + alphaAnimation = null; + } + releaseLoadingLine(); + if (voiceLine != null) { + voiceLine.stopAnim(); + } + } + + private void toNext(boolean isLike) { + boolean isLimit = (boolean) SharedPreferenceUtils.get(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true); + if (isLimit) { + bottleContainer.dealBigBottleLimit(isLike); + } else { + playLikeOrUnLikeBtnAnim(isLike, true); + } + } + + + private void playLikeOrUnLikeBtnAnim(boolean isLike, boolean isNeedDealToNext) { + if (!isLike) { + //播放不喜欢按钮的属性动画 + if (helper.isDontLikeAnimRun()) { + return; + } + helper.playDontLikeAnim(ivDontLike); + } else { + if (svgaGroupVoiceLike.isAnimating()) { + return; + } + bottleContainer.addBigBottleLikeCount(); + helper.playDontLikeAnim(ivLike); + //播放喜欢按钮的svga动画 + svgaGroupVoiceLike.startAnimation(); + svgaGroupVoiceLike.setCallback(new SVGACallback() { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + }); + } + if (isNeedDealToNext) { + bottleContainer.dealToNext(isLike); + } + + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.layout_my_voice_entrance: + if (isLoading) { + return; + } + UIHelper.showMyVoiceAct(VoiceMatchActivity.this, REQUEST_CODE_RECORDING_VOICE_WITH_MY_VOICE, "声音瓶子");// 跳转到我的声音页面 + break; + case R.id.iv_group_dont_like: + toNext(false); + break; + case R.id.svga_group_voice_like: + toNext(true); + break; + } + + } + + private void showDialogWithHasLimit(boolean isRight) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_RECORD_POP, isRight ? "声音瓶子-去录制弹窗-喜欢" : "声音瓶子-去录制弹窗-不喜欢"); + String showMessage; + if (isRight) { + showMessage = "想要进一步了解Ta\n需要先录制一个声音哦~"; + } else { + showMessage = "想要捡更多声音瓶子\n需要先录制一个声音哦~"; + } + getDialogManager().showTipsDialog(showMessage, "去录制", () -> { + // 跳转到录制页面 + UIHelper.showRecordVoiceAct(VoiceMatchActivity.this, REQUEST_CODE_RECORDING_VOICE_WITH_HAS_LIMIT, -1); + }); + } + + private void likeOrUnlikeVoice(VoiceMatchInfo info, boolean isRight, boolean needLoading) { + if (isRight) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_LIKE, "声音瓶子-喜欢"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_UNLIKE, "声音瓶子-不喜欢"); + } + AudioModel.get().likeOrUnlikeVoice(AuthModel.get().getCurrentUid(), info.getId(), isRight ? 1 : 0) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (needLoading) { + loadingData(filterGender); + } + if (error == null) { + if (isRight) { + NimP2PMessageActivity.start(context, String.valueOf(info.getUid()), true); + } + } + } + }); + } + + + public class VoiceRefreshListener implements OnRefreshListener { + + @Override + public void refresh() { + loadingData(filterGender);// 状态页面刷新一下 重新加载数据 + } + } + + @Override + protected void onResume() { + super.onResume(); + RtcEngineManager.get().setOpenVoiceMatchActivity(true); + PlayerModel.get().pause(); + VmSoundManager.get().onResume(status -> { + if (status == VmSoundManager.ConstantStatus.playing || + status == VmSoundManager.ConstantStatus.preparing) { + bottleContainer.onlySetPlayOrStopIconForBigBottle(false); + } + }); + } + + @Override + protected void onPause() { + super.onPause(); + RtcEngineManager.get().setOpenVoiceMatchActivity(false); + PlayerModel.get().play(null); + VmSoundManager.get().onPause(status -> { + if (status == VmSoundManager.ConstantStatus.playing || + status == VmSoundManager.ConstantStatus.preparing) { + bottleContainer.onlySetPlayOrStopIconForBigBottle(true); + } + }); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE_RECORDING_VOICE_WITH_MY_VOICE) { + showMyVoiceEntranceAnim(); + } + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_CODE_RECORDING_VOICE_WITH_HAS_LIMIT && data != null) { + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), false);// 录制完声音,重置不受限制 + } else if (requestCode == REQUEST_CODE_RECORDING_VOICE_WITH_MY_VOICE && data != null) { + SharedPreferenceUtils.put(KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), false);// 录制完声音,重置不受限制 + } + } + if (requestCode == REQUEST_CODE_RECORDING_VOICE_WITH_SYNC_HISTORY_VOICE) { + queryHistoryVoice();// 重新查询是否有历史声音 + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/adapter/CardAdapter.java b/app/src/main/java/com/yizhuan/erban/audio/adapter/CardAdapter.java new file mode 100644 index 000000000..79bcee410 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/adapter/CardAdapter.java @@ -0,0 +1,119 @@ +package com.yizhuan.erban.audio.adapter; + +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.text.method.ScrollingMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.audio.bean.VoiceCardInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + * 录制声音页面的声音卡片 + */ +public class CardAdapter extends RecyclerView.Adapter { + + private List dataList; + + private OnVoiceCardChangeButtonClickListener onVoiceCardChangeButtonClickListener; + + public CardAdapter(List cardInfoList) { + if (cardInfoList == null) { + cardInfoList = new ArrayList<>(); + } + this.dataList = cardInfoList; + } + + @NonNull + @Override + public CardVH onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_voice_card, viewGroup, false); + return new CardVH(itemView); + } + + @Override + public void onBindViewHolder(@NonNull CardVH cardVH, int i) { + if (dataList.get(i) == null) { + return; + } + if (i == 0) { + cardVH.layout.setAlpha(1); + cardVH.title.setAlpha(1); + cardVH.content.setAlpha(1); + } else if (i == 1) { + cardVH.layout.setAlpha(0.5f); + cardVH.title.setAlpha(0); + cardVH.content.setAlpha(0); + } else if (i == 2) { + cardVH.layout.setAlpha(0.3f); + cardVH.title.setAlpha(0); + cardVH.content.setAlpha(0); + } else { + cardVH.layout.setAlpha(0); + cardVH.title.setAlpha(0); + cardVH.content.setAlpha(0); + } + cardVH.title.setText(dataList.get(i).getTitle()); + cardVH.content.setText(dataList.get(i).getPlayBook()); + cardVH.changeButton.setVisibility(i == 0 ? View.VISIBLE : View.GONE); + cardVH.changeButton.setOnClickListener(view -> { + if (onVoiceCardChangeButtonClickListener != null) { + onVoiceCardChangeButtonClickListener.onVoiceCardChange(cardVH); + } + }); + cardVH.content.post(() -> { + // 超过五行显示阴影 + cardVH.shadow.setVisibility(cardVH.content.getLineCount() > 5 ? View.VISIBLE : View.GONE); + }); + } + + @Override + public int getItemCount() { + return dataList.size(); + } + + public void removeItem(int pos) { + dataList.remove(pos); + notifyDataSetChanged(); + } + + public VoiceCardInfo getFistItemInfo() { + return dataList.get(0); + } + + public class CardVH extends RecyclerView.ViewHolder { + + FrameLayout layout; + TextView title; + TextView content; + RelativeLayout changeButton; + View shadow; + + CardVH(@NonNull View itemView) { + super(itemView); + layout = itemView.findViewById(R.id.layout_voice_card); + title = itemView.findViewById(R.id.tv_voice_card_title); + content = itemView.findViewById(R.id.tv_voice_card_content); + changeButton = itemView.findViewById(R.id.layout_voice_card_change); + shadow = itemView.findViewById(R.id.iv_voice_card_bottom_shadow); + + content.setMovementMethod(ScrollingMovementMethod.getInstance()); + } + } + + public interface OnVoiceCardChangeButtonClickListener { + void onVoiceCardChange(RecyclerView.ViewHolder viewHolder); + } + + public void setOnVoiceCardChangeButtonClickListener(OnVoiceCardChangeButtonClickListener onVoiceCardChangeButtonClickListener) { + this.onVoiceCardChangeButtonClickListener = onVoiceCardChangeButtonClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/adapter/MyVoiceListAdapter.java b/app/src/main/java/com/yizhuan/erban/audio/adapter/MyVoiceListAdapter.java new file mode 100644 index 000000000..d1b46e554 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/adapter/MyVoiceListAdapter.java @@ -0,0 +1,260 @@ +package com.yizhuan.erban.audio.adapter; + +import android.support.annotation.Nullable; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.audio.widget.VoiceLine; +import com.yizhuan.xchat_android_core.audio.bean.UserVoiceInfo; +import com.yizhuan.xchat_android_core.utils.StringUtils; + +import java.util.List; +import java.util.Locale; + +/** + * 我的声音.审核通过状态的列表 + */ +public class MyVoiceListAdapter extends BaseQuickAdapter { + + private OnVerifiedVoiceItemClickListener onVerifiedVoiceItemClickListener; + private boolean isPlayingVoice; + private int voiceClickPos = -1; + + private static final int TYPE_IN_REVIEW = 0; + private static final int TYPE_VERIFIED = 1; + private static final int TYPE_NO_SUBMITTED = 2; + + public MyVoiceListAdapter(@Nullable List data) { + super(data); + } + + @Override + public int getItemViewType(int position) { + UserVoiceInfo item = getItem(position); + if (item == null) { + return TYPE_NO_SUBMITTED; + } else { + return item.getStatus(); + } + } + + @Override + protected BaseViewHolder onCreateDefViewHolder(ViewGroup parent, int viewType) { + if (viewType == TYPE_IN_REVIEW) { + return onCreateViewHolderWithInReview(parent); + } else if (viewType == TYPE_VERIFIED) { + return onCreateViewHolderWithVerified(parent); + } else { + return onCreateViewHolderWithNoSubmitted(parent); + } + } + + private BaseViewHolder onCreateViewHolderWithInReview(ViewGroup parent) { + return new InReviewViewHolder(mLayoutInflater.inflate(R.layout.item_my_voice_in_review, parent, false)); + } + + private BaseViewHolder onCreateViewHolderWithVerified(ViewGroup parent) { + return new VerifiedViewHolder(mLayoutInflater.inflate(R.layout.item_my_voice_verified, parent, false)); + } + + private BaseViewHolder onCreateViewHolderWithNoSubmitted(ViewGroup parent) { + return new NoSubmittedViewHolder(mLayoutInflater.inflate(R.layout.item_my_voice_no_submitted, parent, false)); + } + + @Override + protected void convert(BaseViewHolder helper, UserVoiceInfo item) { + if (item == null) { + return; + } + if (helper instanceof InReviewViewHolder) { + onBindViewHolderWithInReview((InReviewViewHolder) helper, item); + } else if (helper instanceof VerifiedViewHolder) { + onBindViewHolderWithVerified((VerifiedViewHolder) helper, item); + } else if (helper instanceof NoSubmittedViewHolder) { + onBindViewHolderWithNoSubmitted((NoSubmittedViewHolder) helper, item); + } + } + + private void onBindViewHolderWithInReview(InReviewViewHolder helper, UserVoiceInfo item) { + helper.tvDuration.setText(String.format(Locale.getDefault(), "%ds", item.getVoiceLength()));// 声音时长 + // 播放动画 + if (helper.voiceLine != null) { + helper.voiceLine.stopAnim(); + } + helper.ivVoicePlay.post(() -> { + if (helper.getAdapterPosition() == voiceClickPos) { + if (isPlayingVoice) { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_pause); + helper.voiceLine.startAnim(); + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + }); + // 点击播放声音/停止声音 + helper.voiceBarLayout.setOnClickListener(view -> { + if (StringUtils.isEmpty(item.getVoiceUrl())) { + return; + } + boolean isChange = helper.getAdapterPosition() != voiceClickPos; + voiceClickPos = helper.getAdapterPosition(); + if (onVerifiedVoiceItemClickListener != null) { + onVerifiedVoiceItemClickListener.onVoiceClick(isChange, item.getVoiceUrl()); + } + }); + // 点击重新录制:跳转到录制声音页面 + helper.addOnClickListener(helper.tvReRecord.getId()); + } + + private void onBindViewHolderWithVerified(VerifiedViewHolder helper, UserVoiceInfo item) { + helper.tvDuration.setText(String.format(Locale.getDefault(), "%ds", item.getVoiceLength()));// 声音时长 + // 播放动画 + if (helper.voiceLine != null) { + helper.voiceLine.stopAnim(); + } + helper.ivVoicePlay.post(() -> { + if (helper.getAdapterPosition() == voiceClickPos) { + if (isPlayingVoice) { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_pause); + helper.voiceLine.startAnim(); + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + }); + // 点击播放声音/停止声音 + helper.voiceBarLayout.setOnClickListener(view -> { + if (StringUtils.isEmpty(item.getVoiceUrl())) { + return; + } + boolean isChange = helper.getAdapterPosition() != voiceClickPos; + voiceClickPos = helper.getAdapterPosition(); + if (onVerifiedVoiceItemClickListener != null) { + onVerifiedVoiceItemClickListener.onVoiceClick(isChange, item.getVoiceUrl()); + } + }); + // 点击重新录制:跳转到录制声音页面 + helper.addOnClickListener(helper.tvReRecord.getId()); + helper.tvHeardCount.setText(String.format(Locale.getDefault(), "%d人听过", item.getPlayCount()));// 听过人数 + helper.tvLikeCount.setText(String.format(Locale.getDefault(), "%d人喜欢", item.getLikeCount()));// 喜欢人数 + } + + private void onBindViewHolderWithNoSubmitted(NoSubmittedViewHolder helper, UserVoiceInfo item) { + helper.tvDuration.setText(String.format(Locale.getDefault(), "%ds", item.getVoiceLength()));// 声音时长 + // 播放动画 + if (helper.voiceLine != null) { + helper.voiceLine.stopAnim(); + } + helper.ivVoicePlay.post(() -> { + if (helper.getAdapterPosition() == voiceClickPos) { + if (isPlayingVoice) { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_pause); + helper.voiceLine.startAnim(); + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + } else { + helper.ivVoicePlay.setImageResource(R.drawable.ic_voice_bar_play); + helper.voiceLine.stopAnim(); + } + }); + // 点击播放声音/停止声音 + helper.voiceBarLayout.setOnClickListener(view -> { + if (StringUtils.isEmpty(item.getVoiceUrl())) { + return; + } + boolean isChange = helper.getAdapterPosition() != voiceClickPos; + voiceClickPos = helper.getAdapterPosition(); + if (onVerifiedVoiceItemClickListener != null) { + onVerifiedVoiceItemClickListener.onVoiceClick(isChange, item.getVoiceUrl()); + } + }); + // 点击重新录制:跳转到录制声音页面 + helper.addOnClickListener(helper.tvReRecord.getId()); + } + + public void changePlayState(boolean isPlaying) { + this.isPlayingVoice = isPlaying; + notifyDataSetChanged(); + } + + private class InReviewViewHolder extends BaseViewHolder { + + LinearLayout voiceBarLayout; + ImageView ivVoicePlay; + VoiceLine voiceLine; + TextView tvDuration; + TextView tvReRecord; + + InReviewViewHolder(View view) { + super(view); + voiceBarLayout = view.findViewById(R.id.layout_voice_bar); + ivVoicePlay = view.findViewById(R.id.iv_voice_bar_play); + voiceLine = view.findViewById(R.id.layout_voice_line); + tvDuration = view.findViewById(R.id.tv_voice_duration); + tvReRecord = view.findViewById(R.id.tv_re_recording); + } + } + + private class VerifiedViewHolder extends BaseViewHolder { + + LinearLayout voiceBarLayout; + ImageView ivVoicePlay; + VoiceLine voiceLine; + TextView tvDuration; + TextView tvReRecord; + TextView tvHeardCount, tvLikeCount; + + VerifiedViewHolder(View view) { + super(view); + voiceBarLayout = view.findViewById(R.id.layout_voice_bar); + ivVoicePlay = view.findViewById(R.id.iv_voice_bar_play); + voiceLine = view.findViewById(R.id.layout_voice_line); + tvDuration = view.findViewById(R.id.tv_voice_duration); + tvReRecord = view.findViewById(R.id.tv_re_recording); + tvHeardCount = view.findViewById(R.id.tv_voice_heard_count); + tvLikeCount = view.findViewById(R.id.tv_voice_like_count); + } + } + + private class NoSubmittedViewHolder extends BaseViewHolder { + + LinearLayout voiceBarLayout; + ImageView ivVoicePlay; + VoiceLine voiceLine; + TextView tvDuration; + TextView tvReRecord; + + NoSubmittedViewHolder(View view) { + super(view); + voiceBarLayout = view.findViewById(R.id.layout_voice_bar); + ivVoicePlay = view.findViewById(R.id.iv_voice_bar_play); + voiceLine = view.findViewById(R.id.layout_voice_line); + tvDuration = view.findViewById(R.id.tv_voice_duration); + tvReRecord = view.findViewById(R.id.tv_re_recording); + } + } + + public interface OnVerifiedVoiceItemClickListener { + void onVoiceClick(boolean isChange, String voice); + } + + public void setOnVerifiedVoiceItemClickListener(OnVerifiedVoiceItemClickListener onVerifiedVoiceItemClickListener) { + this.onVerifiedVoiceItemClickListener = onVerifiedVoiceItemClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/AudioPlayerHelper.java b/app/src/main/java/com/yizhuan/erban/audio/helper/AudioPlayerHelper.java new file mode 100644 index 000000000..e95a7c8a9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/AudioPlayerHelper.java @@ -0,0 +1,211 @@ +package com.yizhuan.erban.audio.helper; + +import android.annotation.SuppressLint; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; + +import java.io.IOException; + +import lombok.Getter; + +/** + * create by lvzebiao @2019/6/14 + */ +public class AudioPlayerHelper { + + private final static long mIntervalTime = 500L; + + public interface WHAT_STATUS { + int ERROR = 1; + int COUNT_PLAY = 2; + int COMPLETION = 3; + int PREPARED = 4; + } + + private static final class Helper { + public static final AudioPlayerHelper INSTANCE = new AudioPlayerHelper(); + } + + public static AudioPlayerHelper get() { + return Helper.INSTANCE; + } + + private MediaPlayer player; + + private String audioFile; + + private boolean isLoop; + + public void onCreate() { + + } + + public void onPause() { + endPlay(); + } + + public void onDestroy() { + endPlay(); + } + + @Getter + private boolean preparing = false; + + @Getter + private boolean pause = false; + + public void playInThread(String filePath, OnPlayListener l) { + playInThread(filePath, false, l); + } + + public void rePlayInThread() { + if (listener != null && !TextUtils.isEmpty(audioFile)) { + playInThread(audioFile, isLoop, listener); + } + } + + public void playInThread(String filePath, boolean isLoop, OnPlayListener l) { + endPlay(); + this.listener = l; + if (listener != null) { + listener.onPreStart(); + } + this.audioFile = filePath; + this.isLoop = isLoop; + player = new MediaPlayer(); + player.setLooping(isLoop); + player.setAudioStreamType(AudioManager.STREAM_MUSIC); + + try { + player.setDataSource(filePath); + } catch (IOException e) { + e.printStackTrace(); + } + preparing = true; + try { + player.prepareAsync(); + } catch (Exception e) { + e.printStackTrace(); + preparing = false; + handler.sendEmptyMessage(WHAT_STATUS.ERROR); + } + player.setOnPreparedListener(mp -> { + if (player != null) { + player.start(); + } + preparing = false; + handler.sendEmptyMessage(WHAT_STATUS.PREPARED); + }); + player.setOnErrorListener((mp, what, extra) -> { + handler.sendEmptyMessage(WHAT_STATUS.ERROR); + return false; + }); + player.setOnCompletionListener(mp -> { + handler.removeMessages(WHAT_STATUS.COUNT_PLAY); + handler.sendEmptyMessage(WHAT_STATUS.COMPLETION); + }); + } + + public void endPlay() { + handler.removeMessages(WHAT_STATUS.COUNT_PLAY); + if (player != null) { + if (preparing) { + player.setOnPreparedListener(null); + player.setOnErrorListener(null); + player.setOnCompletionListener(null); + } + if (player.isPlaying() && !preparing) { + player.stop(); + } + player.release(); + player = null; + } + preparing = false; + pause = false; + this.listener = null; + this.audioFile = null; + } + + public void releaseWhenPreparing () { + handler.removeMessages(WHAT_STATUS.COUNT_PLAY); + if (player != null) { + if (player.isPlaying()) { + player.stop(); + } + player.setOnErrorListener(null); + player.setOnPreparedListener(null); + player.setOnCompletionListener(null); + player.release(); + player = null; + } + preparing = false; + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case WHAT_STATUS.ERROR: + if (listener != null) { + listener.onError("播放出错了"); + } + break; + case WHAT_STATUS.PREPARED: + preparing = false; + if (listener != null) { + listener.onPrepared(); + } + handler.sendEmptyMessage(WHAT_STATUS.COUNT_PLAY); + break; + case WHAT_STATUS.COUNT_PLAY: + if (listener != null) { + if (player != null) { + listener.onPlaying(player.getCurrentPosition()); + } + } + sendEmptyMessageDelayed(WHAT_STATUS.COUNT_PLAY, mIntervalTime); + break; + case WHAT_STATUS.COMPLETION: + preparing = false; + if (listener != null) { + listener.onCompletion(); + } + break; + } + } + }; + + public void pausePlay() { + if (player == null) { + return; + } + if (isPlaying()) { + player.pause(); + pause = true; + } + } + + public void continuePlay() { + if (player == null) { + return; + } + player.start(); + pause = false; + } + + private OnPlayListener listener; + + public boolean isPlaying() { + return player != null && player.isPlaying(); + } + + public long getDuration() { + return player == null ? 0 : player.getDuration(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/OnPlayListener.java b/app/src/main/java/com/yizhuan/erban/audio/helper/OnPlayListener.java new file mode 100644 index 000000000..3f91cacf0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/OnPlayListener.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.audio.helper; + +/** + * create by lvzebiao @2019/6/17 + */ +public interface OnPlayListener { + + /** + * 播放之前的操作 + */ + default void onPreStart() { + + } + + /** + * 出错了 + * 1. prepare 出错 + * 2. setOnErrorListener 回调 + */ + void onError(String error); + + /** + * 准备完毕 + * 1. setOnPreparedListener 回调 + */ + void onPrepared(); + + /** + * 播放中 + * 1. onPlaying + */ + void onPlaying(long currDuration); + + /** + * 播放完毕回调 + * 1. setOnCompletionListener 回调 + */ + void onCompletion(); +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/OnRefreshListener.java b/app/src/main/java/com/yizhuan/erban/audio/helper/OnRefreshListener.java new file mode 100644 index 000000000..ec48d163b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/OnRefreshListener.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.audio.helper; + +/** + * create by lvzebiao @2019/6/11 + */ +public interface OnRefreshListener { + + void refresh(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/SvgaCacheManager.java b/app/src/main/java/com/yizhuan/erban/audio/helper/SvgaCacheManager.java new file mode 100644 index 000000000..586ea6d0e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/SvgaCacheManager.java @@ -0,0 +1,171 @@ +package com.yizhuan.erban.audio.helper; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Build; +import android.os.Handler; +import android.os.Message; + +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +import org.jetbrains.annotations.NotNull; + +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.schedulers.Schedulers; +import lombok.Getter; + +/** + * create by lvzebiao @2019/6/21 + */ +public class SvgaCacheManager { + + private boolean voiceMatchActivityHasDestroy; + + /** + * 大瓶子水波纹 + */ + @Getter + private SVGADrawable bigBottleSvga; + /** + * 大瓶子气泡 + */ + @Getter + private SVGADrawable bigBubbleSvga; + /** + * 小瓶子水波纹 + */ + @Getter + private SVGADrawable smallBottleSvga; + /** + * 小瓶子气泡 + */ + @Getter + private SVGADrawable smallBubbleSvga; + + private static SvgaCacheManager instance; + + private SvgaCacheManager() { + + } + + public static SvgaCacheManager get() { + if (instance == null) { + instance = new SvgaCacheManager(); + } + return instance; + } + + public Single initSvga(Context context) { + if (!isMoreAndroid7_0()) { + return Single.just(""); + } + if (bigBottleSvga != null && bigBubbleSvga != null && + smallBottleSvga != null && smallBubbleSvga != null) { + return Single.just(""); + } + SVGAParser parser = new SVGAParser(context); + return Single.just("") + .flatMap(s -> { + if (bigBottleSvga == null) { + return createSvga(parser, true, true); + } + return Single.just(""); + }) + .flatMap(s -> { + if (bigBubbleSvga == null) { + return createSvga(parser, true, false); + } + return Single.just(""); + }) + .flatMap(s -> { + if (smallBottleSvga == null) { + return createSvga(parser, false, true); + } + return Single.just(""); + }) + .flatMap(s -> { + if (smallBubbleSvga == null) { + return createSvga(parser, false, false); + } + return Single.just(""); + }); + } + + private Single createSvga(SVGAParser parser, boolean isBig, boolean isBottle) { + return Single.create((SingleOnSubscribe) emitter -> { + String path = isBottle ? "svga/svga_voice_bottle.svga" : "svga/svga_voice_bubble.svga"; + parser.decodeFromAssets(path, new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + if (isBig) { + if (isBottle) { + bigBottleSvga = new SVGADrawable(svgaVideoEntity); + } else { + bigBubbleSvga = new SVGADrawable(svgaVideoEntity); + } + } else { + if (isBottle) { + smallBottleSvga = new SVGADrawable(svgaVideoEntity); + } else { + smallBubbleSvga = new SVGADrawable(svgaVideoEntity); + } + } + emitter.onSuccess(""); + } + + @Override + public void onError() { + emitter.onError(new Throwable("svga error")); + } + }); + }).subscribeOn(Schedulers.io()); + } + + public void onCreate() { + if (!isMoreAndroid7_0()) { + return; + } + voiceMatchActivityHasDestroy = false; + handler.removeMessages(0); + } + + public void onDestroy() { + if (!isMoreAndroid7_0()) { + return; + } + voiceMatchActivityHasDestroy = true; + //发送消息释放资源,资源存活时间过后再回收,防止频繁调用声音匹配界面 + handler.sendEmptyMessageDelayed(0, 90 * 1000); + } + + private void release() { + bigBottleSvga = null; + bigBubbleSvga = null; + smallBottleSvga = null; + smallBubbleSvga = null; + instance = null; + //gc + System.gc(); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + release(); + } + }; + + /** + * 是否是android 7.0或者以上 + */ + public boolean isMoreAndroid7_0() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/VmSoundManager.java b/app/src/main/java/com/yizhuan/erban/audio/helper/VmSoundManager.java new file mode 100644 index 000000000..afd89ec7f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/VmSoundManager.java @@ -0,0 +1,77 @@ +package com.yizhuan.erban.audio.helper; + + +import lombok.Getter; + +/** + * 声音匹配界面播放管理,写一个单例类,管理 + * create by lvzebiao @2019/6/20 + */ +public class VmSoundManager { + + public interface ConstantStatus { + int init = 0; + /**准备播放的状态*/ + int preparing = 1; + /**播放中的状态*/ + int playing = 2; + } + + private int playStatus = 0; + + private static final class Helper { + public static final VmSoundManager INSTANCE = new VmSoundManager(); + } + + public static VmSoundManager get() { + return Helper.INSTANCE; + } + + @Getter + private AudioPlayerHelper helper; + + public void onCreate() { + helper = new AudioPlayerHelper(); + helper.onCreate(); + } + + public void onResume(OnResumeListener onResumeListener) { + if (playStatus == ConstantStatus.playing) { + VmSoundManager.get().getHelper().continuePlay(); + } else if (playStatus == ConstantStatus.preparing) { + VmSoundManager.get().getHelper().rePlayInThread(); + } + if (onResumeListener != null) { + onResumeListener.onHandleResume(playStatus); + } + playStatus = ConstantStatus.init; + } + + public void onPause(OnPauseListener onPauseListener) { + if (VmSoundManager.get().getHelper().isPlaying()) { + VmSoundManager.get().getHelper().pausePlay(); + playStatus = ConstantStatus.playing; + } else if (VmSoundManager.get().getHelper().isPreparing()) { + VmSoundManager.get().getHelper().releaseWhenPreparing(); + playStatus = ConstantStatus.preparing; + } + if (onPauseListener != null) { + onPauseListener.onHandlePause(playStatus); + } + } + + public void onDestroy() { + if (helper != null) { + helper.onDestroy(); + } + } + + public interface OnResumeListener { + void onHandleResume(int status); + } + + public interface OnPauseListener { + void onHandlePause(int status); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/helper/VoiceMacthHelper.java b/app/src/main/java/com/yizhuan/erban/audio/helper/VoiceMacthHelper.java new file mode 100644 index 000000000..a709dda99 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/helper/VoiceMacthHelper.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.audio.helper; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.view.View; + +import lombok.Getter; + +/** + * create by lvzebiao @2019/6/11 + */ +public class VoiceMacthHelper { + + @Getter + private boolean dontLikeAnimRun; + + public void playDontLikeAnim(View view) { + dontLikeAnimRun = true; + ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 0.9f, 1.2f, 1.0f); + ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 0.9f, 1.2f, 1.0f); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.setDuration(600); + animatorSet.play(animatorX).with(animatorY); + animatorSet.start(); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + dontLikeAnimRun = false; + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/presenter/MyVoicePresenter.java b/app/src/main/java/com/yizhuan/erban/audio/presenter/MyVoicePresenter.java new file mode 100644 index 000000000..bc98b93ab --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/presenter/MyVoicePresenter.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.audio.presenter; + +import com.yizhuan.erban.audio.view.IMyVoiceView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.audio.AudioModel; +import com.yizhuan.xchat_android_core.audio.bean.UserVoiceInfo; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.List; + +/** + * 我的声音页面 + */ +public class MyVoicePresenter extends BaseMvpPresenter { + + public void getUserVoiceInfo() { + getMvpView().showLoadingView(); + AudioModel.get().getMyVoiceInfoList(AuthModel.get().getCurrentUid()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List userVoiceInfos, String error) { + super.accept(userVoiceInfos, error); + if (getMvpView() == null) { + return; + } + getMvpView().hideLoadingView(); + getMvpView().showVoiceInfo(userVoiceInfos); + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/presenter/RecordingVoicePresenter.java b/app/src/main/java/com/yizhuan/erban/audio/presenter/RecordingVoicePresenter.java new file mode 100644 index 000000000..6ce59327a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/presenter/RecordingVoicePresenter.java @@ -0,0 +1,463 @@ +package com.yizhuan.erban.audio.presenter; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import com.netease.nimlib.sdk.media.record.AudioRecorder; +import com.netease.nimlib.sdk.media.record.IAudioRecordCallback; +import com.netease.nimlib.sdk.media.record.RecordType; +import com.yizhuan.erban.audio.helper.AudioPlayerHelper; +import com.yizhuan.erban.audio.helper.OnPlayListener; +import com.yizhuan.erban.audio.view.IRecordingVoiceView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.audio.AudioModel; +import com.yizhuan.xchat_android_core.audio.AudioPlayAndRecordManager; +import com.yizhuan.xchat_android_core.audio.bean.SaveVoiceSuccessResultInfo; +import com.yizhuan.xchat_android_core.audio.bean.VoiceCardInfo; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.io.File; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.erban.audio.RecordingVoiceActivity.AUDIO_DURA; +import static com.yizhuan.erban.audio.RecordingVoiceActivity.AUDIO_FILE; +import static com.yizhuan.erban.audio.RecordingVoiceActivity.MIN_RECORD_VOICE_DURATION; + +/** + * 录制声音页面 + */ +public class RecordingVoicePresenter extends BaseMvpPresenter { + + private static final String TAG = "RecordingVoiceActivity"; + + public static final int STATE_RECORD_NORMAL = 0; + public static final int STATE_RECORD_RECORDING = 1; + public static final int STATE_RECORD_SUCCESS = 2; + + private int audioState = STATE_RECORD_NORMAL; + + private AudioPlayAndRecordManager audioManager; + private AudioRecorder audioRecorder; + private File audioFile; + private int audioDur; + private String audioUrl; + + private static final int WHAT_COUNT_PLAY = 1; + + /** + * 获取卡片信息 + */ + public void getCardInfo() { + AudioModel.get().getVoiceCardInfoList(AuthModel.get().getCurrentUid(), null, 10) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List voiceCardInfos, String error) { + super.accept(voiceCardInfos, error); + if (getMvpView() == null) { + return; + } + if (error == null) { + if (ListUtils.isListEmpty(voiceCardInfos)) { + return; + } + getMvpView().addCardInfo(voiceCardInfos); + } + } + }); + } + + /** + * 初始化资源 + */ + public void initResource() { + audioManager = AudioPlayAndRecordManager.getInstance(); + } + + /** + * 离开页面处理 + */ + public void leaveThePage() { + if (audioRecorder != null && audioRecorder.isRecording()) { + stopRecord();// 录制过程被中断(如点了返回按钮或电话接入等):【自动跳转到试听状态】停止录音 + return; + } + if (AudioPlayerHelper.get().isPlaying()) { + AudioPlayerHelper.get().endPlay(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// 返回页面时,此时正在播放声音,则停止播放并显示停止状态(播放按钮) + } + } + if (audioState == STATE_RECORD_SUCCESS) {// 已经录制未保存:未保存提示(确定则返回页面/取消则保留当前页面) + if (getMvpView() != null) { + getMvpView().showConfirmDialogWithLeave(); + } + } else { + if (getMvpView() != null) { + getMvpView().finishView(null);// 退出页面 + } + } + + } + + /** + * onPause()回调 + */ + public void pausePage() { + // 正在录制:则停止录制 + if (audioRecorder != null && audioRecorder.isRecording()) { + stopRecord();// onPause()时,如果正在录制,则停止录制 + } + // 正在播放:停止播放 + AudioPlayerHelper.get().onPause(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// onPause() 停止播放并显示停止状态(播放按钮) + } + } + + /** + * 重录 + */ + public void reRecord() { + if (audioState == STATE_RECORD_SUCCESS) { + AudioPlayerHelper.get().endPlay(); + showNormalState();// 点击重录,回到初始状态 + } + } + + /** + * 试听按钮 + */ + public void clickRightIcon() { + if (audioState == STATE_RECORD_SUCCESS) { + if (AudioPlayerHelper.get().isPlaying()) { + AudioPlayerHelper.get().pausePlay(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// 点击试听按钮此时正在播放声音,则暂停播放并显示停止状态(播放按钮) + } + } else if (AudioPlayerHelper.get().isPause()) { + AudioPlayerHelper.get().continuePlay(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(true);// 点击试听按钮此时正在暂停声音,则继续播放并显示播放状态(停止按钮) + } + } else if (AudioPlayerHelper.get().isPreparing()) { + AudioPlayerHelper.get().endPlay(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// 点击试听按钮此时正在准备状态,则停止播放并显示停止状态(播放按钮) + } + } else { + if (null != audioFile && audioFile.exists()) { + MLog.debug(TAG, "play audioFilePath: " + audioFile.getPath()); + AudioPlayerHelper.get().playInThread(audioFile.getPath(), new OnPlayListener() { + @Override + public void onError(String error) { + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// 出错:停止状态(播放按钮) + } + } + + @Override + public void onPrepared() { + if (getMvpView() != null) { + getMvpView().refreshListenerButton(true);// 准备完毕要开始播放:播放状态(暂停按钮) + } + } + + @Override + public void onPlaying(long currDuration) { + MLog.debug(TAG, "duration = " + currDuration); + if (getMvpView() != null) { + getMvpView().showCountDown((int) (currDuration / 1000)); + } + } + + @Override + public void onCompletion() { + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// 播放完成:停止状态(播放按钮) + } + } + }); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(true);// 点击试听按钮此时并没有正在播放声音,则播放声音并显示正在播放状态(暂停按钮) + } + } + } + } + } + + /** + * 中间按钮被点击 + */ + public void clickCenterIcon() { + switch (audioState) { + case STATE_RECORD_NORMAL: + startRecord();// 默认状态,点击了中间按钮:开始录音 + break; + case STATE_RECORD_RECORDING: + stopRecord();// 录制中状态,点击了中间按钮:停止录音 + break; + case STATE_RECORD_SUCCESS: + finishRecord();// 试听状态,点击了中间按钮:上传声音 + break; + } + } + + /** + * 停止录音 + */ + public void stopRecord() { + audioManager.stopRecord(false); + if (getMvpView() != null) { + getMvpView().stopChronometer(); + } + } + + /** + * 开始录音 + */ + private void startRecord() { + RoomInfo current = AvRoomDataManager.get().mCurrentRoomInfo; + if (current != null) { + if (getMvpView() != null) { + getMvpView().showConfirmDialogWithExitRoom(); + } + } else { + showRecordingState();// 开始录制,显示录制状态 + } + } + + /** + * 上传声音,完成录制 + */ + private void finishRecord() { + if (null != audioFile) { + Log.i("result_url", "upload before:" + audioFile.getAbsolutePath()); + if (getMvpView() != null) { + getMvpView().showLoadingView(); + } + FileModel.get() + .uploadFile(audioFile.getAbsolutePath()) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String url) { + audioUrl = url; + Log.i("result_url", "upload success:" + audioUrl); + saveVoice(); + } + + @Override + public void onError(Throwable e) { + SingleToastUtil.showToast("上传失败"); + if (getMvpView() != null) { + getMvpView().hideLoadingView();// 声音文件上传失败时 + } + } + }); + } + } + + /** + * 上传声音文件成功,提交保存声音 + */ + private void saveVoice() { + if (getMvpView() != null) { + Long piaId = getMvpView().getCardPiaId(); + Long changeVoiceId = getMvpView().getChangeVoiceId(); + AudioModel.get().saveVoice(AuthModel.get().getCurrentUid(), audioUrl, audioDur, changeVoiceId, piaId, 0) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(SaveVoiceSuccessResultInfo saveVoiceSuccessResultInfo, String error) { + super.accept(saveVoiceSuccessResultInfo, error); + if (getMvpView() == null) { + return; + } + if (error == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_SOUND_RECORD_SAVE, "我的声音-保存录音"); + showNormalState();// 提交声音成功,显示初始状态 + getMvpView().hideLoadingView();// 提交声音成功时 + + SingleToastUtil.showToast("你的声音已放入瓶子啦"); + Intent intent = new Intent(); + intent.putExtra(AUDIO_FILE, audioUrl); + intent.putExtra(AUDIO_DURA, audioDur); + getMvpView().finishView(intent);// 上传声音成功之后退出页面 + } else { + SingleToastUtil.showToast(error); + getMvpView().hideLoadingView();// 上传声音到用户信息中失败时 + } + } + }) + ; + } + } + + /** + * 显示默认状态,即初始状态 + */ + private void showNormalState() { + audioState = STATE_RECORD_NORMAL; + if (getMvpView() != null) { + getMvpView().refreshButtonView(audioState); + } + if (null != audioRecorder) { + audioRecorder.destroyAudioRecorder(); + audioRecorder = null; + } + } + + /** + * 显示录音中状态 + */ + private void showRecordingState() { + audioState = STATE_RECORD_RECORDING; + if (getMvpView() != null) { + getMvpView().refreshButtonView(audioState); + getMvpView().startChronometer(); + } + audioRecorder = audioManager.getAudioRecorder((Context) mMvpView, new IAudioRecordCallback() { + @Override + public void onRecordReady() { + Log.d(TAG, "onRecordReady"); + } + + @Override + public void onRecordStart(File audioFile, RecordType recordType) { + Log.d(TAG, "onRecordStart : " + audioFile.getPath() + "type: " + recordType.name()); + mHandler.sendEmptyMessage(WHAT_COUNT_PLAY); + if (getMvpView() != null) { + getMvpView().showVoiceWave(); + } + } + + @Override + public void onRecordSuccess(File file, long audioLength, RecordType recordType) { + double dura = (double) audioLength / 1000; + audioDur = (int) Math.round(dura); + audioFile = file; + Log.d(TAG, "onRecordSuccess : " + file.getPath() + + " dura:" + dura + + " length:" + audioDur + + " type:" + recordType.name()); + if (audioDur < MIN_RECORD_VOICE_DURATION) { + recordFailWithDurationShort();// 时长小于5s:Toast提示录音时间太短 + } else { + showRecordSuccessState();// 否则:【跳转到试听状态】 + } + mHandler.removeMessages(WHAT_COUNT_PLAY); + if (getMvpView() != null) { + getMvpView().hideVoiceWave(); + } + } + + @Override + public void onRecordFail() { + Log.d(TAG, "onRecordFail"); + recordFailWithDurationShort();// 录音结束,出错 + mHandler.removeMessages(WHAT_COUNT_PLAY); + if (getMvpView() != null) { + getMvpView().hideVoiceWave(); + } + } + + @Override + public void onRecordCancel() { + Log.d(TAG, "onRecordCancel"); + showNormalState();// 录制过程被取消,显示初始状态 + mHandler.removeMessages(WHAT_COUNT_PLAY); + if (getMvpView() != null) { + getMvpView().hideVoiceWave(); + } + } + + @Override + public void onRecordReachedMaxTime(int maxTime) { + Log.d(TAG, "onRecordReachedMaxTime"); +// double dura = (double) maxTime / 1000; +// int max = (int) Math.round(dura); + SingleToastUtil.showToast("录音时间过长"); + mHandler.removeMessages(WHAT_COUNT_PLAY); + if (getMvpView() != null) { + getMvpView().hideVoiceWave(); + } + } + }); + audioManager.startRecord(); + } + + /** + * 显示试听状态 + */ + private void showRecordSuccessState() { + audioState = STATE_RECORD_SUCCESS; + if (getMvpView() != null) { + getMvpView().refreshButtonView(audioState); + } + } + + /** + * 录音失败因时长太短 + */ + private void recordFailWithDurationShort() { + SingleToastUtil.showToast("录音时间少于5秒"); + showNormalState();// 录制时长太短,显示初始状态 + } + + /** + * 释放资源 + */ + public void releaseResource() { + if (audioManager != null) { + audioManager.release(); + } + AudioPlayerHelper.get().onDestroy(); + if (getMvpView() != null) { + getMvpView().refreshListenerButton(false);// onDestroy() 停止播放并显示停止状态(播放按钮) + } + } + + private Handler mHandler = new Handler(new Handler.Callback() { + @Override + public boolean handleMessage(Message message) { + switch (message.what) { + case WHAT_COUNT_PLAY: + double ratio = (double) audioRecorder.getCurrentRecordMaxAmplitude() / 100; + double db = 0;// 分贝 + if (ratio > 1) { + db = 20 * Math.log10(ratio); + } + Log.d(TAG, "volume--->分贝 = " + db); + if (getMvpView() != null) { + getMvpView().refreshVoiceWave(db); + } + + mHandler.sendEmptyMessageDelayed(WHAT_COUNT_PLAY, 500L); + break; + } + return false; + } + }); +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/BottleContainer.java b/app/src/main/java/com/yizhuan/erban/audio/view/BottleContainer.java new file mode 100644 index 000000000..10269a58d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/BottleContainer.java @@ -0,0 +1,289 @@ +package com.yizhuan.erban.audio.view; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.audio.bean.VoiceMatchInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Setter; + +/** + * create by lvzebiao @2019/6/18 + */ +public class BottleContainer extends FrameLayout { + + private Context context; + + private List list = new ArrayList<>(); + + private int currPosition = 0; + + private int minOffset; + + private int maxOffset; + + public BottleContainer(@NonNull Context context) { + this(context, null); + } + + public BottleContainer(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + minOffset = UIUtil.dip2px(context, 20); + maxOffset = UIUtil.dip2px(context, 270); + } + + public void initData(List list) { + if (!ListUtils.isListEmpty(list)) { + this.list.clear(); + this.list.addAll(list); + } + if (getChildCount() == 0) { + removeAllViews(); + initBottleViews(); + } + currPosition = 0; + initBottleData(); + } + + public void initBottleViews() { + BottleLayout smallBottle = new BottleLayout(context, false); + addView(smallBottle); + BottleLayout bigBottle = new BottleLayout(context, true); + addView(bigBottle); + bigBottle.setSvga(true); + smallBottle.setSvga(false); + } + + private void initBottleData() { + //设置大瓶子的数据 + setBigBottleDataAndSvga(); + //设置小瓶子的数据 + setSmallBottleDataAndSvga(); + //自动播放大瓶子的声音 + autoPlayBigBottleSound(); + //更新监听 + updateBottleStatus(); + //只有一个数据小瓶子隐藏 + updateVisibleStatus(); + } + + private void setBigBottleDataAndSvga() { + if (currPosition < list.size()) { + if (getChildCount() >= 2) { + //bigBottle + BottleLayout bigBottle = ((BottleLayout) getChildAt(1)); + bigBottle.setData(list.get(currPosition)); + bigBottle.stop(); + bigBottle.play(); + } + } + } + + private void setSmallBottleDataAndSvga() { + if (currPosition + 1 < list.size()) { + if (getChildCount() >= 1) { + //smallBottle + BottleLayout smallBottle = ((BottleLayout) getChildAt(0)); + smallBottle.setData(list.get(currPosition + 1)); + smallBottle.stop(); + smallBottle.play(); + } + } + } + + /** + * 自动播放大瓶子的声音 + */ + public void autoPlayBigBottleSound() { + if (getChildCount() >= 2) { + ((BottleLayout) getChildAt(1)).startPlay(); + } + } + + private void updateBottleStatus() { + + if (getChildCount() >= 2) { + //bigBottle + BottleLayout bigBottle = ((BottleLayout) getChildAt(1)); + bigBottle.setOnNextPageListener(new BottleOnNextPageListener()); + bigBottle.setCanDrag(true); + if (bigBottle.getTag() != null) { + bigBottle.getViewTreeObserver().removeOnGlobalLayoutListener( + (ViewTreeObserver.OnGlobalLayoutListener) bigBottle.getTag()); + bigBottle.setTag(null); + } + BottleLayoutListener listener = new BottleLayoutListener(); + bigBottle.getViewTreeObserver().addOnGlobalLayoutListener(listener); + bigBottle.setTag(listener); + } + if (getChildCount() >= 1) { + //smallBottle + BottleLayout smallBottle = ((BottleLayout) getChildAt(0)); + smallBottle.setOnNextPageListener(null); + smallBottle.setCanDrag(false); + if (smallBottle.getTag() != null) { + smallBottle.getViewTreeObserver().removeOnGlobalLayoutListener( + (ViewTreeObserver.OnGlobalLayoutListener) smallBottle.getTag()); + smallBottle.setTag(null); + } + } + + } + + public class BottleOnNextPageListener implements BottleLayout.OnNextPageListener { + + @Override + public void onLimit(boolean isRight) { + if (opListener != null) { + opListener.onLimit(isRight); + } + } + + @Override + public void onNext(boolean isRight) { + VoiceMatchInfo info = null; + if (currPosition < list.size()) { + info = list.get(currPosition); + } + if (getChildCount() == 2) { + //将上面第一个瓶子移除,并且添加到底下的瓶子,也就是大小瓶子位置互换 + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + bigBottle.resetSoundPlayStatus(); + removeView(bigBottle); + + currPosition++; + if (bigBottle.getParent() == null) { + addView(bigBottle, 0); + setSmallBottleDataAndSvga(); + } else { + + } + updateVisibleStatus();// 切换到下一个瓶子时 + updateBottleStatus(); + if (currPosition < list.size()) { + autoPlayBigBottleSound(); + } + if (info != null) { + if (opListener != null) { + opListener.onLikeOrUnLike(info, isRight, currPosition >= list.size()); + } + } + } + } + } + + @Setter + private IBottleOpListener opListener; + + /** + * 更新显示的瓶子状态 + */ + private void updateVisibleStatus() { + if (currPosition == list.size() - 1 && getChildCount() >= 1) { + // 如果是最后一个瓶子,需要将底部的小瓶子隐藏掉 + getChildAt(0).setVisibility(View.INVISIBLE); + } else { + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).setVisibility(View.VISIBLE); + } + } + } + + + public class BottleLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { + + @Override + public void onGlobalLayout() { + if (getChildCount() != 2) { + return; + } + BottleLayout child = (BottleLayout) getChildAt(0); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getChildAt(1).getLayoutParams(); + int leftMargin = params.leftMargin; + int topMargin = params.topMargin; + int dx = leftMargin - child.getInitLeft(); + int dy = topMargin - child.getInitTop(); + //平方后再开方 + int offset = (int) Math.sqrt(dx * dx + dy * dy); + if (offset < minOffset) { + offset = minOffset; + } + if (offset > maxOffset) { + offset = maxOffset; + } + float percent = (float) (offset - minOffset) / (maxOffset - minOffset); + + float scale = BottleLayout.MIN_SCALE_VALUE + (1f - BottleLayout.MIN_SCALE_VALUE) * percent; + child.setScaleX(scale); + child.setScaleY(scale); + } + } + + public void addBigBottleLikeCount() { + if (getChildCount() >= 2) { + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + bigBottle.addLikeCount(); + } + } + + public void dealBigBottleLimit(boolean isLike) { + if (getChildCount() >= 2) { + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + if (!bigBottle.isCanNext()) { + return; + } + bigBottle.dealWithLimit(isLike);// 点击按钮,受限制情况 + } + } + + public void dealToNext(boolean isLike) { + if (getChildCount() >= 2) { + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + if (!bigBottle.isCanNext()) { + return; + } + bigBottle.toNext(isLike);// 点击按钮,不受限情况 + } + } + + public void resetBigBottlePlayStatus() { + if (getChildCount() >= 2) { + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + bigBottle.resetSoundPlayStatus(); + } + } + + public void onlySetPlayOrStopIconForBigBottle(boolean isPlay) { + if (getChildCount() >= 2) { + BottleLayout bigBottle = (BottleLayout) getChildAt(1); + bigBottle.onlySetPlayOrStopIcon(isPlay); + } + } + + public void onDestroy() { + for (int i = 0; i < getChildCount(); i++) { + BottleLayout child = (BottleLayout) getChildAt(i); + if (child.getTag() != null) { + child.getViewTreeObserver().removeOnGlobalLayoutListener( + (ViewTreeObserver.OnGlobalLayoutListener) child.getTag()); + child.setTag(null); + } + child.setOnNextPageListener(null); + child.stop(); + } + opListener = null; + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/BottleLayout.java b/app/src/main/java/com/yizhuan/erban/audio/view/BottleLayout.java new file mode 100644 index 000000000..82fc123f0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/BottleLayout.java @@ -0,0 +1,535 @@ +package com.yizhuan.erban.audio.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.opensource.svgaplayer.SVGAImageView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.VoiceMatchActivity; +import com.yizhuan.erban.audio.helper.OnPlayListener; +import com.yizhuan.erban.audio.helper.SvgaCacheManager; +import com.yizhuan.erban.audio.helper.VmSoundManager; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.audio.bean.VoiceMatchInfo; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.concurrent.TimeUnit; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import lombok.Getter; +import lombok.Setter; + +/** + * create by lvzebiao @2019/6/6 + */ +public class BottleLayout extends FrameLayout { + + public final static float MIN_SCALE_VALUE = 0.0f; + @BindView(R.id.civ_avatar_bg) + CircleImageView civAvatarBg; + @BindView(R.id.civ_avatar) + CircleImageView civAvatar; + @BindView(R.id.svga_voice_bubble) + SVGAImageView svgaVoiceBubble; + @BindView(R.id.svga_voice_bottle) + SVGAImageView svgaVoiceBottle; + @BindView(R.id.tv_nick) + TextView tvNick; + @BindView(R.id.iv_gender) + ImageView ivGender; + @BindView(R.id.stv_constellation) + SuperTextView stvConstellation; + @BindView(R.id.stv_location) + SuperTextView stvLocation; + @BindView(R.id.pliv_play) + PlayLoadingImageView plivPlay; + @BindView(R.id.tv_like_value) + TextView tvLikeValue; + @BindView(R.id.iv_report) + ImageView ivReport; + + private int lastMoveX = 0; + private int lastMoveY = 0; + + int bigBottleWidth; + int bigBottleHeight; + int smallBottleWidth; + int smallBottleHeight; + /** + * 初始化时的左间距 + */ + int leftMargin; + + int topMargin; + + int parentWidth; + + @Getter + int initLeft; + + @Getter + int initTop; + + int minNextOffset; + + private boolean canDrag; + + private boolean animRun; + + private Context context; + + private VoiceMatchInfo voiceMatchInfo; + + public BottleLayout(@NonNull Context context) { + this(context, false); + } + + public BottleLayout(@NonNull Context context, boolean canDrag) { + super(context); + this.context = context; + this.canDrag = canDrag; + inflate(context, R.layout.layout_item_voice_bottle, this); + ButterKnife.bind(this); + + bigBottleWidth = UIUtil.dip2px(context, 295); + bigBottleHeight = UIUtil.dip2px(context, 441); + smallBottleWidth = bigBottleWidth / 3; + smallBottleHeight = bigBottleHeight / 3; + parentWidth = UIUtil.getScreenWidth(context); + topMargin = 0; + minNextOffset = UIUtil.dip2px(context, 80); + leftMargin = (parentWidth - bigBottleWidth) / 2; + initLeft = leftMargin; + initTop = topMargin; + resetParams(); + } + + public void setSvga(boolean isBig) { + if (!SvgaCacheManager.get().isMoreAndroid7_0()) { + svgaVoiceBottle.setImageResource(R.drawable.bg_voice_match_android_6); + return; + } + if (isBig) { + if (SvgaCacheManager.get().getBigBottleSvga() != null) { + svgaVoiceBottle.setLoops(0); + svgaVoiceBottle.setImageDrawable(SvgaCacheManager.get().getBigBottleSvga()); + } + if (SvgaCacheManager.get().getBigBubbleSvga() != null) { + svgaVoiceBubble.setLoops(0); + svgaVoiceBubble.setImageDrawable(SvgaCacheManager.get().getBigBubbleSvga()); + } + } else { + if (SvgaCacheManager.get().getSmallBottleSvga() != null) { + svgaVoiceBottle.setLoops(0); + svgaVoiceBottle.setImageDrawable(SvgaCacheManager.get().getSmallBottleSvga()); + } + if (SvgaCacheManager.get().getSmallBubbleSvga() != null) { + svgaVoiceBubble.setLoops(0); + svgaVoiceBubble.setImageDrawable(SvgaCacheManager.get().getSmallBubbleSvga()); + } + } + } + + public void play() { + if (!SvgaCacheManager.get().isMoreAndroid7_0()) { + return; + } + if (!svgaVoiceBottle.isAnimating()) { + svgaVoiceBottle.startAnimation(); + } + if (!svgaVoiceBubble.isAnimating()) { + svgaVoiceBubble.startAnimation(); + } + } + + public void stop() { + svgaVoiceBottle.stopAnimation(); + svgaVoiceBubble.stopAnimation(); + } + + public void setCanDrag(boolean canDrag) { + this.canDrag = canDrag; + resetParams(); + } + + private void resetParams() { + LayoutParams params = new LayoutParams( + bigBottleWidth, bigBottleHeight); + params.leftMargin = initLeft; + params.topMargin = initTop; + setLayoutParams(params); + if (!canDrag) { + setScaleX(MIN_SCALE_VALUE); + setScaleY(MIN_SCALE_VALUE); + } else { + setScaleX(1.0f); + setScaleY(1.0f); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return super.onInterceptTouchEvent(event); + } + + @Override + public boolean performClick() { + return super.performClick(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + //LogUtil.print(canDrag + "---Bottle---onTouchEvent---" + event.getAction()); + if (!canDrag || animRun) { + return super.onTouchEvent(event); + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + int downX = (int) event.getRawX(); + int downY = (int) event.getRawY(); + lastMoveX = downX; + lastMoveY = downY; + break; + + case MotionEvent.ACTION_MOVE: + + int disX = (int) (event.getRawX() - lastMoveX); + int disY = (int) (event.getRawY() - lastMoveY); + + //LogUtil.print("getLeft()=" + getLeft() + ", disX=" + disX); + leftMargin = getLeft() + disX; + topMargin = getTop() + disY; + //LogUtil.print("leftMargin=" + leftMargin + ", topMargin=" + topMargin); + + LayoutParams moveParams = new LayoutParams( + bigBottleWidth, bigBottleHeight + ); + moveParams.leftMargin = leftMargin; + moveParams.topMargin = topMargin; + setLayoutParams(moveParams); + + lastMoveX = (int) event.getRawX(); + lastMoveY = (int) event.getRawY(); + + break; + + case MotionEvent.ACTION_UP: + //手指离开的时候,回弹到初始位置 + if (Math.abs(getLeft() - initLeft) <= minNextOffset) { + recoveryToInit(); + } else { + boolean isRight = getLeft() > initLeft; + boolean isLimit = (boolean) SharedPreferenceUtils.get(VoiceMatchActivity.KEY_VOICE_MUST_LIMIT + AuthModel.get().getCurrentUid(), true); + if (isLimit) { + dealWithLimit(isRight);// 手势滑动,受限制情况 + } else { + toNext(isRight);// 不受限情况,允许左右滑动 + } + } + + break; + } + return true; + } + + public void dealWithLimit(boolean isRight) { + if (isRight) { + recoveryToInit(); + toLimit(true);// 限制右滑 + } else { + int limitCount = (int) SharedPreferenceUtils.get(VoiceMatchActivity.KEY_VOICE_LIMIT_COUNT + AuthModel.get().getCurrentUid(), 0); + if (limitCount >= 2) {// 0 1 索引为2时即为第三个声音 + recoveryToInit(); + toLimit(false);// 不喜欢第三个 限制左滑 + } else { + toNext(false);// 受限情况 但 左滑未超过三次,允许左滑 + limitCount = limitCount + 1; + SharedPreferenceUtils.put(VoiceMatchActivity.KEY_VOICE_LIMIT_COUNT + AuthModel.get().getCurrentUid(), limitCount); + } + } + } + + public boolean isCanNext() { + return !animRun; + } + + private void toLimit(boolean isRight) { + if (onNextPageListener != null) { + onNextPageListener.onLimit(isRight); + } + } + + public void toNext(boolean isRight) { + //如果切换下一页的时候,声音正在播放,则停止播放声音 + VmSoundManager.get().getHelper().endPlay(); + + animRun = true; + int endValue; + if (isRight) { + endValue = parentWidth; + } else { + endValue = -bigBottleWidth; + } + int duration = Math.abs(getLeft() - endValue) / 2; + if (duration < 100) { + duration = 100; + } else if (duration > 300) { + duration = 300; + } + ValueAnimator animator = ValueAnimator.ofInt(getLeft(), endValue); + animator.setDuration(duration); + animator.addUpdateListener(animation -> { + int curr = (int) animation.getAnimatedValue(); + LayoutParams params = (LayoutParams) getLayoutParams(); + params.leftMargin = curr; + setLayoutParams(params); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (onNextPageListener != null) { + onNextPageListener.onNext(isRight); + } + Single.timer(200, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Long aLong, String error) { + super.accept(aLong, error); + animRun = false; + } + }); + } + }); + animator.start(); + } + + @Setter + private OnNextPageListener onNextPageListener; + + public interface OnNextPageListener { + /** + * 受到限制 不给滑动 + * + * @param isRight 是否往右滑 + */ + void onLimit(boolean isRight); + + void onNext(boolean isRight); + } + + private void recoveryToInit() { + ValueAnimator xAnimator = ValueAnimator.ofInt(getLeft(), initLeft); + xAnimator.setDuration(150); + xAnimator.addUpdateListener(animation -> { + int currLeft = (int) animation.getAnimatedValue(); + LayoutParams params = (LayoutParams) getLayoutParams(); + params.leftMargin = currLeft; + setLayoutParams(params); + }); + xAnimator.start(); + + ValueAnimator yAnimator = ValueAnimator.ofInt(getTop(), initTop); + yAnimator.setDuration(150); + yAnimator.addUpdateListener(animation -> { + int currValue = (int) animation.getAnimatedValue(); + LayoutParams params = (LayoutParams) getLayoutParams(); + params.topMargin = currValue; + setLayoutParams(params); + }); + yAnimator.start(); + + } + + public void setData(VoiceMatchInfo info) { + voiceMatchInfo = info; + if (info == null) { + return; + } + ImageLoadUtils.loadAvatarBig(info.getAvatar(), civAvatar); + ImageLoadUtils.loadImageWithBlur(context, ImageLoadUtils.getAvatarSizeUrl(info.getAvatar()), civAvatarBg, 20, 2); + String showNick = info.getNick(); + if (showNick == null) { + showNick = ""; + } + if (showNick.length() >= 6) { + showNick = showNick.substring(0, 5) + "…"; + } + tvNick.setText(showNick); + ivGender.setImageResource(info.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + stvConstellation.setText(TimeUtils.msToConstellation(info.getBirth())); + String location = info.getLocation(); + if (TextUtils.isEmpty(location)) { + stvLocation.setVisibility(GONE); + } else { + stvLocation.setVisibility(VISIBLE); + if (location.length() >= 5) { + location = location.substring(0, 4) + "…"; + } + stvLocation.setText(location); + } + + lastClickPlayTime = System.currentTimeMillis(); + + plivPlay.setOnClickListener(v -> { + //加个容错处理,防止频繁点击播放按钮 + long currTime = System.currentTimeMillis(); + if (currTime - lastClickPlayTime < 400) { + return; + } + if (isDelaying) { + return; + } + lastClickPlayTime = currTime; + if (VmSoundManager.get().getHelper().isPreparing()) { + VmSoundManager.get().getHelper().endPlay(); + resetSoundPlayStatus(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_SUSPEND, "声音瓶子-暂停播放按钮-暂停"); + return; + } + if (VmSoundManager.get().getHelper().isPlaying()) { + VmSoundManager.get().getHelper().pausePlay(); + plivPlay.setImageResource(R.drawable.icon_voice_to_start); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_SUSPEND, "声音瓶子-暂停播放按钮-暂停"); + return; + } + if (VmSoundManager.get().getHelper().isPause()) { + VmSoundManager.get().getHelper().continuePlay(); + plivPlay.setImageResource(R.drawable.icon_voice_to_stop); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_SUSPEND, "声音瓶子-暂停播放按钮-继续播放"); + return; + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SOUND_MATCH_SUSPEND, "声音瓶子-暂停播放按钮-播放"); + startPlay(); + }); + + ivReport.setOnClickListener(view -> { + // 跳转到举报页面 + UIHelper.showReportPage(context, info.getUid(), XChatConstants.REPORT_TYPE_VOICE); + }); + + } + + public void startPlay() { + if (!canDrag) { + return; + } + if (voiceMatchInfo == null) { + return; + } + tvLikeValue.setTag(voiceMatchInfo.getLikeCount()); + tvLikeValue.setText(formatLikeCount(voiceMatchInfo.getLikeCount())); + plivPlay.setImageResource(R.drawable.icon_voice_to_stop); + VmSoundManager.get().getHelper().playInThread(voiceMatchInfo.getVoiceUrl(), true, new OnPlayListener() { + + @Override + public void onError(String error) { + resetSoundPlayStatus(); + SingleToastUtil.showToast(error); + } + + @Override + public void onPrepared() { + duration = VmSoundManager.get().getHelper().getDuration(); + plivPlay.setMaxProgress(duration); + } + + @Override + public void onPlaying(long currDuration) { + plivPlay.setProgress(currDuration, duration); + } + + @Override + public void onCompletion() { + plivPlay.setProgress(duration, duration); + isDelaying = true; + Single.timer(150, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .compose(RxHelper.bindContext(context)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(Long aLong, Throwable throwable) { + super.acceptThrowable(aLong, throwable); + resetSoundPlayStatus(); + isDelaying = false; + } + }); + } + }); + + } + + public void addLikeCount() { + tvLikeValue.post(() -> { + if (tvLikeValue.getTag() instanceof Integer) { + int tagLikeCount = (Integer) tvLikeValue.getTag(); + tvLikeValue.setText(String.valueOf(tagLikeCount + 1)); + } + }); + } + + public void resetSoundPlayStatus() { + plivPlay.setImageResource(R.drawable.icon_voice_to_start); + plivPlay.setProgress(0, 1000); + } + + public void onlySetPlayOrStopIcon(boolean isPlay) { + plivPlay.setImageResource(isPlay ? R.drawable.icon_voice_to_start : R.drawable.icon_voice_to_stop); + } + + private long duration; + + + private long lastClickPlayTime = 0; + /** + * 播放结束后,会有延迟让按钮回到最初状态,如果正在延迟中的话,则禁止操作 + */ + private boolean isDelaying = false; + + private String formatLikeCount(int likeCount) { + String showText; + if (likeCount < 0) { + showText = "0"; + } else if (likeCount < 10000) { + showText = String.valueOf(likeCount); + } else { + double likeCountDouble = (double) likeCount; + double num = likeCountDouble / 10000; + + DecimalFormat decimalFormat = new DecimalFormat("0.00");// 构造方法的字符格式这里如果小数不足2位,会以0补足. + BigDecimal bigDecimal = new BigDecimal(num); + double likeCountFormat = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + if (likeCountFormat > 9999) { + showText = "9999万+"; + } else { + showText = decimalFormat.format(likeCountFormat) + "万"; + } + } + return showText; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/IBottleOpListener.java b/app/src/main/java/com/yizhuan/erban/audio/view/IBottleOpListener.java new file mode 100644 index 000000000..9fe00f221 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/IBottleOpListener.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.audio.view; + +import com.yizhuan.xchat_android_core.audio.bean.VoiceMatchInfo; + +/** + * create by lvzebiao @2019/6/19 + */ +public interface IBottleOpListener { + + void onLimit(boolean isRight); + + void onLikeOrUnLike(VoiceMatchInfo info, boolean isRight, boolean needLoading); + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/IMyVoiceView.java b/app/src/main/java/com/yizhuan/erban/audio/view/IMyVoiceView.java new file mode 100644 index 000000000..e0a26b0d5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/IMyVoiceView.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.audio.view; + +import com.yizhuan.xchat_android_core.audio.bean.UserVoiceInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * 我的声音页面 + */ +public interface IMyVoiceView extends IMvpBaseView { + /** + * 显示声音数据消息 + */ + void showVoiceInfo(List voiceList); + + /** + * 请稍后 + */ + void showLoadingView(); + + void hideLoadingView(); +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/IRecordingVoiceView.java b/app/src/main/java/com/yizhuan/erban/audio/view/IRecordingVoiceView.java new file mode 100644 index 000000000..a288268bb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/IRecordingVoiceView.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.audio.view; + +import android.content.Intent; + +import com.yizhuan.xchat_android_core.audio.bean.VoiceCardInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * 录制声音页面 + */ +public interface IRecordingVoiceView extends IMvpBaseView { + + /** + * 添加卡片信息 + */ + void addCardInfo(List cardInfoList); + + /** + * 获取当前pia剧本id + */ + Long getCardPiaId(); + + /** + * 刷新按钮的状态 + */ + void refreshButtonView(int state); + + /** + * 刷新试听按钮 + */ + void refreshListenerButton(boolean isPlaying); + + /** + * 开始倒计时 + */ + void startChronometer(); + + /** + * 停止倒计时 + */ + void stopChronometer(); + + /** + * 确认退出页面对话框 + */ + void showConfirmDialogWithLeave(); + + /** + * 退出页面 + */ + void finishView(Intent intent); + + /** + * 关闭房间再录音 + */ + void showConfirmDialogWithExitRoom(); + + /** + * 请稍后 + */ + void showLoadingView(); + + void hideLoadingView(); + + /** + * 获取被重新录制的声音的ID:打开页面的时候传入,可以为空 + */ + Long getChangeVoiceId(); + + void refreshVoiceWave(double db); + + void showVoiceWave(); + + void hideVoiceWave(); + + void showCountDown(int duration); +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/view/PlayLoadingImageView.java b/app/src/main/java/com/yizhuan/erban/audio/view/PlayLoadingImageView.java new file mode 100644 index 000000000..cb9fc3769 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/view/PlayLoadingImageView.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.audio.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import lombok.Setter; + +/** + * create by lvzebiao @2019/6/12 + */ +public class PlayLoadingImageView extends AppCompatImageView { + + private long progress; + + RectF rectF; + + private Paint paint; + + private int color_white; + + private int color_32ECD9; + + private int color_F2F4F4; + + private int loading_width; + + @Setter + private long maxProgress = 1000; + + public PlayLoadingImageView(Context context, AttributeSet attrs) { + super(context, attrs); + loading_width = UIUtil.dip2px(context, 2); + rectF = new RectF(); + paint = new Paint(); + paint.setAntiAlias(true); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(loading_width); + color_white = context.getResources().getColor(R.color.white); + color_32ECD9 = context.getResources().getColor(R.color.color_32ECD9); + color_F2F4F4 = context.getResources().getColor(R.color.color_F2F4F4); + + + left = (float) loading_width / 2; + top = (float) loading_width / 2; + } + + private float left, top, rigth, end; + + @Override + protected void onDraw(Canvas canvas) { + + rectF.set(left, top, getWidth() - left, getHeight() - top); + + paint.setColor(color_F2F4F4); + float radiu = (float) (getWidth() - loading_width) / 2; + canvas.drawCircle((float) getWidth() / 2, (float) getHeight() / 2, radiu, paint); + + paint.setColor(color_32ECD9); + int degree; + if (maxProgress > 0) { + degree = (int) (progress * 360 / maxProgress); + } else { + degree = 0; + } + canvas.drawArc(rectF, -90, degree, false, paint); + + super.onDraw(canvas); + } + + public void setProgress(long progress, long maxProgress) { + if (progress > maxProgress) { + progress = maxProgress; + } else if (progress < 0) { + progress = 0; + } + if (maxProgress - progress <= 500) { + //LogUtil.print("播放进度不足500ms了,绘制一个完整的圆"); + progress = maxProgress; + } + if (progress == this.progress && maxProgress == this.maxProgress) { + //加载进度一样,不需要重绘 + return; + } + this.progress = progress; + this.maxProgress = maxProgress; + invalidate(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/DynamicWave.java b/app/src/main/java/com/yizhuan/erban/audio/widget/DynamicWave.java new file mode 100644 index 000000000..8ba98a6fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/DynamicWave.java @@ -0,0 +1,121 @@ +package com.yizhuan.erban.audio.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.DrawFilter; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.util.AttributeSet; +import android.view.View; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; + +/** + * Created by liruiyuan on 2015/12/21. + */ +public class DynamicWave extends View { + // y = Asin(wx+b)+h + private static final float STRETCH_FACTOR_A = 20; + private static final int OFFSET_Y = -50; + // 第一条水波移动速度 + private static final int TRANSLATE_X_SPEED_ONE = 7; + // 第二条水波移动速度 + private static final int TRANSLATE_X_SPEED_TWO = 5; + private float mCycleFactorW; + + private int mTotalWidth, mTotalHeight; + private float[] mYPositions; + private float[] mResetOneYPositions; + private float[] mResetTwoYPositions; + private int mXOffsetSpeedOne; + private int mXOffsetSpeedTwo; + private int mXOneOffset; + private int mXTwoOffset; + + private Paint mWavePaint; + private DrawFilter mDrawFilter; + + public DynamicWave(Context context, AttributeSet attrs) { + super(context, attrs); + // 将dp转化为px,用于控制不同分辨率上移动速度基本一致 + mXOffsetSpeedOne = ScreenUtil.dip2px(TRANSLATE_X_SPEED_ONE); + mXOffsetSpeedTwo = ScreenUtil.dip2px(TRANSLATE_X_SPEED_TWO); + + // 初始绘制波纹的画笔 + mWavePaint = new Paint(); + // 去除画笔锯齿 + mWavePaint.setAntiAlias(true); + // 设置风格为实线 + mWavePaint.setStyle(Paint.Style.FILL); + // 设置画笔颜色 + mWavePaint.setColor(Color.parseColor("#26FFFFFF")); + mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 从canvas层面去除绘制时锯齿 + canvas.setDrawFilter(mDrawFilter); + resetPositonY(); + for (int i = 0; i < mTotalWidth; i++) { + + // 减400只是为了控制波纹绘制的y在屏幕的位置,大家可以改成一个变量,然后动态改变这个变量,从而形成波纹上升下降效果 + // 绘制第一条水波纹 + canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 200, i, mTotalHeight, mWavePaint); + + // 绘制第二条水波纹 + canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 200, i, mTotalHeight, mWavePaint); + } + + // 改变两条波纹的移动点 + mXOneOffset += mXOffsetSpeedOne; + mXTwoOffset += mXOffsetSpeedTwo; + + // 如果已经移动到结尾处,则重头记录 + if (mXOneOffset >= mTotalWidth) { + mXOneOffset = 0; + } + if (mXTwoOffset > mTotalWidth) { + mXTwoOffset = 0; + } + + // 引发view重绘,一般可以考虑延迟20-30ms重绘,空出时间片 + postInvalidate(); + } + + private void resetPositonY() { + // mXOneOffset代表当前第一条水波纹要移动的距离 + int yOneInterval = mYPositions.length - mXOneOffset; + // 使用System.arraycopy方式重新填充第一条波纹的数据 + System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, 0, yOneInterval); + System.arraycopy(mYPositions, 0, mResetOneYPositions, yOneInterval, mXOneOffset); + + int yTwoInterval = mYPositions.length - mXTwoOffset; + System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, 0, yTwoInterval); + System.arraycopy(mYPositions, 0, mResetTwoYPositions, yTwoInterval, mXTwoOffset); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + // 记录下view的宽高 + mTotalWidth = w; + mTotalHeight = h; + // 用于保存原始波纹的y值 + mYPositions = new float[mTotalWidth]; + // 用于保存波纹一的y值 + mResetOneYPositions = new float[mTotalWidth]; + // 用于保存波纹二的y值 + mResetTwoYPositions = new float[mTotalWidth]; + + // 将周期定为view总宽度 + mCycleFactorW = (float) (2 * Math.PI / mTotalWidth); + + // 根据view总宽度得出所有对应的y值 + for (int i = 0; i < mTotalWidth; i++) { + mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/OnSwipeListener.java b/app/src/main/java/com/yizhuan/erban/audio/widget/OnSwipeListener.java new file mode 100644 index 000000000..9af8d51e2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/OnSwipeListener.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.audio.widget; + +import android.support.v7.widget.RecyclerView; + +/** + * 录制声音页面.声音卡片滑动监听 + */ +public interface OnSwipeListener { + /** + * 卡片还在滑动时回调 + * + * @param viewHolder 该滑动卡片的viewHolder + * @param ratio 滑动进度的比例 + * @param direction 卡片滑动的方向,CardConfig.SWIPING_LEFT 为向左滑,CardConfig.SWIPING_RIGHT 为向右滑, + * CardConfig.SWIPING_NONE 为不偏左也不偏右 + */ + void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction); + + /** + * 卡片完全滑出时回调 + * + * @param viewHolder 该滑出卡片的viewHolder + * @param pos 该滑出卡片的索引 + * @param direction 卡片滑出的方向,CardConfig.SWIPED_LEFT 为左边滑出;CardConfig.SWIPED_RIGHT 为右边滑出 + */ + void onSwiped(RecyclerView.ViewHolder viewHolder, int pos, int direction); + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/RingProgressView.java b/app/src/main/java/com/yizhuan/erban/audio/widget/RingProgressView.java new file mode 100644 index 000000000..d2784d39d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/RingProgressView.java @@ -0,0 +1,114 @@ +package com.yizhuan.erban.audio.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; + +/** + * 录制声音页面的环形进度条 + */ +public class RingProgressView extends View { + // 圆环的颜色 + private int ringColor = 0x00FFFFFF; + // 圆环进度的颜色 + private int ringProgressColor = 0xFFFFFFFF; + // 圆环的宽度 + private int ringWidth = ScreenUtil.dip2px(4); + // 当前进度 + private int currentProgress = 0; + // 最大进度 + private int maxProgress = 100; + // 得到控件的宽度 + private int width; + // 画笔对象 + private Paint paint; + // 圆弧 + private RectF rectF; + + // 默认的构造方法,一般取这3个就够用了 + public RingProgressView(Context context) { + this(context, null); + } + + public RingProgressView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public RingProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + // 得到自定义资源数组 + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressView); + ringColor = typedArray.getColor(R.styleable.RingProgressView_ringColor, ringColor); + ringProgressColor = typedArray.getColor(R.styleable.RingProgressView_ringProgressColor, ringProgressColor); + ringWidth = (int) typedArray.getDimension(R.styleable.RingProgressView_ringWidth, ringWidth); + currentProgress = typedArray.getInt(R.styleable.RingProgressView_currentProgress, currentProgress); + maxProgress = typedArray.getColor(R.styleable.RingProgressView_maxProgress, maxProgress); + typedArray.recycle(); + + initData(); + } + + private void initData() { + paint = new Paint(); + paint.setAntiAlias(true); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(ringWidth); + paint.setStrokeCap(Paint.Cap.ROUND); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + width = getMeasuredWidth(); + rectF = new RectF(ringWidth / 2, ringWidth / 2, width - ringWidth / 2, width - ringWidth / 2); + } + + // 绘制 + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // 1. 计算圆心坐标及半径 + float centerX = width / 2; + float centerY = width / 2; + float radius = width / 2 - ringWidth / 2; + + + // 2. 画圆环 + paint.setColor(ringColor); + canvas.drawCircle(centerX, centerY, radius, paint); + + + // 3. 画圆弧 + paint.setColor(ringProgressColor); + canvas.drawArc(rectF, -90, currentProgress * 360 / maxProgress, false, paint); + } + + public int getCurrentProgress() { + return currentProgress; + } + + public void setCurrentProgress(int currentProgress) { + if (currentProgress > maxProgress) { + currentProgress = maxProgress; + } + this.currentProgress = currentProgress; + postInvalidate(); + } + + public int getMaxProgress() { + return maxProgress; + } + + public void setMaxProgress(int maxProgress) { + this.maxProgress = maxProgress; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceBottleFilterGenderBottomDialog.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceBottleFilterGenderBottomDialog.java new file mode 100644 index 000000000..eff17af1b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceBottleFilterGenderBottomDialog.java @@ -0,0 +1,104 @@ +package com.yizhuan.erban.audio.widget; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetDialog; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * 声音瓶子.筛选性别Dialog + */ +public class VoiceBottleFilterGenderBottomDialog extends BottomSheetDialog { + private RadioGroup rgVoiceFilterGender; + private TextView btnConfirm; + + private int currentFilterGender; + private OnVoiceBottleFilterGenderListener onFilterGenderListener; + + public VoiceBottleFilterGenderBottomDialog(@NonNull Context context, int currentFilterGender, OnVoiceBottleFilterGenderListener onFilterGenderListener) { + super(context); + this.currentFilterGender = currentFilterGender; + this.onFilterGenderListener = onFilterGenderListener; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ViewGroup view = (ViewGroup) View.inflate(getContext(), R.layout.layout_voice_bottle_filter_gender_bottom_dialog, null); + RadioButton rbVoiceFilterGenderFemale = view.findViewById(R.id.rb_voice_filter_gender_female); + RadioButton rbVoiceFilterGenderMale = view.findViewById(R.id.rb_voice_filter_gender_male); + RadioButton rbVoiceFilterGenderAll = view.findViewById(R.id.rb_voice_filter_gender_all); + rgVoiceFilterGender = view.findViewById(R.id.rg_voice_filter_gender); + btnConfirm = view.findViewById(R.id.btn_confirm); + + if (currentFilterGender == 1) { + rbVoiceFilterGenderFemale.setChecked(false); + rbVoiceFilterGenderMale.setChecked(true); + rbVoiceFilterGenderAll.setChecked(false); + } else if (currentFilterGender == 2) { + rbVoiceFilterGenderFemale.setChecked(true); + rbVoiceFilterGenderMale.setChecked(false); + rbVoiceFilterGenderAll.setChecked(false); + } else { + rbVoiceFilterGenderFemale.setChecked(false); + rbVoiceFilterGenderMale.setChecked(false); + rbVoiceFilterGenderAll.setChecked(true); + } + + setContentView(view); + + Window window = getWindow(); + if (window == null) { + return; + } + WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + if (windowManager == null) { + return; + } + Display display = windowManager.getDefaultDisplay(); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + display.getRealMetrics(realDisplayMetrics); + window.setAttributes(params); + window.setWindowAnimations(R.style.ErbanCommonWindowAnimationStyle); + window.findViewById(R.id.design_bottom_sheet).setBackgroundResource(android.R.color.transparent); + setCancelable(false); + + setListener(); + } + + private void setListener() { + btnConfirm.setOnClickListener(view -> { + if (onFilterGenderListener != null) { + if (rgVoiceFilterGender.getCheckedRadioButtonId() == R.id.rb_voice_filter_gender_female) { + onFilterGenderListener.onFilterGender(2); + } else if (rgVoiceFilterGender.getCheckedRadioButtonId() == R.id.rb_voice_filter_gender_male) { + onFilterGenderListener.onFilterGender(1); + } else if (rgVoiceFilterGender.getCheckedRadioButtonId() == R.id.rb_voice_filter_gender_all) { + onFilterGenderListener.onFilterGender(0); + } + } + dismiss(); + }); + } + + public interface OnVoiceBottleFilterGenderListener { + /** + * @param gender 0.不限 1.男 2.女 + */ + void onFilterGender(int gender); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardConfig.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardConfig.java new file mode 100644 index 000000000..242822a7b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardConfig.java @@ -0,0 +1,43 @@ +package com.yizhuan.erban.audio.widget; + +/** + * 录制声音页面.声音卡片滑动配置 + */ +public class VoiceCardConfig { + /** + * 显示可见的卡片数量 + */ + public static final int DEFAULT_SHOW_ITEM = 3; + /** + * 默认缩放的比例 + */ + public static final float DEFAULT_SCALE = 0.1f; + /** + * 卡片Y轴偏移量时按照14等分计算 + */ + public static final int DEFAULT_TRANSLATE_Y = 14; + /** + * 卡片滑动时默认倾斜的角度 + */ + public static final float DEFAULT_ROTATE_DEGREE = 15f; + /** + * 卡片滑动时不偏左也不偏右 + */ + public static final int SWIPING_NONE = 1; + /** + * 卡片向左滑动时 + */ + public static final int SWIPING_LEFT = 1 << 2; + /** + * 卡片向右滑动时 + */ + public static final int SWIPING_RIGHT = 1 << 3; + /** + * 卡片从左边滑出 + */ + public static final int SWIPED_LEFT = 1; + /** + * 卡片从右边滑出 + */ + public static final int SWIPED_RIGHT = 1 << 2;; +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardItemTouchHelperCallback.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardItemTouchHelperCallback.java new file mode 100644 index 000000000..a32a33277 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardItemTouchHelperCallback.java @@ -0,0 +1,152 @@ +package com.yizhuan.erban.audio.widget; + +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.util.Log; +import android.view.View; + +/** + * 录制声音页面.声音卡片滑动列表ItemTouchHelperCallback + */ +public class VoiceCardItemTouchHelperCallback extends ItemTouchHelper.Callback { + private OnSwipeListener mListener; + + public void setOnSwipedListener(OnSwipeListener mListener) { + this.mListener = mListener; + } + + /** + * 让RecyclerView拦截上下左右的滑动 + * + * @return 调用makeMovementFlags() + */ + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + int dragFlags = 0; + int swipeFlags = 0; + RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof VoiceCardLayoutManager) { + swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; + } + return makeMovementFlags(dragFlags, swipeFlags); + } + + /** + * 针对drag状态:在canDropOver()返回true时,会调用该方法 + * 可以实现拖动换位置的逻辑(需要自己处理变换位置的逻辑) + */ + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + return false; + } + + /** + * 针对swipe和drag状态:当一个item view在swipe、drag状态结束的时候调用 + * drag状态:当手指释放的时候会调用 + * swipe状态:当item从RecyclerView中删除的时候调用,一般我们会在onSwiped()函数里面删除掉指定的item view + */ + @Override + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + Log.e("ItemTouchHelperCallback", "clearView--->"); + viewHolder.itemView.setRotation(0f); + viewHolder.itemView.setAlpha(1); + viewHolder.itemView.setScaleY(1); + viewHolder.itemView.setScaleX(1); + } + + /** + * 针对swipe和drag状态:整个过程中一直会调用这个函数,随手指移动的view就是在super里面做到的(和ItemDecoration里面的onDraw()函数对应) + */ + @Override + public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + Log.e("ItemTouchHelperCallback", "onChildDraw--->" + + " dX = " + dX + + " dY = " + dY + + " actionState = " + actionState + + " isCurrentlyActive = " + isCurrentlyActive); + View itemView = viewHolder.itemView; + if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { + float ratio = dX / getThreshold(recyclerView, viewHolder); + // ratio 最大为 1 或 -1 + if (ratio > 1) { + ratio = 1; + } else if (ratio < -1) { + ratio = -1; + } + itemView.setRotation(ratio * VoiceCardConfig.DEFAULT_ROTATE_DEGREE); + int childCount = recyclerView.getChildCount(); + // 当数据源个数大于最大显示数时 + if (childCount > VoiceCardConfig.DEFAULT_SHOW_ITEM) { + for (int position = 1; position < childCount - 1; position++) { + int index = childCount - position - 1; + View view = recyclerView.getChildAt(position); + view.setScaleX(1 - index * VoiceCardConfig.DEFAULT_SCALE + Math.abs(ratio) * VoiceCardConfig.DEFAULT_SCALE); + view.setScaleY(1 - index * VoiceCardConfig.DEFAULT_SCALE + Math.abs(ratio) * VoiceCardConfig.DEFAULT_SCALE); + view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / VoiceCardConfig.DEFAULT_TRANSLATE_Y); + } + } else { + // 当数据源个数小于或等于最大显示数时 + for (int position = 0; position < childCount - 1; position++) { + int index = childCount - position - 1; + View view = recyclerView.getChildAt(position); + view.setScaleX(1 - index * VoiceCardConfig.DEFAULT_SCALE + Math.abs(ratio) * VoiceCardConfig.DEFAULT_SCALE); + view.setScaleY(1 - index * VoiceCardConfig.DEFAULT_SCALE + Math.abs(ratio) * VoiceCardConfig.DEFAULT_SCALE); + view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / VoiceCardConfig.DEFAULT_TRANSLATE_Y); + } + } + if (mListener != null) { + if (ratio != 0) { + mListener.onSwiping(viewHolder, ratio, ratio < 0 ? VoiceCardConfig.SWIPING_LEFT : VoiceCardConfig.SWIPING_RIGHT); + } else { + mListener.onSwiping(viewHolder, ratio, VoiceCardConfig.SWIPING_NONE); + } + } + } + } + + /** + * 针对swipe和drag状态:当swipe或者drag对应的ViewHolder改变的时候调用,可以通过重写这个函数获取到swipe、drag开始和结束时机, + * viewHolder 不为空的时候是开始,空的时候是结束 + */ + @Override + public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) { + Log.e("ItemTouchHelperCallback", "onSelectedChanged--->" + (viewHolder == null ? "onSelectedChanged()--->结束" + actionState : "onSelectedChanged()--->开始" + actionState)); + } + + /** + * 针对swipe状态:是否允许swipe(滑动)操作 + */ + @Override + public boolean isItemViewSwipeEnabled() { + Log.e("ItemTouchHelperCallback", "isItemViewSwipeEnabled--->"); + return true; + } + + /** + * 针对swipe状态:swipe 到达滑动消失的距离会回调函数 + * 一般在这个函数里面处理删除item的逻辑, + * 确切的来讲是swipe item滑出屏幕动画结束的时候调用 + */ + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + Log.e("ItemTouchHelperCallback", "onSwiped--->"); + // 移除 onTouchListener,否则触摸滑动会乱了 + viewHolder.itemView.setOnTouchListener(null); + int layoutPosition = viewHolder.getLayoutPosition(); + // 移除完item时回调 mListener + if (mListener != null) { + mListener.onSwiped(viewHolder, layoutPosition, direction == ItemTouchHelper.LEFT ? VoiceCardConfig.SWIPED_LEFT : VoiceCardConfig.SWIPED_RIGHT); + } + } + + private float getThreshold(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + return recyclerView.getWidth() * getSwipeThreshold(viewHolder); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardLayoutManager.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardLayoutManager.java new file mode 100644 index 000000000..d5ba0ab13 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardLayoutManager.java @@ -0,0 +1,109 @@ +package com.yizhuan.erban.audio.widget; + +import android.support.annotation.NonNull; +import android.support.v4.view.MotionEventCompat; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +/** + * 录制声音页面.声音卡片滑动列表LayoutManager + */ +public class VoiceCardLayoutManager extends RecyclerView.LayoutManager { + + private RecyclerView mRecyclerView; + private ItemTouchHelper mItemTouchHelper; + + public VoiceCardLayoutManager(@NonNull RecyclerView recyclerView, @NonNull ItemTouchHelper itemTouchHelper) { + this.mRecyclerView = checkIsNull(recyclerView); + this.mItemTouchHelper = checkIsNull(itemTouchHelper); + } + + private T checkIsNull(T t) { + if (t == null) { + throw new NullPointerException(); + } + return t; + } + + /** + * 给RecyclerView的ItemView生成LayoutParams + */ + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + /** + * 布局ItemView + */ + @Override + public void onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) { + detachAndScrapAttachedViews(recycler); + int itemCount = getItemCount(); + // 当数据源个数大于最大显示数时 + if (itemCount > VoiceCardConfig.DEFAULT_SHOW_ITEM) { + for (int position = VoiceCardConfig.DEFAULT_SHOW_ITEM; position >= 0; position--) { + final View view = recycler.getViewForPosition(position); + addView(view); + measureChildWithMargins(view, 0, 0); + int widthSpace = getWidth() - getDecoratedMeasuredWidth(view); + int heightSpace = getHeight() - getDecoratedMeasuredHeight(view); + // recyclerView 布局 + layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2, + widthSpace / 2 + getDecoratedMeasuredWidth(view), + heightSpace / 2 + getDecoratedMeasuredHeight(view)); + + if (position == VoiceCardConfig.DEFAULT_SHOW_ITEM) { + view.setScaleX(1 - (position - 1) * VoiceCardConfig.DEFAULT_SCALE); + view.setScaleY(1 - (position - 1) * VoiceCardConfig.DEFAULT_SCALE); + view.setTranslationY((position - 1) * view.getMeasuredHeight() / VoiceCardConfig.DEFAULT_TRANSLATE_Y); + view.setOnTouchListener(null); + } else if (position > 0) { + view.setScaleX(1 - position * VoiceCardConfig.DEFAULT_SCALE); + view.setScaleY(1 - position * VoiceCardConfig.DEFAULT_SCALE); + view.setTranslationY(position * view.getMeasuredHeight() / VoiceCardConfig.DEFAULT_TRANSLATE_Y); + view.setOnTouchListener(null); + } else { + view.setOnTouchListener(mOnTouchListener); + } + } + } else { + // 当数据源个数小于或等于最大显示数时 + for (int position = itemCount - 1; position >= 0; position--) { + final View view = recycler.getViewForPosition(position); + addView(view); + measureChildWithMargins(view, 0, 0); + int widthSpace = getWidth() - getDecoratedMeasuredWidth(view); + int heightSpace = getHeight() - getDecoratedMeasuredHeight(view); + // recyclerView 布局 + layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2, + widthSpace / 2 + getDecoratedMeasuredWidth(view), + heightSpace / 2 + getDecoratedMeasuredHeight(view)); + + if (position > 0) { + view.setScaleX(1 - position * VoiceCardConfig.DEFAULT_SCALE); + view.setScaleY(1 - position * VoiceCardConfig.DEFAULT_SCALE); + view.setTranslationY(position * view.getMeasuredHeight() / VoiceCardConfig.DEFAULT_TRANSLATE_Y); + view.setOnTouchListener(null); + } else { + view.setOnTouchListener(mOnTouchListener); + } + } + } + } + + private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(v); + if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { + mItemTouchHelper.startSwipe(childViewHolder); + } + return false; + } + }; +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardRecyclerView.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardRecyclerView.java new file mode 100644 index 000000000..c32990c58 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceCardRecyclerView.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.audio.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * 录制声音页面.声音卡片滑动列表 + */ +public class VoiceCardRecyclerView extends RecyclerView { + + private Canvas canvas; + + public VoiceCardRecyclerView(Context context) { + super(context); + } + + public VoiceCardRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public VoiceCardRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onDraw(Canvas c) { + canvas = c; + super.onDraw(c); + } + + public Canvas getCanvas() { + return canvas; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceLine.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceLine.java new file mode 100644 index 000000000..e6d144b09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceLine.java @@ -0,0 +1,225 @@ +package com.yizhuan.erban.audio.widget; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * 声音播放的波纹 + */ +public class VoiceLine extends View { + + public static final int VOICE_LINE_STYLE_REGULAR_LINE = 1;// 缺省图的规律的效果 + public static final int VOICE_LINE_STYLE_VOICE_CORRUGATED = 2;// 播放声音的动画效果:9个线条 + + + /*画笔*/ + private Paint mPaint; + + /*lineView*/ + private RectF[] lineList; + + /*lineView.height*/ + private List lineHeightList = new ArrayList<>(); + + /*lineView.Top坐标 Bottom坐标*/ + private List lineTopList = new ArrayList<>(); + private List lineBottomList = new ArrayList<>(); + + /*属性*/ + private int lineStyle = VOICE_LINE_STYLE_REGULAR_LINE;// 展示效果,默认:缺省图的规律的效果 + private float lineWidth = ScreenUtil.dip2px(3);// 线条宽度,单位PX + private float lineRadius = lineWidth / 2;// 线条圆角,为线条宽度的一半 + private float lineSpace = lineWidth;// 线条之间的间隙 + private int lineCount = 5;// 线条数量:默认5 + private float lineHeightMin = ScreenUtil.dip2px(15);// 线条最小高度 + private float lineHeightMax = ScreenUtil.dip2px(28);// 线条最大高度 + private float lineHeightMiddle = (lineHeightMax - lineHeightMin) / 2 + lineHeightMin;// 线条中界的数值:控制拉伸收缩 + + /*动画*/ + private boolean isPlayingAnim = false; + private ValueAnimator valueAnimator; + private float fraction; + + + public VoiceLine(Context context) { + this(context, null); + } + + public VoiceLine(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public VoiceLine(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initAttrs(context, attrs); + init(); + } + + private void initAttrs(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VoiceLine); + lineStyle = typedArray.getInt(R.styleable.VoiceLine_voice_line_style, lineStyle); + lineWidth = typedArray.getDimension(R.styleable.VoiceLine_voice_line_width, lineWidth); + lineRadius = lineWidth / 2; + lineSpace = lineWidth; + + lineCount = typedArray.getInt(R.styleable.VoiceLine_voice_line_count, lineCount); + if (lineStyle == VOICE_LINE_STYLE_VOICE_CORRUGATED) {// 如果是播放声音的动画效果:默认就是9个线条 + lineCount = 9; + } + lineList = new RectF[lineCount]; + + lineHeightMin = typedArray.getDimension(R.styleable.VoiceLine_voice_line_height_min, lineHeightMin); + lineHeightMax = typedArray.getDimension(R.styleable.VoiceLine_voice_line_height_max, lineHeightMax); + + /*设置中界的数值:控制拉伸收缩*/ + if (lineStyle == VOICE_LINE_STYLE_VOICE_CORRUGATED) {// 如果是播放声音的动画效果:默认中界数值为10 + lineHeightMiddle = ScreenUtil.dip2px(10); + } else { + lineHeightMiddle = (lineHeightMax - lineHeightMin) / 2 + lineHeightMin; + + } + typedArray.recycle(); + } + + private void init() { + mPaint = new Paint(); + mPaint.setColor(Color.WHITE); + mPaint.setStyle(Paint.Style.FILL); + + valueAnimator = ValueAnimator.ofInt(0, 1); + valueAnimator.setDuration(500); + valueAnimator.setRepeatCount(-1); + valueAnimator.setRepeatMode(ValueAnimator.REVERSE); + valueAnimator.addUpdateListener(animation -> { + fraction = animation.getAnimatedFraction(); + postInvalidate(); + }); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // 高度 + lineHeightList.clear(); + if (lineStyle == VOICE_LINE_STYLE_VOICE_CORRUGATED) {// 如果是播放声音的动画效果:给线条指定高度 + lineHeightList.add(ScreenUtil.dip2px(10)); + lineHeightList.add(ScreenUtil.dip2px(16)); + lineHeightList.add(ScreenUtil.dip2px(10)); + lineHeightList.add(ScreenUtil.dip2px(6)); + lineHeightList.add(ScreenUtil.dip2px(10)); + lineHeightList.add(ScreenUtil.dip2px(12)); + lineHeightList.add(ScreenUtil.dip2px(19)); + lineHeightList.add(ScreenUtil.dip2px(11)); + lineHeightList.add(ScreenUtil.dip2px(7)); + lineWidth = ScreenUtil.dip2px(3); + lineRadius = lineWidth / 2; + lineSpace = lineWidth; + } else { + for (int i = 0; i < lineCount; i++) { + if (i == 0) { + lineHeightList.add((int) lineHeightMax); + } else if (i == lineCount - 1) { + lineHeightList.add((int) lineHeightMax); + } else { + lineHeightList.add((int) lineHeightMin); + } + } + lineWidth = ScreenUtil.dip2px(6); + lineRadius = lineWidth / 2; + lineSpace = lineWidth; + } + + // 左边的坐标 + float[] lineLeftList = new float[lineCount]; + for (int i = 0; i < lineCount; i++) { + if (i == 0) { + lineLeftList[i] = 0f; + } else { + lineLeftList[i] = lineLeftList[i - 1] + lineWidth + lineSpace; + } + } + + // 右边的坐标 + float[] lineRightList = new float[lineCount]; + for (int i = 0; i < lineCount; i++) { + lineRightList[i] = lineLeftList[i] + lineSpace; + } + + // Top坐标 + lineTopList.clear(); + float lineMaxHeight = getMeasuredHeight();// 单位PX + for (int i = 0; i < lineCount; i++) { + lineTopList.add((lineMaxHeight - lineHeightList.get(i)) / 2); + } + // Bottom坐标 + lineBottomList.clear(); + for (int i = 0; i < lineCount; i++) { + lineBottomList.add(lineTopList.get(i) + lineHeightList.get(i)); + } + + // LineView + for (int i = 0; i < lineCount; i++) { + lineList[i] = new RectF(lineLeftList[i], lineTopList.get(i), lineRightList[i], lineBottomList.get(i)); + } + + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (!isPlayingAnim) { + for (int i = 0; i < lineList.length; i++) { + lineList[i].top = lineTopList.get(i); + lineList[i].bottom = lineBottomList.get(i); + canvas.drawRoundRect(lineList[i], lineRadius, lineRadius, mPaint); + } + } else { + for (int i = 0; i < lineList.length; i++) { + int centerIndex = lineList.length % 2 == 0 ? lineList.length / 2 : lineList.length / 2 + 1; + if (i == centerIndex - 1) {// 中间拉伸并且增加长度 + lineList[i].top = lineTopList.get(i) - fraction / 2 * lineHeightList.get(i); + lineList[i].bottom = lineBottomList.get(i) + fraction / 2 * lineHeightList.get(i); + canvas.drawRoundRect(lineList[i], lineRadius, lineRadius, mPaint); + } else { + if (lineHeightList.get(i) <= lineHeightMiddle) {// 拉伸 + lineList[i].top = lineTopList.get(i) - fraction / 2 * lineHeightList.get(i) * 0.5f; + lineList[i].bottom = lineBottomList.get(i) + fraction / 2 * lineHeightList.get(i) * 0.5f; + canvas.drawRoundRect(lineList[i], lineRadius, lineRadius, mPaint); + } else {// 收缩 + lineList[i].top = lineTopList.get(i) + fraction / 2 * lineHeightList.get(i) * 0.5f; + lineList[i].bottom = lineBottomList.get(i) - fraction / 2 * lineHeightList.get(i) * 0.5f; + canvas.drawRoundRect(lineList[i], lineRadius, lineRadius, mPaint); + } + } + } + } + } + + public void startAnim() { + this.isPlayingAnim = true; + valueAnimator.start(); + } + + public void stopAnim() { + this.isPlayingAnim = false; + if (valueAnimator != null) { + valueAnimator.cancel(); + } + postInvalidate(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceWave.java b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceWave.java new file mode 100644 index 000000000..629daf4d7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/audio/widget/VoiceWave.java @@ -0,0 +1,193 @@ +package com.yizhuan.erban.audio.widget; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.util.AttributeSet; +import android.view.View; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * 录制声音的波纹 + */ +public class VoiceWave extends View { + + private Paint paintVoiceLine; + private List paths = null; + + /*属性*/ + private int voiceLineColor = Color.WHITE;// 波动的线的颜色 + private int lineSpeed = 90;// 波动线的横向移动速度,数值越大线移动越慢,默认90 + private float maxVolume = 100;// 所输入音量的最大值 + private int sensibility = 4;// 灵敏度 + private int fineness = 1;// 精细度,绘制曲线的时候,每几个像素绘制一次,默认是1,值越小,曲线越顺滑 + + + // 音量 + private float volume = 10; + private float targetVolume = 1; + + private long lastTime = 0;// 记录最后绘制的时间 + private float translateX = 0; + private boolean isSet = false; + private boolean isClear = true;// 是否清楚为初始状态,清空振幅 + + private ValueAnimator valueAnimator; + + private int viewHeight; + + public VoiceWave(Context context) { + super(context); + } + + public VoiceWave(Context context, AttributeSet attrs) { + super(context, attrs); + initAttrs(context, attrs); + initData(); + } + + public VoiceWave(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initAttrs(context, attrs); + initData(); + } + + private void initAttrs(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VoiceWave); + voiceLineColor = typedArray.getColor(R.styleable.VoiceWave_voice_wave_line_color, voiceLineColor); + lineSpeed = typedArray.getInt(R.styleable.VoiceWave_voice_wave_line_speed, lineSpeed); + maxVolume = typedArray.getFloat(R.styleable.VoiceWave_voice_wave_max_volume, maxVolume); + sensibility = typedArray.getInt(R.styleable.VoiceWave_voice_wave_sensibility, sensibility); + fineness = typedArray.getInt(R.styleable.VoiceWave_voice_wave_fineness, fineness); + typedArray.recycle(); + } + + private void initData() { + paths = new ArrayList<>(2); + for (int i = 0; i < 2; i++) { + paths.add(new Path()); + } + + paintVoiceLine = new Paint(); + paintVoiceLine.setColor(voiceLineColor); + paintVoiceLine.setAntiAlias(true); + paintVoiceLine.setStyle(Paint.Style.STROKE); + paintVoiceLine.setStrokeWidth(ScreenUtil.dip2px(2)); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + viewHeight = getHeight(); + } + + @Override + protected void onDraw(Canvas canvas) { + lineChange(); + canvas.save(); + int moveY = viewHeight / 2; + for (int i = 0; i < paths.size(); i++) { + paths.get(i).reset(); + paths.get(i).moveTo(getWidth(), viewHeight / 2); + } + for (float i = getWidth() - 1; i >= 0; i -= fineness) { + // 振幅 + float amplitude; + if (isClear) { + amplitude = 1; + } else { + amplitude = volume * i / getWidth() - volume * i * i / getWidth() / getWidth(); + } +// Log.e("VoiceWave", "是否清零 = " + isClear + " 振幅 = " + amplitude); + for (int n = 1; n <= paths.size(); n++) { + float sin = amplitude * (float) Math.sin((i - Math.pow(1.22, n)) * Math.PI / 180 - translateX); + float lineToY; + if (n == 1) { + lineToY = 10 * sin / paths.size() + moveY; + } else { + lineToY = 25 * sin / paths.size() + moveY; + } +// float lineToY = 2 * n * sin / paths.size() - 15 * sin / paths.size() + moveY; + paths.get(n - 1).lineTo(i, lineToY); + } + } + for (int n = 0; n < paths.size(); n++) { + if (n == 0) { + paintVoiceLine.setAlpha(255); + } else { + paintVoiceLine.setAlpha(200); + } + if (paintVoiceLine.getAlpha() > 0) { + canvas.drawPath(paths.get(n), paintVoiceLine); + } + } + canvas.restore(); + } + + private void lineChange() { + if (lastTime == 0) { + lastTime = System.currentTimeMillis(); + translateX += 1.5; + } else { + if (System.currentTimeMillis() - lastTime > lineSpeed) { + lastTime = System.currentTimeMillis(); + translateX += 1.5; + } else { + return; + } + } + if (volume < targetVolume && isSet) { + volume += viewHeight / 30; + } else { + isSet = false; + if (volume <= 10) { + volume = 10; + } else { + if (volume < viewHeight / 30) { + volume -= viewHeight / 60; + } else { + volume -= viewHeight / 30; + } + } + } + } + + public void setVolume(int volume) { + if (volume > maxVolume * sensibility / 25) { + isSet = true; + targetVolume = viewHeight * volume / 2 / maxVolume; + } + } + + public void startAnim() { + isClear = false; + if (valueAnimator == null) { + valueAnimator = ValueAnimator.ofInt(0, 1); + valueAnimator.setDuration(500); + valueAnimator.setRepeatCount(-1); + valueAnimator.setRepeatMode(ValueAnimator.REVERSE); + valueAnimator.addUpdateListener(valueAnimator -> invalidate()); + } + if (!valueAnimator.isRunning()) { + valueAnimator.start(); + } + } + + public void stopAnim() { + isClear = true; + postInvalidate(); + if (valueAnimator != null) { + valueAnimator.cancel(); + valueAnimator = null; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/BottomViewListenerWrapper.java b/app/src/main/java/com/yizhuan/erban/avroom/BottomViewListenerWrapper.java new file mode 100644 index 000000000..a61feef64 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/BottomViewListenerWrapper.java @@ -0,0 +1,64 @@ +package com.yizhuan.erban.avroom; + +/** + * Created by chenran on 2017/11/21. + */ + +public abstract class BottomViewListenerWrapper { + public BottomViewListenerWrapper() { + + } + + public void onOpenMicBtnClick() { + + } + + public void onSendMsgBtnClick() { + + } + + public void onSendFaceBtnClick() { + + } + + public void onSendGiftBtnClick() { + + } + + public void onRemoteMuteBtnClick() { + + } + + public void onMoreBtnClick() { + + } + + /** + * 转成ktv模式 + */ + public void onTransformKTVClick() { + + } + + /** + * 转成游戏模式 + */ + public void onTransformGameClick() { + + } + + /** + * 点击排麦按钮 + */ + public void onMicQueueClick() { + + } + + /** + * 房间内私聊 + */ + public void onRoomMessageClick() { + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ButtonItemFactory.java b/app/src/main/java/com/yizhuan/erban/avroom/ButtonItemFactory.java new file mode 100644 index 000000000..b9e19fb1b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ButtonItemFactory.java @@ -0,0 +1,655 @@ +package com.yizhuan.erban.avroom; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.text.TextUtils; + +import com.netease.nim.uikit.business.uinfo.UserInfoHelper; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.RoomBlackListActivity; +import com.yizhuan.erban.avroom.activity.RoomManagerListActivity; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.public_chat_hall.widget.ShutUpDialog; +import com.yizhuan.erban.ui.im.avtivity.NimFriendModel; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.tutu.room_chat.activity.RoomMsgActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.kick.KickModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatLogKey; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.bean.KickOutExtBean; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SAdminOptUtil; +import com.yizhuan.xchat_android_core.super_admin.util.SaAttachmentFactory; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + + +/** + * @author chenran + * @date 2017/10/11 + */ +public class ButtonItemFactory { + + /** + * 创建相关的buttons 添加到资料卡片 + * + * @param context context + * @param uid uid or 云信account + * @param isNeedGiftItem ture能送礼物 + * @param isNeedRoomItem ture表示房间相关的操作,比如踢出房间,外部调用一般置为false + * @param isInRoom ture表现在房间内,giftdialog在不在房间有不同的ui + * @param listener dialog的监听回调 + * @return List + */ + public static List createCommonButtonItems( + Context context, + long uid, + boolean isNeedGiftItem, + boolean isNeedRoomItem, + boolean isInRoom, + GiftDialog.OnGiftDialogBtnClickListener listener) { + + if (uid <= 0) return null; + String account = String.valueOf(uid); + // 判断在不在麦上 + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByAccount(account); + // 麦上的人员信息,麦上的坑位信息 + ChatRoomMember chatRoomMember = null; + String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + //null表示不在麦位,比如,点击公屏的用户时 + if (roomQueueInfo != null) { + chatRoomMember = roomQueueInfo.mChatRoomMember; + } + if (chatRoomMember == null) { + chatRoomMember = AvRoomDataManager.get().getChatRoomMember(account); + } + //account和chatRoomMember 不会同时为空,如果同时为空,则是前面传参出错 + boolean isMySelf = Objects.equals(currentUid, account); + if (isMySelf) { + return null; + } + List buttonItems = new ArrayList<>(); + //ture则表示需要传入此类型button + boolean gift = false; + boolean magic = false; + if (isNeedGiftItem) { + gift = true; + } + //提出房间 + boolean kickOutRoom = false; + //设置管理员 + boolean mark_manager = false; + //取消管理员 + boolean no_mark_manager = false; + //黑名单 + boolean mart_black = false; + boolean isTargetRoomAdmin = AvRoomDataManager.get().isRoomAdmin(account); + boolean isTargetRoomOwner = AvRoomDataManager.get().isRoomOwner(account); + //资料卡片需要房间操作的按钮,不去判断是否在房间内 + if (AvRoomDataManager.get().isRoomOwner()) { + //房主操作 + //点击不是自己 + if (isNeedRoomItem) { + //提出房间 + kickOutRoom = true; + //管理员 + if (!isTargetRoomAdmin) { + mark_manager = true; + } else { + no_mark_manager = true; + } + //黑名单 + mart_black = true; + } + + } else if (AvRoomDataManager.get().isRoomAdmin()) { + //管理员操作 + //不是自己 + if (!isTargetRoomAdmin && !isTargetRoomOwner) { + //非房主或管理员 + if (isNeedRoomItem) { + //踢出房间 + kickOutRoom = true; + //加入黑名单 + mart_black = true; + } + } + } else { + //游客操作 + //不是自己 + } + if (gift) { + if (!SuperAdminUtil.isSuperAdmin()) { + buttonItems.add(createSendGiftItem(context, uid, isInRoom, listener)); + } + } + if (magic) { + buttonItems.add(createSendMagicItem(context, account, isInRoom, listener)); + } + // 私聊 + buttonItems.add(createPrivateChatItem(context, account, isInRoom)); + //装扮 + if (!SuperAdminUtil.isSuperAdmin()) { + buttonItems.add(createSendDecorationItem(context, uid)); + } + //关注 + buttonItems.add(createAttentItem()); + + final RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) return buttonItems; + + //超管能踢人拉黑用户,房主除外 + if (!isTargetRoomOwner && SuperAdminUtil.isSuperAdmin()) { + kickOutRoom = true; + mart_black = true; + } + + if (kickOutRoom) { + buttonItems.add(createKickOutRoomItem(context, String.valueOf(currentRoom.getRoomId()), + account, getNick(chatRoomMember, account))); + } + if (mark_manager) { + buttonItems.add(createMarkManagerListItem(String.valueOf(currentRoom.getRoomId()), account, true)); + } + if (no_mark_manager) { + buttonItems.add(createMarkManagerListItem(String.valueOf(currentRoom.getRoomId()), account, false)); + } + if (mart_black) { + buttonItems.add(createMarkBlackListItem( + context, + String.valueOf(currentRoom.getRoomId()), + account, + getNick(chatRoomMember, account)) + ); + } + return buttonItems; + } + + /** + * 创建相关的buttons 添加到资料卡片 + * + * @param context context + * @param uid uid or 云信account + * @param listener dialog的监听回调 + * @return List + */ + public static List createPublicChatHallButtonItems( + Context context, + long uid, + boolean isInRoom, + GiftDialog.OnGiftDialogBtnClickListener listener) { + if (uid <= 0) return null; + String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + String account = String.valueOf(uid); + //account和chatRoomMember 不会同时为空,如果同时为空,则是前面传参出错 + boolean isMySelf = Objects.equals(currentUid, account); + if (isMySelf) { + return null; + } + List buttonItems = new ArrayList<>(); + //不在房间内,也不需要魔法 + buttonItems.add(createSendGiftItem(context, uid, true, true, listener)); + // 私聊 + buttonItems.add(createPrivateChatItem(context, account, isInRoom)); + //装扮和关注目前是都有的操作 + buttonItems.add(createSendDecorationItem(context, uid)); + buttonItems.add(createAttentItem()); + buttonItems.add(createFindMeItem()); + if (PublicChatHallDataManager.get().isRoomAdmin()) { + buttonItems.add(createShutupItem(context, uid)); + } + return buttonItems; + } + + /** + * 踩TA,当该人再房间中的时候,进入他所在的房间 + * + * @return + */ + private static ViewItem createFindMeItem() { + ViewItem viewItem = new ViewItem("踩Ta", R.drawable.icon_dialog_find_ta, null); + viewItem.isFindTa = true; + return viewItem; + } + + /** + * 根据account获取昵称 + */ + private static String getNick(ChatRoomMember member, String account) { + String nick = null; + if (member != null) { + nick = member.getNick(); + } else { + nick = UserInfoHelper.getUserDisplayName(account); + } + if (TextUtils.isEmpty(nick)) { + nick = ""; + } + return nick; + } + + + /** + * 送魔法 + */ + public static ViewItem createSendMagicItem(final Context context, String account, boolean isInRoom, + final GiftDialog.OnGiftDialogBtnClickListener listener) { + return new ViewItem("施魔法", R.drawable.icon_dialog_send_magic, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_magic_send_click, "资料卡片-送魔法"); + + GiftDialog dialog = new GiftDialog(context, JavaUtil.str2long(account), isInRoom, true); + if (listener != null) { + dialog.setGiftDialogBtnClickListener(listener); + } + dialog.show(); + }); + } + + + /** + * 私聊 + */ + public static ViewItem createPrivateChatItem(final Context context, String account, boolean isInRoom) { + return new ViewItem("私聊", R.mipmap.ic_private_chat, () -> { + if (isInRoom) { + RoomMsgActivity.startForPrivateChat(context, account); + } else { + NimP2PMessageActivity.start(context, account); + } + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.DATA_CARD_CHAT, "资料卡片-私聊计数"); + }); + } + + /** + * 抱Ta下麦 用户卡片 + */ + public static ViewItem createKickDownMicItem(final String account, String nick) { + return new ViewItem(BasicConfig.INSTANCE.getAppContext().getString(R.string.embrace_down_mic), + () -> { + if (AvRoomDataManager.get().isOnMic(Long.valueOf(account))) { + int micPosition = AvRoomDataManager.get().getMicPosition(Long.valueOf(account)); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(micPosition); + if (roomQueueInfo != null) { + String level = (String) NobleUtil.getResource(NobleResourceType.KEY_LEVEL, roomQueueInfo.mChatRoomMember); + String name = NobleUtil.getNobleName(level); + if (!NobleUtil.canKickMicroOrNot(level)) { + // 如果不能被踢下麦,则直接返回 +// Toast.makeText(BasicConfig.INSTANCE.getAppContext(), "不能踢" + name + "陛下哦", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("不能踢" + name + "陛下哦"); + return; + } + } + IMNetEaseManager.get().downMicroPhoneBySdk(micPosition, null); + + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + IMNetEaseManager.get().kickMicroPhoneBySdk(Long.valueOf(account), nick, + roomInfo.getRoomId()).subscribe(chatRoomMessage -> + KickModel.get().sendMessage(chatRoomMessage) + , throwable -> throwable.printStackTrace()); + } + } + + + }); + } + + /** + * 送装扮 + */ + public static ViewItem createSendDecorationItem(final Context context, final long uid) { + return new ViewItem("送装扮", R.drawable.icon_dialog_send_decaration, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_decoration_send_click, "资料卡片-送装扮"); + + DecorationStoreActivity.start(context, uid); + }); + } + + /** + * 关注or取消 + */ + public static ViewItem createAttentItem() { + ViewItem viewItem = new ViewItem("关注Ta", R.drawable.icon_dialog_attent, null); + viewItem.isAttent = true; + return viewItem; + } + + /** + * 踢出房间: 先强制下麦,再踢出房间 + */ + public static ViewItem createKickOutRoomItem(Context context, final String roomId, + final String account, String nick) { + return new ViewItem("踢出房间", R.drawable.icon_dialog_kickout_room, new ViewItem.OnClickListener() { + @Override + public void onClick() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_kickout_room_click, "资料卡片-踢出房间"); + + new DialogManager(context).showOkCancelDialog((AvRoomDataManager.get().isOpenKTV() ? "KTV模式下将自动删除ta的歌曲," : "") + "是否要将此用户踢出房间?", + true, new DialogManager.AbsOkDialogListener() { + @SuppressLint("CheckResult") + @Override + public void onOk() { + final Map reason = new HashMap<>(); + reason.put("reason", "kick"); + if (AvRoomDataManager.get().isOnMic(JavaUtil.str2long(account))) { + int micPosition = AvRoomDataManager.get().getMicPosition(JavaUtil.str2long(account)); + reason.put("micPosition", micPosition); + reason.put("account", account); + IMNetEaseManager.get().downMicroPhoneBySdk(micPosition, null); + } + + reason.put(StatLogKey.USER_ID_KICK, String.valueOf(AuthModel.get().getCurrentUid())); + int role = SuperAdminUtil.isSuperAdmin() ? 1 : 2; + reason.put(KickOutExtBean.KEY_ROLE, role); + + //如果是超管踢人 + //超管踢普通人的话, 先将自己升级为管理员,再踢人 + if (SAdminOptUtil.kickOutNormalUser(account, nick, reason)) { + LogUtil.print("super admin kick out normal user"); + SuperAdminModel superAdminModel = new SuperAdminModel(); + superAdminModel.roomOperate(SuperAdminModel.KICK_OUT_ROOM, JavaUtil.str2long(account)).subscribe(); + return; + } + //踢房间管理员 + //通过超管发消息管理员,管理员退出房间的方式踢人 + if (SAdminOptUtil.kickOutRoomAdmin(account, nick)) { + LogUtil.print("super admin kick out room admin"); + return; + } + IMNetEaseManager.get().kickMemberFromRoomBySdk(JavaUtil.str2long(roomId), + JavaUtil.str2long(account), reason) + .subscribe((s, throwable) -> { + if (throwable != null) { + if (throwable.getMessage().contains("404")) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), "用户不在房间"); + } else { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), throwable.getMessage()); + } + } else { + IMNetEaseManager.get().kickMemberFromRoomBySdk(Long.valueOf(roomId), + Long.valueOf(account), nick) + .subscribe(chatRoomMessage -> + KickModel.get().sendMessage(chatRoomMessage)); + + Logger.e("kick out mic and room: " + s); + IMNetEaseManager.get().noticeKickOutChatMember(null, account); + } + }); + } + }); + } + }); + } + + /** + * 查看资料弹窗 + */ + public static ViewItem createCheckUserInfoDialogItem(final Context context, final String account) { + return new ViewItem("查看资料", R.drawable.icon_send_gift_ture, () -> new UserInfoDialog(context, Long.valueOf(account)).show()); + } + + /** + * 查看资料页面 + */ + public static ButtonItem createCheckUserInfoActivityItem(final Context context, final String account) { + return new ButtonItem("查看资料", () -> UserInfoActivity.Companion.start(context, Long.valueOf(account))); + } + + + /** + * 下麦旁听,用户卡片 + */ + public static ViewItem createDownMicItem(ViewItem.OnClickListener onClickListener) { + return new ViewItem(BasicConfig.INSTANCE.getAppContext().getString(R.string.down_mic_text), onClickListener); +// return new ButtonItem(BasicConfig.INSTANCE.getAppContext().getString(R.string.down_mic_text), +// 0, ButtonItem.BUTTON_TYPE_BOTTOM, R.layout.item_room_user_dialog_bottom_button, +// onClickListener); + } + + + //设置管理员 + public static ViewItem createMarkManagerListItem(final String roomId, final String account, final boolean mark) { + String title = BasicConfig.INSTANCE.getAppContext().getString(mark ? R.string.set_manager : R.string.remove_manager); + int icon = mark ? R.drawable.icon_dialog_set_manager_ture : R.drawable.icon_dialog_set_manager_false; + return new ViewItem(title, icon, () -> { + if (mark) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_set_admin_click, "资料卡片-设置管理员"); + } + IMNetEaseManager.get().markManagerListBySdk(roomId, account, mark, null); + }); + } + + //加入黑名单 + public static ViewItem createMarkBlackListItem(final Context context, + final String roomId, + final String account, + String nick) { + return new ViewItem("拉入黑名单", R.drawable.icon_dialog_mark_black_list, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_join_blacklist_click, "资料卡片-加入黑名单"); + + new DialogManager(context).showOkCancelDialog( + "是否将" + nick + "加入黑名单?加入后他将无法进入此房间" + + (AvRoomDataManager.get().mCurrentRoomInfo != null && AvRoomDataManager.get().isOpenKTV() ? "KTV模式下将自动删除ta的歌曲" : ""), true, + () -> { + + Single single; + if (SuperAdminUtil.isSuperAdmin()) { + //超管拉黑 + single = AvRoomModel.get().markBlack(JavaUtil.str2long(account)); + SuperAdminModel superAdminModel = new SuperAdminModel(); + superAdminModel.roomOperate(SuperAdminModel.ADD_BLACK_LIST, JavaUtil.str2long(account)).subscribe(); + } else { + single = IMNetEaseManager.get().markBlackListBySdk(roomId, account, true); + } + //拉黑后,下麦和管理操作保持一致 + single + //发公屏 + .flatMap((Function>) s -> { + if (SuperAdminUtil.isSuperAdmin()) { + ChatRoomMessage chatRoomMessage = SaAttachmentFactory + .createBlackOrKickOutChatRoomMsg(account, nick, 1); + return IMNetEaseManager.get().sendChatRoomMessage(chatRoomMessage, false); + } + return IMNetEaseManager.get().markBlackListBySdk(roomId, account, true, nick); + }) + .doOnSuccess(chatRoomMessage -> + KickModel.get().onSendRoomMessageSuccess(chatRoomMessage)) + .flatMap(s -> { + int micPosition = AvRoomDataManager.get().getMicPosition(account); + return IMNetEaseManager.get().downMicroPhoneBySdk(micPosition); + }) + .subscribe(); + }); + + + }); + } + + //发送礼物 + + /** + * @param isInRoom true 在房间内弹起 + * @param isHideMagicTab true 隐藏魔法 + * @return ViewItem + */ + public static ViewItem createSendGiftItem(final Context context, long otherUid, boolean isInRoom, boolean isHideMagicTab, + final GiftDialog.OnGiftDialogBtnClickListener giftDialogBtnClickListener) { + return new ViewItem("送礼物", R.drawable.icon_send_gift_ture, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_gift_send_click, "资料卡片-送礼物"); + + GiftDialog dialog = new GiftDialog(context, otherUid, isInRoom, false, isHideMagicTab); + if (giftDialogBtnClickListener != null) { + dialog.setGiftDialogBtnClickListener(giftDialogBtnClickListener); + } + dialog.show(); + }); + } + + /** + * 公聊大厅禁言 + */ + public static ViewItem createShutupItem(Context context, long uid) { + return new ViewItem("禁言", R.drawable.icon_shut_up, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_banword, "公聊大厅禁言"); + new ShutUpDialog(context, uid).openDialog(); + }); + } + + + /** + * @param isInRoom true 在房间内弹起 + * @return ViewItem + */ + public static ViewItem createSendGiftItem(final Context context, long otherUid, boolean isInRoom, + final GiftDialog.OnGiftDialogBtnClickListener giftDialogBtnClickListener) { + return createSendGiftItem(context, otherUid, isInRoom, false, giftDialogBtnClickListener); + } + + /** + * 拉黑 + */ + public static ButtonItem createAddToBlackListItem(DialogManager dialogManager, String account) { + return new ButtonItem("拉黑", () -> { + dialogManager.showOkCancelDialog("加入黑名单,你将不再收到对方的信息", true, + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + NimFriendModel.get().addToBlackList(account) + .subscribe((aBoolean, throwable) -> { +// Toast.makeText(BasicConfig.INSTANCE.getAppContext(), +// (throwable == null) ? "已经成功将对方加入黑名单" : "加入黑名单失败", +// Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort((throwable == null) ? "已经成功将对方加入黑名单" : "加入黑名单失败"); + }); + } + }); + }); + } + + /** + * 举报 + */ + public static ButtonItem createReportItem(Context context, long uid, String reportType) { + return new ButtonItem("举报", () -> UIHelper.showReportPage(context, uid, reportType)); + } + + + /** + * 禁麦,用户卡片 + */ + public static ViewItem createLockMicItem(final int position, ViewItem.OnClickListener onClickListener) { + return new ViewItem("闭麦", onClickListener); + } + + /** + * 禁麦 个人弹窗的 + */ + public static ButtonItem createLockMicDialogItem(final int position, ButtonItem.OnClickListener onClickListener) { + return new ButtonItem("禁麦", 0, ButtonItem.BUTTON_TYPE_BOTTOM, + R.layout.item_room_user_dialog_bottom_button, onClickListener); + } + + /** + * 取消禁麦 个人弹窗 + */ + public static ButtonItem createOpenMicItem(final int position, ButtonItem.OnClickListener onClickListener) { + return new ButtonItem("解禁", onClickListener); + } + + /** + * 取消禁麦 + */ + public static ViewItem createFreeMicItem(final int position, ViewItem.OnClickListener onClickListener) { + return new ViewItem(BasicConfig.INSTANCE.getAppContext().getString(R.string.no_forbid_mic), onClickListener); + } + + /** + * 取消禁麦, 资料卡片 + */ + public static ViewItem createFreeMicCardItem(final int position, ViewItem.OnClickListener onClickListener) { + return new ViewItem("开麦", onClickListener); + } + + public static ButtonItem createManagerListItem(final Context context) { + ButtonItem buttonItem = new ButtonItem("管理员", () -> RoomManagerListActivity.start(context)); + return buttonItem; + } + + public static ButtonItem createBlackListItem(final Context context) { + ButtonItem buttonItem = new ButtonItem("黑名单", () -> RoomBlackListActivity.start(context)); + return buttonItem; + } + + /** + * 锁麦,资料卡片 + */ + public static ViewItem createLockMicListItem(final Context context, ViewItem.OnClickListener onClickListener) { + return new ViewItem("锁麦", onClickListener); + } + + /** + * 解封,资料卡片 + */ + public static ViewItem createUnLockMicListItem(final Context context, ViewItem.OnClickListener onClickListener) { + return new ViewItem("解锁", onClickListener); + } + + public static List createMiniWorldGroupButtonItems( + Context context, + long uid, + boolean isInRoom, + GiftDialog.OnGiftDialogBtnClickListener listener) { + if (uid <= 0) return null; + String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + String account = String.valueOf(uid); + //account和chatRoomMember 不会同时为空,如果同时为空,则是前面传参出错 + boolean isMySelf = Objects.equals(currentUid, account); + if (isMySelf) { + return null; + } + List buttonItems = new ArrayList<>(); + //不在房间内,也不需要魔法 + buttonItems.add(createSendGiftItem(context, uid, true, true, listener)); + // 私聊 + buttonItems.add(createPrivateChatItem(context, account, isInRoom)); + //装扮和关注目前是都有的操作 + buttonItems.add(createSendDecorationItem(context, uid)); + buttonItems.add(createAttentItem()); + buttonItems.add(createFindMeItem()); + return buttonItems; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ChatMemberDiffUtilCallback.java b/app/src/main/java/com/yizhuan/erban/avroom/ChatMemberDiffUtilCallback.java new file mode 100644 index 000000000..06538a375 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ChatMemberDiffUtilCallback.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.avroom; + +import android.support.v7.util.DiffUtil; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.List; +import java.util.Objects; + +/** + * @author Administrator + */ +public class ChatMemberDiffUtilCallback extends DiffUtil.Callback { + private List mOldMemberList, mNewMemberList; + + public ChatMemberDiffUtilCallback(List oldMemberList, List newMemberList) { + mOldMemberList = oldMemberList; + mNewMemberList = newMemberList; + } + + @Override + public int getOldListSize() { + return mOldMemberList == null ? 0 : mOldMemberList.size(); + } + + @Override + public int getNewListSize() { + return mNewMemberList == null ? 0 : mNewMemberList.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return Objects.equals(mOldMemberList.get(oldItemPosition).getAccount(), + mNewMemberList.get(newItemPosition).getAccount()); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + ChatRoomMember oldItem = mOldMemberList.get(oldItemPosition); + ChatRoomMember newItem = mNewMemberList.get(newItemPosition); + return Objects.equals(oldItem.getAccount(), newItem.getAccount()) + && Objects.equals(oldItem.getNick(), newItem.getNick()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/SoftKeyBoardListener.java b/app/src/main/java/com/yizhuan/erban/avroom/SoftKeyBoardListener.java new file mode 100644 index 000000000..2ed71337d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/SoftKeyBoardListener.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.avroom; + +import android.app.Activity; +import android.graphics.Rect; +import android.view.View; +import android.view.ViewTreeObserver; + +import java.lang.ref.WeakReference; + +/** + * 该类用于监听软键盘是否显示并获取其高度 + *

+ * Success is the sum of small efforts, repeated day in and day out. + * 成功就是日复一日那一点点小小努力的积累。 + * AndroidGroup:158423375 + * Author:Johnny + * AuthorQQ:956595454 + * AuthorWX:Qiang_it + * AuthorPhone:nothing + * Created by 2016/9/22. + */ +public class SoftKeyBoardListener { + + private View rootView;/*activity的根视图*/ + private int rootViewVisibleHeight;/*纪录根视图的显示高度*/ + private WeakReference mReference; +// private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener; + + public SoftKeyBoardListener(Activity activity) { + /*获取activity的根视图*/ + rootView = activity.getWindow().getDecorView(); + /*监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变*/ + rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener = mReference.get(); + if (onSoftKeyBoardChangeListener == null) return; + /*获取当前根视图在屏幕上显示的大小*/ + Rect r = new Rect(); + rootView.getWindowVisibleDisplayFrame(r); + int visibleHeight = r.height(); + if (rootViewVisibleHeight == 0) { + rootViewVisibleHeight = visibleHeight; + return; + } + /*根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变*/ + if (rootViewVisibleHeight == visibleHeight) { + return; + } + /*根视图显示高度变小超过200,可以看作软键盘显示了*/ + if (rootViewVisibleHeight - visibleHeight > 200) { + onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); + rootViewVisibleHeight = visibleHeight; + return; + } + /*根视图显示高度变大超过200,可以看作软键盘隐藏了*/ + if (visibleHeight - rootViewVisibleHeight > 200) { + onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); + rootViewVisibleHeight = visibleHeight; + } + } + }); + } + + private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { + mReference = new WeakReference<>(onSoftKeyBoardChangeListener); +// this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener; + } + + public interface OnSoftKeyBoardChangeListener { + void keyBoardShow(int height); + + void keyBoardHide(int height); + } + + public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { + SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity); + softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/UserCardButtonManager.java b/app/src/main/java/com/yizhuan/erban/avroom/UserCardButtonManager.java new file mode 100644 index 000000000..5972731a0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/UserCardButtonManager.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.avroom; + +import android.content.Context; +import android.util.SparseArray; + +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.ui.widget.GiftDialog; + +/** + * 用户卡片的管理 + * Created by lvzebiao on 2018/11/12. + */ + +public class UserCardButtonManager { + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java new file mode 100644 index 000000000..6217298d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/AVRoomActivity.java @@ -0,0 +1,1371 @@ +package com.yizhuan.erban.avroom.activity; + + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewPager; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewStub; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.model.BroadcastMessage; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.AbsRoomFragment; +import com.yizhuan.erban.avroom.fragment.HomePartyFragment; +import com.yizhuan.erban.avroom.fragment.InputPwdDialogFragment; +import com.yizhuan.erban.avroom.game.PlayGameActivity; +import com.yizhuan.erban.avroom.presenter.AvRoomPresenter; +import com.yizhuan.erban.avroom.presenter.HomePartyPresenter; +import com.yizhuan.erban.avroom.view.IAvRoomView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.CustomImageSpan; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.monsterhunting.MonsterHuntingActivity; +import com.yizhuan.erban.treasure_box.service.OpenHonourBoxService; +import com.yizhuan.erban.ui.patriarch.help.LimitEnterRoomHelper; +import com.yizhuan.erban.treasure_box.service.OpenBoxService; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.LoadingDialog; +import com.yizhuan.erban.ui.widget.NobleOpenNoticeView; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelOneDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelThreeDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelTwoDialog; +import com.yizhuan.erban.ui.widget.dialog.MonsterDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.LogoutEvent; +import com.yizhuan.xchat_android_core.bean.BaseProtocol; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringStartCountingEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringStopCountingEvent; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingResult; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterProtocol; +import com.yizhuan.xchat_android_core.monsterhunting.manager.MonsterDataManager; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.patriarch.event.CloseMinRoomEvent; +import com.yizhuan.xchat_android_core.patriarch.event.ImPushMsgPmLimitTimeEvent; +import com.yizhuan.xchat_android_core.patriarch.event.PmDismissAllLimitDialogEvent; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.SimplePartyRoomInfo; +import com.yizhuan.xchat_android_core.room.dragonball.DragonBallModel; +import com.yizhuan.xchat_android_core.room.event.RoomClearScreenEvent; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.pk.event.PKStateEvent; + +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; + +import com.yizhuan.xchat_android_core.super_admin.util.SAdminOptUtil; + +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.StringUtils; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.UIUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.lang.ref.WeakReference; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +import static android.view.View.VISIBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_ALL_SERVICE_GIFT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_GIFT; + +/** + * 房间入口 + * + * @author Administrator + */ +@CreatePresenter(AvRoomPresenter.class) +public class AVRoomActivity extends BaseMvpActivity + implements View.OnClickListener, IAvRoomView { + + private static final String TAG = "AVRoomActivity"; + private static final String GAME_INFO = "gameInfo"; + private static final String GAME_URL = "gameUrl"; + private static final String AI_UID = "aiUid"; + private static final String SHOW_PARTY_ROOM_FIRST_ENTER_TIP = "show_party_room_first_enter_tip"; + + private SVGAImageView svgaRoomBg; + private RelativeLayout finishLayout; + private ViewStub mVsRoomOffline; + private ViewStub mVsPartyRoomTip; + private ImageView avatarBg; + private TextView nick; + private CircleImageView avatar; + private SVGAParser mSVGAParser; + + private ViewStub mVsNobleOpen; + private NobleOpenNoticeView mNobleOpenNoticeView; + + private long roomUid; + private AbsRoomFragment mCurrentFragment; + + private InputPwdDialogFragment mPwdDialogFragment; + + private RoomInfo mRoomInfo; + private ImageView ivHeadWear; + private View shade; + private MonsterDialog monsterDialog; + + private ViewPager viewpager; + private List fragmentList; + private FragmentViewPagerAdapter mAdapter; + private int pos = 0; + boolean isLast = true; + private LoadingDialog mLoadingDialog; + + /** + * 管理限制进房 + */ + LimitEnterRoomHelper limitEnterRoomHelper; + + public static void start(Context context, long roomUid) { + Intent intent = new Intent(context, AVRoomActivity.class); + intent.putExtra(Constants.ROOM_UID, roomUid); + AvRoomDataManager.get().setIsParty(false); + //bug-fixed java.lang.RuntimeException:Unable to start receiver com.yizhuan.erban.reciever.NotificationClickReceiver: android.util.AndroidRuntimeException + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + public static void start(Context context, long roomUid, GameInfo gameInfo, String gameUrl, long aiUid) { + Intent intent = new Intent(context, AVRoomActivity.class); + intent.putExtra(Constants.ROOM_UID, roomUid); + intent.putExtra(GAME_INFO, gameInfo); + intent.putExtra(GAME_URL, gameUrl); + intent.putExtra(AI_UID, aiUid); + AvRoomDataManager.get().setIsParty(false); + //bug-fixed java.lang.RuntimeException:Unable to start receiver com.yizhuan.erban.reciever.NotificationClickReceiver: android.util.AndroidRuntimeException + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + public static void start(Context context, long roomUid, int roomType) { + Intent intent = new Intent(context, AVRoomActivity.class); + intent.putExtra(Constants.ROOM_UID, roomUid); + intent.putExtra(Constants.ROOM_TYPE, roomType); + AvRoomDataManager.get().setIsParty(false); + //bug-fixed java.lang.RuntimeException:Unable to start receiver com.yizhuan.erban.reciever.NotificationClickReceiver: android.util.AndroidRuntimeException + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + public static void start(Context context, boolean isParty) { + Intent intent = new Intent(context, AVRoomActivity.class); + intent.putExtra(Constants.IS_PARTY, isParty); + AvRoomDataManager.get().setIsParty(true); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + /** + * 师徒任务中特殊的分享跳转 + */ + public static void startForMentoring(Context context, long roomUid) { + Intent intent = new Intent(context, AVRoomActivity.class); + intent.putExtra(Constants.ROOM_UID, roomUid); + // 缓存起来,后面在 HomePartyRoomFragment 里拿出来判断使用 + AvRoomDataManager.get().setFromMentoring(true); + AvRoomDataManager.get().setMasterUid(roomUid); + AvRoomDataManager.get().setIsParty(false); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + // 如果是同一个房间,则只更新房间的信息 + long newRoomUid = intent.getLongExtra(Constants.ROOM_UID, 0); + boolean isParty = getIntent().getBooleanExtra(Constants.IS_PARTY, false); + //从嗨聊房进入 + if (isParty) { + if (AvRoomDataManager.get().getRoomUidList() != null) { + List list = AvRoomDataManager.get().getRoomUidList(); + if (list.size() > 0) { + AvRoomDataManager.get().setIsParty(true); + roomUid = list.get(0).getUid(); + if (mCurrentFragment != null) { + mCurrentFragment = null; + } + if (roomUid != AuthModel.get().getCurrentUid()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ENTERROOM, "进入别人房间"); + } + updateRoomInfo(); + return; + } else { + AvRoomDataManager.get().setIsParty(false); + } + } else { + AvRoomDataManager.get().setIsParty(false); + } + } + + if (newRoomUid != 0 && newRoomUid == roomUid) { + updateRoomInfo(); + return; + } + // 师徒任务三判定 + if (AvRoomDataManager.get().isFromMentoring() && Objects.equals(AvRoomDataManager.get().getMasterUid(), + AvRoomDataManager.get().mCurrentRoomInfo.getUid())) { + // 只有从任务三分享房间链接进来的时候才开始倒计时 + EventBus.getDefault().post(new MentoringStartCountingEvent()); + } else { + EventBus.getDefault().post(new MentoringStopCountingEvent()); + } + roomUid = newRoomUid; + if (roomUid != AuthModel.get().getCurrentUid()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ENTERROOM, "进入别人房间"); + } + if (mCurrentFragment != null) { + mCurrentFragment = null; + } + // 相同类型的房间,但是是不同人的房间 + if (AvRoomDataManager.get().isFirstEnterRoomOrChangeOtherRoom(roomUid)) { + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(View.INVISIBLE); + getDialogManager().showProgressDialog(this, getString(R.string.waiting_text), true); + updateRoomInfo(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat_room); + + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + roomUid = getIntent().getLongExtra(Constants.ROOM_UID, 0); + boolean isParty = getIntent().getBooleanExtra(Constants.IS_PARTY, false); + //如果是嗨聊房入口roomUid就不从intent中取值 + if (isParty) { + List roomUidList = AvRoomDataManager.get().getRoomUidList(); + if (roomUidList != null && roomUidList.size() > 0) { + roomUid = roomUidList.get(0).getUid(); + } + } + fragmentList = new ArrayList<>(); + + svgaRoomBg = findViewById(R.id.svga_image_view_bg); + mVsRoomOffline = findViewById(R.id.vs_room_offline); + mVsNobleOpen = findViewById(R.id.vs_noble_open_notice); + mVsPartyRoomTip = findViewById(R.id.vs_hiparty_room_tips); + viewpager = findViewById(R.id.viewpager); + shade = findViewById(R.id.view); + mSVGAParser = new SVGAParser(this); + + RtcEngineManager.get().setOpenAVRoomActivity(true); + + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .subscribe(this::onRoomEventReceive); + + if (roomUid != AuthModel.get().getCurrentUid()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ENTERROOM, "进入别人房间"); + } + + EventBus.getDefault().register(this); + + mAdapter = new FragmentViewPagerAdapter(getSupportFragmentManager(), fragmentList); + viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + dismissLoadingDialog(); + pos = position; + List roomUidList = AvRoomDataManager.get().getRoomUidList(); + if (fragmentList != null && fragmentList.size() > 0 + && roomUidList != null && roomUidList.size() > 0) { + showLoadingDialog(); + mCurrentFragment = (AbsRoomFragment) fragmentList.get(position); + + //嗨聊房切换时清除公屏信息 + EventBus.getDefault().post(new RoomClearScreenEvent()); + + roomUid = roomUidList.get(position).getUid(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.room_hiparty_slide, "房间内-滑动切换嗨聊房"); + updateRoomInfo(); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == 2) { + isLast = false; + } else if (state == 0 && isLast) { + //此处为你需要的情况,再加入当前页码判断可知道是第一页还是最后一页 + if (fragmentList.size() != 1 && pos == (fragmentList.size() - 1)) { + showLoadingDialog(); + viewpager.setCurrentItem(0); + } else if (fragmentList.size() != 1 && pos == 0) { + showLoadingDialog(); + viewpager.setCurrentItem(fragmentList.size() - 1); + } + } else { + isLast = true; + } + } + }); + viewpager.setAdapter(mAdapter); + + //第一次进来 + if (AvRoomDataManager.get().isFirstEnterRoomOrChangeOtherRoom(roomUid)) { + getDialogManager().showProgressDialog(this, getString(R.string.waiting_text), false); + updateRoomInfo(); + return; + } + + addRoomFragment(true); + + } + + + @Override + protected void onResume() { + super.onResume(); + AvRoomDataManager.get().roomNoDestory = true; + + registerGiftBroadcastMessage(true); + if (giftList != null) { + giftList.clear(); + } + isResume = true; + + } + + private void onRoomEventReceive(RoomEvent roomEvent) { + if (roomEvent == null || roomEvent.getEvent() == RoomEvent.NONE) return; + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.ENTER_ROOM: + onEnterRoom(); + break; + case RoomEvent.KICK_OUT_ROOM: + if (AvRoomDataManager.get().haveStartDragon && AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + giveUpDragonBar().subscribe(s -> onKickMember(roomEvent.getReason())); + } else { + onKickMember(roomEvent.getReason()); + } + break; + case RoomEvent.ROOM_MANAGER_ADD: + case RoomEvent.ROOM_MANAGER_REMOVE: + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + if (roomEvent.getEvent() == RoomEvent.ROOM_MANAGER_ADD) { + toast(R.string.set_room_manager); + } else if (roomEvent.getEvent() == RoomEvent.ROOM_MANAGER_REMOVE) { + toast(R.string.remove_room_manager); + } + } + break; + case RoomEvent.RTC_ENGINE_NETWORK_BAD: + toast("当前网络不稳定,请检查网络"); + break; + case RoomEvent.RTC_ENGINE_NETWORK_CLOSE: + toast("当前网络异常,与服务器断开连接,请检查网络"); + break; + case RoomEvent.ON_OPEN_NOBLE_NOTICE: + if (roomEvent.mRoomNobleMsgAttachment != null) { + NobleInfo nobleInfo = roomEvent.mRoomNobleMsgAttachment.nobleInfo; + if (nobleInfo == null) return; + if (mNobleOpenNoticeView == null) + mNobleOpenNoticeView = (NobleOpenNoticeView) mVsNobleOpen.inflate(); + mNobleOpenNoticeView.setVisibility(VISIBLE); + mNobleOpenNoticeView.setData(nobleInfo, roomEvent.mRoomNobleMsgAttachment.nick, + roomEvent.mRoomNobleMsgAttachment.type); + } + break; + case RoomEvent.ROOM_INFO_UPDATE: + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) + setBackBg(this, roomInfo, svgaRoomBg, bgPicture, shade); + break; + case RoomEvent.GIFT_OUT_OF_DATE: + onGiftOutOfDate(); + break; + case RoomEvent.RECHARGE: + onNeedRecharge(); + break; + case RoomEvent.RADISH_NOT_ENOUGH: + //已经在base弹出过,修复同时弹出2个弹窗的bug + //2019/8/20 @lzb + break; + case RoomEvent.MONSTER_STATUS_CHANGED: + MonsterProtocol.DataBean dataBean = roomEvent.getMonsterStatusAttachment().getDataBean(); + Log.e(TAG, "onRoomEventReceive: monster status changed: " + dataBean); + RoomInfo myRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + // 当前为房间页面并且当前房间为怪兽出现房间时才出现通知 + if (UIUtils.isTopActivity(AVRoomActivity.this) && myRoomInfo != null && + myRoomInfo.getUid() == dataBean.getAppearRoomUid()) { + switch (dataBean.getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_WILL_APPEAR: + if (dataBean.getBeforeAppearSeconds() <= 3 * 60 && + dataBean.getBeforeAppearSeconds() >= 45) { + if (monsterDialog != null && monsterDialog.isShowing()) { + monsterDialog.dismiss(); + } + monsterDialog = new MonsterDialog(AVRoomActivity.this, dataBean); + monsterDialog.show(); + } else if (dataBean.getBeforeAppearSeconds() < 15) { + if (monsterDialog != null && monsterDialog.isShowing()) { + monsterDialog.dismiss(); + } + monsterDialog = new MonsterDialog(AVRoomActivity.this, dataBean); + monsterDialog.show(); + } + break; + + case MonsterInfo.MONSTER_STATUS_DID_APPEAR: + if (dataBean.getAppearRoomUid() == AvRoomDataManager.get().mCurrentRoomInfo.getUid() && + UIUtils.isTopActivity(AVRoomActivity.this)) { + getMvpPresenter().getMonster(); + } + break; + + case MonsterInfo.MONSTER_STATUS_DID_LEAVE: + if (monsterDialog != null && monsterDialog.isShowing()) { + monsterDialog.dismiss(); + } + monsterDialog = new MonsterDialog(AVRoomActivity.this, dataBean); + monsterDialog.show(); + break; + } + } + break; + case RoomEvent.MONSTER_HUNTING_RESULT: + MonsterHuntingResult monsterHuntingResult = roomEvent.getMonsterHuntingResultAttachment().getResult(); + Log.e(TAG, "onRoomEventReceive: monster result has come: " + monsterHuntingResult); + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + // 当前为房间页面并且当前房间为怪兽出现房间时才出现通知 + if (UIUtils.isTopActivity(AVRoomActivity.this) && currentRoomInfo != null && + currentRoomInfo.getUid() == monsterHuntingResult.getMonster().getAppearRoomUid()) { + MonsterProtocol.DataBean monsterInfo = monsterHuntingResult.getMonster(); + if (monsterDialog != null && monsterDialog.isShowing()) { + monsterDialog.dismiss(); + } + monsterDialog = new MonsterDialog(AVRoomActivity.this, monsterInfo); + monsterDialog.show(); + } + break; + case RoomEvent.MY_SELF_KICK_OUT_ROOM_BY_S_ADMIN: + toBack(true); + break; + default: + } + } + + + private void onKickMember(ChatRoomKickOutEvent reason) { + if (reason == null) return; + ChatRoomKickOutEvent.ChatRoomKickOutReason reasonReason = reason.getReason(); + getDialogManager().dismissDialog(); + if (reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.BE_BLACKLISTED) { + if (SAdminOptUtil.isOptBySAdmin(reason)) { + toast(R.string.add_to_room_black_list_by_s_admin); + } else { + toast(getString(R.string.add_black_list)); + } + finish(); + } else if (reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + showLiveFinishView(); + } else if (reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.KICK_OUT_BY_MANAGER) { + if (SAdminOptUtil.isOptBySAdmin(reason)) { + toast(R.string.kick_out_room_by_s_admin); + } else { + toast(getString(R.string.kick_member_by_manager)); + } + finish(); + } else { + finish(); + } + } + + private void onEnterRoom() { + mRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + Logger.i("进入房间成功:" + mRoomInfo.getRoomId()); + dismissDialog(); + getMvpPresenter().getMonster(); + + startGame(); + } + + private void startGame() { + String url = getIntent().getStringExtra(GAME_URL); + LogUtil.e("游戏地址" + url); + if (!TextUtils.isEmpty(url)) { + long aiUid = getIntent().getLongExtra(AI_UID, 0); + GameInfo gameInfo = (GameInfo) getIntent().getSerializableExtra(GAME_INFO); + PlayGameActivity.start(this, url, aiUid); + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.PLAYING, + gameInfo.getGameId(), + gameInfo.getGameName(), + false) + .subscribe(); + if (aiUid == 0) { + GameModel.get().sendGameStartMsg(gameInfo); + } else { + if (AvRoomDataManager.get().findFreePositionNoOwner() == 0) { + getMvpPresenter().upAiMicroPhone(0, aiUid + ""); + } else { + getMvpPresenter().upAiMicroPhone(AvRoomDataManager.get().findFreePosition(), aiUid + ""); + } + } + } + } + + /** + * @param isRoomMin 如果是最小化,则传ture + */ + private void addRoomFragment(boolean isRoomMin) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + setBackBg(this, roomInfo, svgaRoomBg, bgPicture, shade); + int roomType = roomInfo.getType(); + if ((roomType == RoomInfo.ROOMTYPE_HOME_PARTY || roomType == RoomInfo.ROOMTYPE_CP) && + !(mCurrentFragment instanceof HomePartyFragment)) { + fragmentList.clear(); + List roomUidList = AvRoomDataManager.get().getRoomUidList(); + if (AvRoomDataManager.get().isParty()) { + for (int i = 0; i < roomUidList.size(); i++) { + HomePartyFragment homePartyFragment = HomePartyFragment.newInstance(roomUidList.get(i).getUid(), isRoomMin); + if (i == 0) { + mCurrentFragment = homePartyFragment; + } + fragmentList.add(homePartyFragment); + } + showPartyRoomTip(); + } else { + mCurrentFragment = HomePartyFragment.newInstance(roomUid, isRoomMin); + SimplePartyRoomInfo simplePartyRoomInfo = new SimplePartyRoomInfo(); + simplePartyRoomInfo.setUid(roomUid); + roomUidList.add(simplePartyRoomInfo); + fragmentList.add(mCurrentFragment); + } + } + if (fragmentList != null && fragmentList.size() > 0) { + mAdapter.setmFragmentList(fragmentList); + mAdapter.notifyDataSetChanged(); + } + + getMvpPresenter().getActionDialog(2); + } + + + if (isRoomMin) { + getMvpPresenter().judgeIsLimitEnter(); + } + + } + + private String[] bgPicture = new String[]{""}; + + public static void setBackBg(Context context, RoomInfo roomInfo, SVGAImageView svgaRoomBg, String[] bgPicture, View shade) { + if (roomInfo != null) { + if (!StringUtils.isBlank(roomInfo.getBackPic())) { + int resourceType = NobleUtil.getResourceType(roomInfo.getBackPic()); + if (resourceType == NobleResourceType.URLS) { + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(View.VISIBLE); + if (!roomInfo.getBackPic().equals(bgPicture[0])) { + bgPicture[0] = roomInfo.getBackPic(); + ImageLoadUtils.loadRoomBgBackground(context, bgPicture[0], svgaRoomBg); + } + } else if (resourceType == NobleResourceType.SVGAS) { + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(View.VISIBLE); + if (!roomInfo.getBackPic().equals(bgPicture[0])) { + bgPicture[0] = roomInfo.getBackPic(); + try { + SVGAParser mSVGAParser = new SVGAParser(context); + mSVGAParser.parse(new URL(bgPicture[0]), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + svgaRoomBg.setVisibility(View.VISIBLE); + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + svgaRoomBg.setImageDrawable(drawable); + svgaRoomBg.startAnimation(); + } + + @Override + public void onError() { + svgaRoomBg.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + } + } else { + bgPicture[0] = ""; + if (roomInfo.getType() == RoomInfo.ROOMTYPE_CP) { + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(VISIBLE); + shade.setVisibility(View.GONE); + if (roomInfo.isOpenGame) { + svgaRoomBg.setImageResource(R.drawable.room_cp_game_bg); + } else { + svgaRoomBg.setImageResource(R.drawable.bg_room_cp); + } + } else { + //不再使用头像作为房间默认背景 + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(VISIBLE); + if (isPKModel) { + svgaRoomBg.setImageResource(R.drawable.bg_room_pk); + } else + svgaRoomBg.setImageResource(R.drawable.bg_room_normal_default_pic); + } + + } + } else { + svgaRoomBg.clearAnimation(); + svgaRoomBg.setVisibility(View.GONE); + } + } + + private void showLiveFinishView() { + if (mCurrentFragment instanceof HomePartyFragment) { + ((HomePartyFragment) mCurrentFragment).dismissGiftDialog(); + } + if (mRoomInfo != null) { + if (finishLayout == null) { + finishLayout = (RelativeLayout) mVsRoomOffline.inflate(); + ivHeadWear = finishLayout.findViewById(R.id.iv_head_wear); + avatar = finishLayout.findViewById(R.id.avatar); + avatarBg = finishLayout.findViewById(R.id.avatar_bg); + nick = finishLayout.findViewById(R.id.nick); + } + //防止点击到底下的操作按钮 + finishLayout.setOnClickListener(null); + finishLayout.setVisibility(VISIBLE); + finishLayout.findViewById(R.id.home_page_btn).setOnClickListener(this); + finishLayout.findViewById(R.id.back_btn).setOnClickListener(this); + + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + setBackBg(this, roomInfo, svgaRoomBg, bgPicture, shade); + } + + UserModel.get().getUserInfo(mRoomInfo.getUid()).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(UserInfo userInfo) { + setUserInfo(userInfo); + } + + @Override + public void onError(Throwable e) { + + } + }); + + } else { + + finish(); + } + AvRoomDataManager.get().release(); + } + + private void showPartyRoomTip() { + boolean isFirst = (boolean) SharedPreferenceUtils.get(SHOW_PARTY_ROOM_FIRST_ENTER_TIP, true); + if (isFirst) { + LinearLayout layout = (LinearLayout) mVsPartyRoomTip.inflate(); + layout.setOnClickListener(view -> { + mVsPartyRoomTip.setVisibility(View.GONE); + SharedPreferenceUtils.put(SHOW_PARTY_ROOM_FIRST_ENTER_TIP, false); + }); + mVsPartyRoomTip.setVisibility(View.VISIBLE); + } else { + mVsPartyRoomTip.setVisibility(View.GONE); + } + } + + private void setUserInfo(UserInfo userInfo) { + if (avatarBg == null || avatar == null || nick == null) return; + if (userInfo != null) { + ImageLoadUtils.loadImageWithBlurTransformation(this, userInfo.getAvatar(), avatarBg); + ImageLoadUtils.loadBigAvatar(this, userInfo.getAvatar(), avatar, false); + Drawable badgeDrawable = null; + if (userInfo.getNobleInfo() != null) { + // 勋章 + String badge = userInfo.getNobleInfo().getBadge(); + badgeDrawable = NobleUtil.getDrawable(this, badge); + // 头饰 + String headWear = userInfo.getNobleInfo().getHeadWear(); + NobleUtil.loadResource(headWear, ivHeadWear); + } + String nick = (badgeDrawable == null ? "" : " ") + userInfo.getNick(); + SpannableStringBuilder builder = new SpannableStringBuilder(nick); + if (badgeDrawable != null) { + badgeDrawable.setBounds(0, 0, Utils.dip2px(this, 18), Utils.dip2px(this, 18)); + CustomImageSpan imageSpan = new CustomImageSpan(badgeDrawable); + builder.setSpan(imageSpan, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + Drawable drawable = ContextCompat.getDrawable(this, + userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + this.nick.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); + this.nick.setText(builder); + } else { + avatar.setImageResource(R.drawable.default_user_head); + } + } + + private void updateRoomInfo() { + getMvpPresenter().requestRoomInfoFromService(String.valueOf(roomUid)); + } + + private void showRoomPwdDialog(final RoomInfo roomInfo) { + if (!isValid()) return; + // fix bugs + if (afterOnSavedInstanceState) { + finish(); + return; + } + mPwdDialogFragment = InputPwdDialogFragment.newInstance(getString(R.string.input_pwd), + getString(R.string.ok), + getString(R.string.cancel), + roomInfo.getRoomPwd()); + mPwdDialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.TranslucentNoTitle); + if (getSupportFragmentManager() == null) return; + mPwdDialogFragment.show(getSupportFragmentManager(), "pwdDialog"); + + mPwdDialogFragment.setOnDialogBtnClickListener(new InputPwdDialogFragment.OnDialogBtnClickListener() { + @Override + public void onBtnConfirm() { + getMvpPresenter().enterRoom(roomInfo); + } + + @Override + public void onBtnCancel() { + mPwdDialogFragment.dismiss(); + finish(); + } + }); + } + + + @Override + public void onGetActionDialog(List dialogInfo) { + if (mCurrentFragment != null && mCurrentFragment.isVisible()) { + mCurrentFragment.onShowActivity(dialogInfo); + } + } + + @Override + public void onGetActionDialogError(String error) { + } + + @Override + public void exitRoom(RoomInfo currentRoomInfo) { + if (OpenBoxService.isAutoOpenBox) { + OpenBoxService.stop(this); + } + if (OpenHonourBoxService.isAutoOpenBox) { + OpenHonourBoxService.stop(this); + } + if (currentRoomInfo != null && currentRoomInfo.getUid() == roomUid) { + finish(); + } + } + + @Override + public void onRoomOnlineNumberSuccess(int onlineNumber) { + if (mCurrentFragment != null) + mCurrentFragment.onRoomOnlineNumberSuccess(onlineNumber); + } + + @Override + public void getMonsterInfoSuccess(MonsterInfo monsterInfo) { + // 把请求回来的数据缓存到内存里 + MonsterDataManager.get().setMonsterInfo(monsterInfo.getAppearRoomUid(), monsterInfo); + switch (monsterInfo.getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_DID_APPEAR: + if (monsterInfo.getBeforeDisappearSeconds() >= 0) { + if (monsterDialog != null && monsterDialog.isShowing()) { + monsterDialog.dismiss(); + } + MonsterHuntingActivity.start(this); + } + break; + } + } + + @Override + public void getMonsterInfoFail(String error) { + toast(error); + } + + private void onGiftOutOfDate() { + toast("该礼物已过期"); + } + + public void onNeedRecharge() { + + getDialogManager().showOkCancelDialog("余额不足,是否充值", true, + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_NOT_ENOUGH_TO_RECHARGE, + "余额不足_去充值:送礼物"); + ChargeActivity.start(AVRoomActivity.this); + } + }); + } + + public void toBack() { + toBack(false); + } + + /** + * @param justClosePage ture的话 表示 退出聊天室的方法不调用,关闭当前界面就行 + * 把退出聊天室交给Main执行 + */ + public void toBack(boolean justClosePage) { + //陪伴房的弹框提示去掉,直接关闭即可 + cancelGame(); + if (!justClosePage) { + getMvpPresenter().exitRoom(); + } + finish(); + } + + @Override + protected int setBgColor() { + return R.color.black; + } + + @Override + protected boolean needSteepStateBar() { + return false; + } + + @Override + protected void onDestroy() { + + // 确保关闭 dialog,避免出现 leak window 异常 + getDialogManager().dismissDialog(); + if (AvRoomDataManager.get().haveStartDragon) { + giveUpDragonBar(); + } + + // 避免 ISE + if (mPwdDialogFragment != null && mPwdDialogFragment.isAdded() + && !isFinishing()) { + mPwdDialogFragment.dismiss(); + mPwdDialogFragment = null; + } + if (monsterDialog != null) { + monsterDialog.cancelCountDownTimer(); + monsterDialog.dismiss(); + monsterDialog = null; + } + if (svgaRoomBg.isAnimating()) { + svgaRoomBg.clearAnimation(); + } + EventBus.getDefault().unregister(this); + RtcEngineManager.get().setOpenAVRoomActivity(false); + super.onDestroy(); + + if (giftDialog != null && giftDialog.isShowing()) { + giftDialog.setOnDismissListener(null); + giftDialog.dismiss(); + giftDialog = null; + } + + if (limitEnterRoomHelper != null) { + limitEnterRoomHelper.release(); + } + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.home_page_btn: + if (mRoomInfo != null) { + UserInfoActivity.Companion.start(this, mRoomInfo.getUid()); + finish(); + } + break; + case R.id.back_btn: + finish(); + break; + default: + } + } + + @Override + public void onBackPressed() { + if (DemoCache.readFirstExitRoom() && ImGameMode.get().exitCancelGame(false)) { + DemoCache.saveFirstExitRoom(); + getDialogManager().showOkCancelDialog("最小化房间会取消当前游戏发起", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + minRoomCode(); + } + }); + } else if (mNobleOpenNoticeView != null && mNobleOpenNoticeView.getVisibility() == VISIBLE) { + mNobleOpenNoticeView.setVisibility(View.GONE); + } else if (AvRoomDataManager.get().haveStartDragon) { + getDialogManager().showOkCancelDialog("你正在交友匹配中,此操作代表你放弃本局匹配展示,确定进行此操作?", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @SuppressLint("CheckResult") + @Override + public void onOk() { + + //noinspection ResultOfMethodCallIgnored + giveUpDragonBar().subscribe(s -> { + new HomePartyPresenter().cancelDragon(); + minRoomCode(); + }); + + } + }); + } else { + minRoomCode(); + } + } + + /** + * 最小化房间的代码,放在一处 + */ + private void minRoomCode() { + cancelGame(); + ImGameMode.get().exitCancelGame(true); + AvRoomDataManager.get().roomNoDestory = false; + super.onBackPressed(); + } + + private void cancelGame() { + + if (GameModel.get().prepareGame()) { + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.SELECTING, + GameModel.get().getGameId(), + GameModel.get().getGameName(), false) + .subscribe(s -> GameModel.get().sendCancelPrepare()); + GameModel.get().removePool(GameModel.get().getGameId()).subscribe(); + } + } + + @Override + public void requestRoomInfoSuccessView(RoomInfo roomInfo) { + mRoomInfo = roomInfo; + + // 超管绕过密码直接进房 + if (SuperAdminUtil.isSuperAdmin()) { + getMvpPresenter().enterRoom(roomInfo); + return; + } + + if (!AvRoomDataManager.get().isFirstEnterRoomOrChangeOtherRoom(roomInfo.getUid()) + || TextUtils.isEmpty(roomInfo.getRoomPwd()) + || roomInfo.getUid() == AuthModel.get().getCurrentUid()) { + if (AvRoomDataManager.get().isCpRoom() && AvRoomDataManager.get().isRoomOwner()) { + getDialogManager().showOkCancelDialog("切换房间后,房间将关闭,确认切换吗?", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + // cp房切换嗨聊房,弹框点击拒绝:防止从首页小图标重新进入cp房循环展示切换房间弹框; + AvRoomDataManager.get().setIsParty(false); + + finish(); + } + + @Override + public void onOk() { + // cp房切换嗨聊房,弹框点击确定:清屏并重置公屏数据; + // 普通房切嗨聊房直接清屏(清屏调用在homePartyFragment 随机切换嗨聊房 监听), + // cp房切换嗨聊房不会先清屏,防止用户点击取消按钮,不进行切换房间操作,但是公屏被清的情况; + EventBus.getDefault().post(new RoomClearScreenEvent()); + + getMvpPresenter().enterRoom(roomInfo); + } + }); + } else { + getMvpPresenter().enterRoom(roomInfo); + } + } else { + if (isFinishing()) { + return; + } + showRoomPwdDialog(roomInfo); + } + } + + @Override + public void requestRoomInfoFailView(Throwable throwable) { + dismissLoadingDialog(); + getDialogManager().dismissDialog(); + if (throwable instanceof PmRoomLimitException) { + getLimitEnterRoomHelper().handleThisContext(context, throwable.getMessage(), false, () -> { + finish(); + //如果本身房间存在,这个时候直接finish,没有退出房间,应当退出 + EventBus.getDefault().post(new CloseMinRoomEvent()); + }); + return; + } + toast(throwable.getMessage()); + finish(); + } + + @Override + public void enterRoomSuccess() { + addRoomFragment(false); + //获取管理员 + getMvpPresenter().getNormalChatMember(); + dismissLoadingDialog(); + } + + @Override + public void enterRoomFail(int code, String error) { + dismissDialog(); + dismissLoadingDialog(); + AvRoomDataManager.get().release(); + toast(error); + finish(); + } + + @Override + public void showFinishRoomView() { + dismissLoadingDialog(); + dismissDialog(); + showLiveFinishView(); + } + + @Override + public void showBlackEnterRoomView() { + dismissLoadingDialog(); + dismissDialog(); + AvRoomDataManager.get().release(); + toast(getString(R.string.add_black_list)); + finish(); + } + + @Override + public void dismissLoadingDialog() { + if (mLoadingDialog != null && mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + } + + public void showLoadingDialog() { + if (mLoadingDialog == null) { + mLoadingDialog = new LoadingDialog(AVRoomActivity.this); + } + mLoadingDialog.show(); + } + + private void dismissDialog() { + getDialogManager().dismissDialog(); + if (mPwdDialogFragment != null) { + mPwdDialogFragment.dismiss(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLogoutEvent(LogoutEvent event) { + finish(); + } + + public static boolean isPKModel = false; + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKStateEvent(PKStateEvent event) { + isPKModel = event != null && event.isCreate(); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) + setBackBg(this, roomInfo, svgaRoomBg, bgPicture, shade); + } + + public Single giveUpDragonBar() { + return DragonBallModel.get() + .clearDragonBar() + .compose(bindToLifecycle()) + .doOnError(throwable -> toast(throwable.getMessage())) + .doOnSuccess(s -> { + AvRoomDataManager.get().haveStartDragon = false; + }); + } + + + /*********************************显示全服礼物***************************************/ + + private GiftBroadcastObserver giftObserver; + + protected void registerGiftBroadcastMessage(boolean register) { + if (giftObserver == null) { + giftObserver = new GiftBroadcastObserver(this); + } + NIMSDK.getMsgServiceObserve().observeBroadcastMessage(giftObserver, register); + } + + private static class GiftBroadcastObserver implements Observer { + private WeakReference mReference; + + GiftBroadcastObserver(AVRoomActivity activity) { + mReference = new WeakReference<>(activity); + } + + @Override + public void onEvent(BroadcastMessage broadcastMessage) { + if (broadcastMessage != null) { + String contentStr = broadcastMessage.getContent(); + Logger.i("全服礼物全局广播:" + contentStr); + if (TextUtils.isEmpty(contentStr)) return; + AVRoomActivity activity = mReference.get(); + if (activity == null) return; + if (activity.isValid()) { + JSONObject jsonObject; + try { + jsonObject = JSON.parseObject(contentStr); + } catch (Exception e) { + jsonObject = null; + } + if (jsonObject == null) return; + if (jsonObject.containsKey("body")) { + String body = jsonObject.getString("body"); + if (TextUtils.isEmpty(body)) return; + activity.onReceivedGiftBroadcastMessage(body); + } + } + } + } + } + + private Dialog giftDialog; + private LinkedList giftList; + private boolean isResume = true; + + /** + * 接收到全局广播信息 + * + * @param body 信息实体 + */ + protected void onReceivedGiftBroadcastMessage(String body) { + BaseProtocol baseProtocol; + try { + baseProtocol = JSON.parseObject(body, BaseProtocol.class); + } catch (Exception e) { + baseProtocol = null; + } + if (baseProtocol == null) return; + + switch (baseProtocol.getFirst()) { + case CUSTOM_MSG_HEADER_TYPE_GIFT: +// if (!isResume) return; + if (giftList == null) { + giftList = new LinkedList<>(); + } + int second2 = baseProtocol.getSecond(); + AllServiceGiftProtocol.DataBean data = JSON.parseObject(String.valueOf(baseProtocol.getData()), AllServiceGiftProtocol.DataBean.class); + if (data == null || (data.getGiftUrl()) == null) + return; + giftList.add(data); + if (second2 == CUSTOM_MSG_ALL_SERVICE_GIFT) { + if (giftDialog != null && giftDialog.isShowing()) { + // 如果当前以及有礼物弹窗在展示,则需要等到他 dismiss 后再显示下一个 + AllServiceGiftProtocol.DataBean dataBean = giftList.peekFirst(); + if (dataBean != null) { + return; + } else { + if (isValid()) { + giftDialog.dismiss(); + } + } + } else { + showGiftDialog(); + } + } + break; + default: + } + } + + private void showGiftDialog() { + if (giftList.size() == 0) return; + giftDialog = generateAllServiceGiftDialog(this, giftList.peekFirst()); + giftDialog.setOnDismissListener(dialog -> { + giftList.pollFirst(); + AllServiceGiftProtocol.DataBean dataBean = giftList.peekFirst(); + if (dataBean != null) { + if (isValid()) { + showGiftDialog(); + } else { + giftList.clear(); + } + } + }); + giftDialog.show(); + } + + private AllServiceGiftDialog generateAllServiceGiftDialog(Context context, AllServiceGiftProtocol.DataBean dataBean) { + switch (JavaUtil.str2int(dataBean.getLevelNum())) { + default: + case AllServiceGiftDialog.ALL_SERVICE_GIFT_LEVEL_1: + return new AllServiceGiftLevelOneDialog(context, dataBean); + + case AllServiceGiftDialog.ALL_SERVICE_GIFT_LEVEL_2: + + return new AllServiceGiftLevelTwoDialog(context, dataBean); + + case AllServiceGiftDialog.ALL_SERVICE_GIFT_LEVEL_3: + return new AllServiceGiftLevelThreeDialog(context, dataBean); + } + } + + + @Override + protected void onPause() { + super.onPause(); + registerGiftBroadcastMessage(false); + isResume = false; + } + + private int gvTipsIndex = 0; + + public void handleGiftValueStartTips() { + String key_first_open_gift_value_tips = "first_open_gift_value_tips"; + Boolean firstOpen = (Boolean) SharedPreferenceUtils.get(key_first_open_gift_value_tips, true); + if (firstOpen != null && !firstOpen) { + //不是首次打开,不提示 + return; + } + gvTipsIndex = 0; + SharedPreferenceUtils.put(key_first_open_gift_value_tips, false); + final int[] topRes = new int[]{R.drawable.icon_gv_start_top_1, R.drawable.icon_gv_start_top_2}; + //因为0和1是一张图, + final int[] bottomRes = new int[]{R.drawable.icon_gv_start_bottom_0, R.drawable.icon_gv_start_bottom_2}; + ViewStub vs_gift_value_tips = findViewById(R.id.vs_gift_value_tips); + View parent = vs_gift_value_tips.inflate(); + parent.setVisibility(VISIBLE); + View iv_gv_status_bar = parent.findViewById(R.id.iv_gv_status_bar); + final ImageView iv_gv_top = parent.findViewById(R.id.iv_gv_top); + iv_gv_status_bar.getLayoutParams().height = TitleBar.getStatusBarHeight(); + final TextView tv_skip_guide = parent.findViewById(R.id.tv_skip_guide); + tv_skip_guide.setOnClickListener(v -> parent.setVisibility(View.GONE)); + tv_skip_guide.setVisibility(VISIBLE); + ImageView iv_gv_bottom = parent.findViewById(R.id.iv_gv_bottom); + parent.setOnClickListener(v -> { + if (gvTipsIndex < topRes.length) { + iv_gv_top.setImageResource(topRes[gvTipsIndex]); + if (gvTipsIndex == topRes.length - 1) { + tv_skip_guide.setVisibility(View.GONE); + } else { + tv_skip_guide.setVisibility(VISIBLE); + } + } else { + parent.setVisibility(View.GONE); + } + if (gvTipsIndex < bottomRes.length) { + iv_gv_bottom.setImageResource(bottomRes[gvTipsIndex]); + } + gvTipsIndex++; + }); + } + + private void handlePmExitRoom() { + EventBus.getDefault().post(new PmDismissAllLimitDialogEvent()); + getMvpPresenter().exitRoom(); + } + + public LimitEnterRoomHelper getLimitEnterRoomHelper() { + if (limitEnterRoomHelper == null) { + limitEnterRoomHelper = new LimitEnterRoomHelper(); + } + return limitEnterRoomHelper; + } + + @Override + public void recoverRoomMinWhenPmLimit(Throwable throwable) { + getLimitEnterRoomHelper().handleThisContext(this, throwable.getMessage(), true, + this::handlePmExitRoom); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onImPushMsgPmLimitTimeEvent(ImPushMsgPmLimitTimeEvent event) { + //时间到限制时间段之后,后台推送im消息 + getLimitEnterRoomHelper().handleThisContext(this, event.getData(), true, this::handlePmExitRoom); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/CpRoomInviteActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/CpRoomInviteActivity.java new file mode 100644 index 000000000..561c20ea4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/CpRoomInviteActivity.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.avroom.activity; + +import android.os.Bundle; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.InviteFriendListFragment; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityCpRoomInviteBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.public_chat_hall.event.AitFriendEvent; +import com.yizhuan.erban.public_chat_hall.fragment.PublicChatHallFriendListFragment; +import com.yizhuan.erban.ui.im.friend.FriendListFragment; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +@ActLayoutRes(R.layout.activity_cp_room_invite) +public class CpRoomInviteActivity extends BaseBindingActivity { + + private List uids = new ArrayList<>(); + private List userNames = new ArrayList<>(); + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void init() { + EventBus.getDefault().register(this); + initTitleBar("选择好友(0/20)"); + getSupportFragmentManager().beginTransaction().add(R.id.content, new InviteFriendListFragment(), null).commitAllowingStateLoss(); + + mBinding.tvInvite.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) return; + if (uids.size() == 0) { + toast("要选择好友才可以邀请哦!"); + return; + } + String uid = ""; + for (int i = 0; i < uids.size(); i++) { + String targetUid = uids.get(i); + String nick = userNames.get(i); + uid += uids.get(i) + ","; + int sessionType = SessionType.P2P; + IMNetEaseManager.get().sendSharingRoomMessage(sessionType, targetUid); + } + + RoomSettingModel model = new RoomSettingModel(); + + model.invite(AvRoomDataManager.get().mCurrentRoomInfo.getUid(), uid) + .flatMap((Function>) s -> updateRoomInfo("", RoomInfo.IS_INVITE)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(RoomInfo roomInfo, String error) { + super.accept(roomInfo, error); + if (error != null) { + toast(error); + } else { + toast("邀请成功"); + finish(); + } + } + }); + } + }); + } + + private Single updateRoomInfo(String encryptPwd, String limitType) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return Single.error(new Throwable("房间信息空")); + } + //更新房间接口调用成功后,会发事件RoomEvent.ROOM_INFO_UPDATE + RoomSettingModel model = new RoomSettingModel(); + if (AvRoomDataManager.get().isRoomOwner()) { + return model.updateRoomInfo(roomInfo.title, + roomInfo.getRoomDesc(), + roomInfo.getIntroduction(), + encryptPwd, + roomInfo.getRoomTag(), + roomInfo.tagId, + AuthModel.get().getCurrentUid(), + AuthModel.get().getTicket(), + roomInfo.isHasAnimationEffect(), + roomInfo.getAudioQuality(), + limitType, + roomInfo.isPureMode()); + } else { + return model.updateByAdmin(roomInfo.getUid(), roomInfo.title, + roomInfo.getRoomDesc(), + roomInfo.getIntroduction(), + encryptPwd, + roomInfo.getRoomTag(), + roomInfo.tagId, + AuthModel.get().getCurrentUid(), + AuthModel.get().getTicket(), + roomInfo.isHasAnimationEffect(), + roomInfo.getAudioQuality(), + roomInfo.isPureMode()); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void countingAitFriends(AitFriendEvent event) { + switch (event.getType()) { + case AitFriendEvent.TYPE_ADD: + if (uids.size() == 20) { + toast("最多只能选择20个好友哦"); + return; + } + if (!uids.contains(event.getUid())) { + uids.add(event.getUid()); + userNames.add(event.getNick()); + } + break; + + case AitFriendEvent.TYTPE_REMOVE: + if (uids.contains(event.getUid())) { + uids.remove(event.getUid()); + userNames.remove(event.getNick()); + } + break; + } + initTitleBar("选择好友(" + uids.size() + "/20)"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/CreatePKActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/CreatePKActivity.java new file mode 100644 index 000000000..8765f7e3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/CreatePKActivity.java @@ -0,0 +1,450 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayout; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.dialog.PKSelectPeopleDialog; +import com.yizhuan.erban.avroom.dialog.PKTimePickerDialog; +import com.yizhuan.erban.avroom.presenter.CreatePKPresenter; +import com.yizhuan.erban.avroom.view.ICreatePKView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.pk.bean.PKMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/12/28 + */ +@CreatePresenter(CreatePKPresenter.class) +public class CreatePKActivity extends BaseMvpActivity + implements ICreatePKView { + + private GridLayout glRedTeam; + private GridLayout glBlueTeam; + private ImageView ivRedAvatar1; + private TextView tvRedName1; + private ImageView ivRedAvatar2; + private TextView tvRedName2; + private ImageView ivRedAvatar3; + private TextView tvRedName3; + private ImageView ivRedAvatar4; + private TextView tvRedName4; + private ImageView ivBlueAvatar1; + private TextView tvBlueName1; + private ImageView ivBlueAvatar2; + private TextView tvBlueName2; + private ImageView ivBlueAvatar3; + private TextView tvBlueName3; + private ImageView ivBlueAvatar4; + private TextView tvBlueName4; + private RadioButton rbVoteTypeGiftValue; + private RadioButton rbVoteTypeGiftMember; + private LinearLayout llSelectTime; + private TextView tvPkTime; + private TextView okBtn; + private LinearLayout llInPk; + private TextView tvRecreateBtn; + private TextView tvClosePkMode; + + private List redTeamAvatar = new ArrayList<>(); + private List redTeamName = new ArrayList<>(); + + private List blueTeamAvatar = new ArrayList<>(); + private List blueTeamName = new ArrayList<>(); + + private List redTeamMember = new ArrayList<>(); + private List blueTeamMember = new ArrayList<>(); + + public static void start(Context context) { + Intent intent = new Intent(context, CreatePKActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_create_pk); + + + glRedTeam = (GridLayout) findViewById(R.id.gl_red_team); + glBlueTeam = (GridLayout) findViewById(R.id.gl_blue_team); + + ivRedAvatar1 = (ImageView) findViewById(R.id.iv_red_avatar_1); + tvRedName1 = (TextView) findViewById(R.id.tv_red_name_1); + ivRedAvatar2 = (ImageView) findViewById(R.id.iv_red_avatar_2); + tvRedName2 = (TextView) findViewById(R.id.tv_red_name_2); + ivRedAvatar3 = (ImageView) findViewById(R.id.iv_red_avatar_3); + tvRedName3 = (TextView) findViewById(R.id.tv_red_name_3); + ivRedAvatar4 = (ImageView) findViewById(R.id.iv_red_avatar_4); + tvRedName4 = (TextView) findViewById(R.id.tv_red_name_4); + ivBlueAvatar1 = (ImageView) findViewById(R.id.iv_blue_avatar_1); + tvBlueName1 = (TextView) findViewById(R.id.tv_blue_name_1); + ivBlueAvatar2 = (ImageView) findViewById(R.id.iv_blue_avatar_2); + tvBlueName2 = (TextView) findViewById(R.id.tv_blue_name_2); + ivBlueAvatar3 = (ImageView) findViewById(R.id.iv_blue_avatar_3); + tvBlueName3 = (TextView) findViewById(R.id.tv_blue_name_3); + ivBlueAvatar4 = (ImageView) findViewById(R.id.iv_blue_avatar_4); + tvBlueName4 = (TextView) findViewById(R.id.tv_blue_name_4); + rbVoteTypeGiftValue = (RadioButton) findViewById(R.id.rb_vote_type_gift_value); + rbVoteTypeGiftMember = (RadioButton) findViewById(R.id.rb_vote_type_gift_member); + llSelectTime = (LinearLayout) findViewById(R.id.ll_select_time); + tvPkTime = (TextView) findViewById(R.id.tv_pk_time); + okBtn = (TextView) findViewById(R.id.ok_btn); + llInPk = (LinearLayout) findViewById(R.id.ll_in_pk); + tvRecreateBtn = (TextView) findViewById(R.id.tv_recreate_btn); + tvClosePkMode = (TextView) findViewById(R.id.tv_close_pk_mode); + + redTeamAvatar.add(ivRedAvatar1); + redTeamAvatar.add(ivRedAvatar2); + redTeamAvatar.add(ivRedAvatar3); + redTeamAvatar.add(ivRedAvatar4); + redTeamName.add(tvRedName1); + redTeamName.add(tvRedName2); + redTeamName.add(tvRedName3); + redTeamName.add(tvRedName4); + + blueTeamAvatar.add(ivBlueAvatar1); + blueTeamAvatar.add(ivBlueAvatar2); + blueTeamAvatar.add(ivBlueAvatar3); + blueTeamAvatar.add(ivBlueAvatar4); + blueTeamName.add(tvBlueName1); + blueTeamName.add(tvBlueName2); + blueTeamName.add(tvBlueName3); + blueTeamName.add(tvBlueName4); + + + rbVoteTypeGiftValue.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + getMvpPresenter().setPkVoteMode(PkModel.PK_VOTE_MODE_GIFT_VALUE); + } + } + }); + rbVoteTypeGiftMember.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + getMvpPresenter().setPkVoteMode(PkModel.PK_VOTE_MODE_PEOPLE_COUNT); + } + } + }); + llSelectTime.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showSelectTimeDialog(); + } + }); + + okBtn.setOnClickListener(v -> { + //提交pk + if (AvRoomDataManager.get().isQueuingMicro()) { + getDialogManager().showOkCancelDialog("当前正在排麦模式,确认切换为PK模式吗?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + createPk(); + } + }); + + return; + } + createPk(); + + }); + + glRedTeam.setOnClickListener(v -> { + PKSelectPeopleDialog dialog = new PKSelectPeopleDialog(this, PKTeamInfo.TEAM_RED, getPKMemberList()); + dialog.setOnSelectPeopleListener(new PKSelectPeopleDialog.OnSelectPeopleListener() { + @Override + public void onSelectPeople(List micEntityList) { + List userInfoList = new ArrayList<>(); + for (PKSelectPeopleDialog.MicEntity micEntity : micEntityList) { + if (micEntity.isSelect) { + UserInfo userInfo = new UserInfo(); + userInfo.setUid(Long.parseLong(micEntity.uid)); + userInfo.setAvatar(micEntity.avatar); + userInfo.setNick(micEntity.nick); + userInfo.setGender(micEntity.gender); + userInfo.setGroupType(PKTeamInfo.TEAM_RED); + userInfoList.add(userInfo); + } + } + redTeamMember = userInfoList; + for (int i = 0; i < redTeamAvatar.size(); i++) { + if (i < userInfoList.size()) { + GlideApp.with(CreatePKActivity.this) + .load(userInfoList.get(i).getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(redTeamAvatar.get(i)); + redTeamName.get(i).setText(userInfoList.get(i).getNick()); + } else { + redTeamAvatar.get(i).setImageResource(R.mipmap.ic_red_seat); + redTeamName.get(i).setText(R.string.wait_for_mic); + } + } + + + } + }); + dialog.show(); + }); + + glBlueTeam.setOnClickListener(v -> { + PKSelectPeopleDialog dialog = new PKSelectPeopleDialog(this, PKTeamInfo.TEAM_BLUE, getPKMemberList()); + dialog.setOnSelectPeopleListener(new PKSelectPeopleDialog.OnSelectPeopleListener() { + @Override + public void onSelectPeople(List micEntityList) { + List userInfoList = new ArrayList<>(); + for (PKSelectPeopleDialog.MicEntity micEntity : micEntityList) { + if (micEntity.isSelect) { + UserInfo userInfo = new UserInfo(); + userInfo.setUid(Long.parseLong(micEntity.uid)); + userInfo.setAvatar(micEntity.avatar); + userInfo.setNick(micEntity.nick); + userInfo.setGender(micEntity.gender); + userInfo.setGroupType(PKTeamInfo.TEAM_BLUE); + userInfoList.add(userInfo); + } + } + blueTeamMember = userInfoList; + for (int i = 0; i < blueTeamAvatar.size(); i++) { + if (i < userInfoList.size()) { + GlideApp.with(CreatePKActivity.this) + .load(userInfoList.get(i).getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(blueTeamAvatar.get(i)); + blueTeamName.get(i).setText(userInfoList.get(i).getNick()); + } else { + blueTeamAvatar.get(i).setImageResource(R.mipmap.ic_blue_seat); + blueTeamName.get(i).setText(R.string.wait_for_mic); + } + } + } + }); + dialog.show(); + }); + + if (AvRoomDataManager.get().isOpenPKMode()) { + llInPk.setVisibility(View.VISIBLE); + tvRecreateBtn.setOnClickListener(v -> { + getDialogManager().showOkCancelDialog( + "创建此Pk,会覆盖现在进行的PK,\n确定覆盖当前Pk吗?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(CreatePKActivity.this); + getMvpPresenter().createPKAgain( + redTeamMember, + blueTeamMember + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + StatisticManager.Instance().onEvent( + CreatePKActivity.this, + StatisticsProtocol.Event.ROOM_CREATE_A_PK_AGAIN, + "再次创建", + null); + + toast(s); + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + } + }); + }); + + tvClosePkMode.setOnClickListener(v -> { + //关闭pk 模式 + getDialogManager().showOkCancelDialog("结束PK,会关闭现在进行的PK并恢复普通房间模式,确定关闭当前PK吗?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(CreatePKActivity.this); + getMvpPresenter().closePkMode() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast(s); + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + getDialogManager().dismissDialog(); + } + }); + } + }); + }); + } else { + llInPk.setVisibility(View.GONE); + } + + } + + private void createPk() { + getDialogManager().showProgressDialog(CreatePKActivity.this); + getMvpPresenter().createPK( + redTeamMember, + blueTeamMember + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + StatisticManager.Instance().onEvent( + CreatePKActivity.this, + StatisticsProtocol.Event.ROOM_CREATE_A_PK, + "创建PK", + null); + + toast(s); + getDialogManager().dismissDialog(); + finish(); + + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + } + + private List getPKMemberList() { + List pkMemberInfoList = new ArrayList<>(); + for (UserInfo userInfo : redTeamMember) { + PKMemberInfo pkMemberInfo = new PKMemberInfo(); + pkMemberInfo.setTeamId(PKTeamInfo.TEAM_RED); + pkMemberInfo.setUserInfo(userInfo); + pkMemberInfoList.add(pkMemberInfo); + } + for (UserInfo userInfo : blueTeamMember) { + PKMemberInfo pkMemberInfo = new PKMemberInfo(); + pkMemberInfo.setTeamId(PKTeamInfo.TEAM_BLUE); + pkMemberInfo.setUserInfo(userInfo); + pkMemberInfoList.add(pkMemberInfo); + } + return pkMemberInfoList; + } + + @Override + protected void onResume() { + super.onResume(); + if (getMvpPresenter().getPkMode() == -1) { + getMvpPresenter().setPkMode(PkModel.PK_MODE_TEAM); + } + if (getMvpPresenter().getPkVoteMode() == -1) { + getMvpPresenter().setPkVoteMode(PkModel.PK_VOTE_MODE_GIFT_VALUE); + rbVoteTypeGiftValue.setChecked(true); + } + if (getMvpPresenter().getPkDuration() == -1) { + getMvpPresenter().setPkDuration(30); + tvPkTime.setText(30 + "秒"); + } + } + + private void showSelectTimeDialog() { + PKTimePickerDialog pkTimePickerDialog = new PKTimePickerDialog(this); + pkTimePickerDialog.setOnSelectTime(new PKTimePickerDialog.OnSelectTime() { + @Override + public void selectTime(long timeSecond) { + if (timeSecond < 30 || timeSecond > 1800) { + toast("PK的时间大于等于30秒,小于等于30分钟"); + return; + } + tvPkTime.setText((timeSecond / 60) + "分" + (timeSecond % 60) + "秒"); + getMvpPresenter().setPkDuration(timeSecond); + } + }); + pkTimePickerDialog.show(); + + } + + @Override + public void initTitleBar() { + super.initTitleBar(getString(R.string.create_PK)); + mTitleBar.setActionTextColor(getResources().getColor(R.color.color_999999)); + mTitleBar.addAction(new TitleBar.TextAction(getString(R.string.PK_record)) { + @Override + public void performAction(View view) { + RecordForPKActivity.start(CreatePKActivity.this); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/OpenRoomActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/OpenRoomActivity.java new file mode 100644 index 000000000..b3e4be2a0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/OpenRoomActivity.java @@ -0,0 +1,292 @@ +package com.yizhuan.erban.avroom.activity; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.jph.takephoto.app.TakePhotoActivity; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.TResult; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.room.IRoomCoreClient; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_library.coremanager.CoreEvent; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by zhouxiangfeng on 2017/6/1. + */ +@Deprecated +public class OpenRoomActivity extends TakePhotoActivity implements View.OnClickListener { + + private static final String TAG = "OpenRoomActivity"; + /** + * 基本权限管理 + */ + private final String[] BASIC_PERMISSIONS = new String[]{ + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO + }; + + // Content View Elements + private ImageView mIv_close; + private ImageView mIv_cover; + private EditText mEt_title; + private EditText mEt_noti; + private TextView pageTitle; + private Button mBtn_open_room; + private String roomCoverUrl; + private int type; + + //开启竞拍房 + public static void startAuction(Context context) { + Intent intent = new Intent(context, OpenRoomActivity.class); + intent.putExtra("type", RoomInfo.ROOMTYPE_AUCTION); + context.startActivity(intent); + + } + + //开启轻聊房 + public static void startHomeParty(Context context) { + Intent intent = new Intent(context, OpenRoomActivity.class); + intent.putExtra("type", RoomInfo.ROOMTYPE_LIGHT_CHAT); + context.startActivity(intent); + } + + //开启游戏房 + public static void startGame(Context context) { + Intent intent = new Intent(context, OpenRoomActivity.class); + intent.putExtra("type", RoomInfo.ROOMTYPE_HOME_PARTY); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_open_room); + bindViews(); + onSetListener(); + init(); + } + + private void init() { + type = getIntent().getIntExtra("type", 0); + if (type == RoomInfo.ROOMTYPE_AUCTION) { + pageTitle.setText("竞拍房"); + } else if (type == RoomInfo.ROOMTYPE_LIGHT_CHAT) { + pageTitle.setText("轻聊房"); + } else if (type == RoomInfo.ROOMTYPE_HOME_PARTY) { + pageTitle.setText("轰趴房"); + } + } + + private void onSetListener() { + mBtn_open_room.setOnClickListener(this); + mIv_close.setOnClickListener(this); + mIv_cover.setOnClickListener(this); + } + + // End Of Content View Elements + private void bindViews() { + mIv_close = (ImageView) findViewById(R.id.iv_close); + mIv_cover = (ImageView) findViewById(R.id.iv_cover); + mEt_title = (EditText) findViewById(R.id.et_title); + mEt_noti = (EditText) findViewById(R.id.et_noti); + mBtn_open_room = (Button) findViewById(R.id.btn_open_room); + pageTitle = (TextView) findViewById(R.id.title); + } + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(checkPermissionListener, R.string.ask_camera, Manifest.permission.CAMERA); +// checkPermission(checkPermissionListener, R.string.ask_again, android.Manifest.permission.CAMERA); + } + + PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() { + @Override + public void superPermission() { + takePhoto(); + } + }; + + private void takePhoto() { + File cameraOutFile = JXFileUtils.getTempFile(this, "picture_" + System.currentTimeMillis() + ".jpg"); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, false); + getTakePhoto().onPickFromCapture(uri); + } + + /** + * 开房权限检查 + */ + PermissionActivity.CheckPermListener loginCheckPermissionListener = new PermissionActivity.CheckPermListener() { + @SuppressLint("CheckResult") + @Override + public void superPermission() { + getDialogManager().showProgressDialog(OpenRoomActivity.this, "进入房间..."); + AvRoomModel.get().openRoom( + AuthModel.get().getCurrentUid(), type, + mEt_title.getText().toString(), mEt_noti.getText().toString(), + roomCoverUrl, null) + .compose(bindToLifecycle()) + .subscribe((roomResult, throwable) -> { + if (throwable != null) { + onOpenRoomFail(throwable.getMessage()); + } else if (roomResult != null && roomResult.isSuccess()) { + onOpenRoom(roomResult.getData()); + } else if (roomResult != null && !roomResult.isSuccess()) { + if (roomResult.getCode() == 1500) { + onAlreadyOpenedRoom(); + } else { + onOpenRoomFail(roomResult.getError()); + } + } else { + onOpenRoomFail("未知错误"); + } + }); + } + }; + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_open_room: + checkPermission(loginCheckPermissionListener, R.string.ask_again, Manifest.permission.RECORD_AUDIO); + break; + case R.id.iv_close: + finish(); + break; + case R.id.iv_cover: + ButtonItem upItem = new ButtonItem("拍照上传", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + checkPermissionAndStartCamera(); + } + }); + ButtonItem localItem = new ButtonItem("本地相册", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, true); + getTakePhoto().onPickFromGallery(); + } + }); + List buttonItemList = new ArrayList<>(); + buttonItemList.add(upItem); + buttonItemList.add(localItem); + getDialogManager().showCommonPopupDialog(buttonItemList, "取消", false); + break; + default: + } + } + + @CoreEvent(coreClientClass = IRoomCoreClient.class) + public void onGetRoomInfo(RoomInfo roomInfo) { + getDialogManager().dismissDialog(); + mEt_title.setText(roomInfo.getTitle()); + mEt_noti.setText(roomInfo.getRoomDesc()); + + if (!StringUtil.isEmpty(roomInfo.getBackPic())) { + roomCoverUrl = roomInfo.getBackPic(); + ImageLoadUtils.loadAvatar(this, roomCoverUrl, mIv_cover); + } + + } + + @CoreEvent(coreClientClass = IRoomCoreClient.class) + public void onGetRoomInfoFail(String error) { + getDialogManager().dismissDialog(); + } + + public void onOpenRoom(RoomInfo roomInfo) { + getDialogManager().dismissDialog(); + AVRoomActivity.start(this, roomInfo.getUid()); + finish(); + } + + public void onOpenRoomFail(String error) { + toast(error); + getDialogManager().dismissDialog(); + } + + @CoreEvent(coreClientClass = IRoomCoreClient.class) + public void onAlreadyOpenedRoom() { + getDialogManager().showOkCancelDialog("您的房间已开启,是否立即进入?", true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + long uid = AuthModel.get().getCurrentUid(); + AVRoomActivity.start(OpenRoomActivity.this, uid); + finish(); + } + }); + } + + public void onUpload(String url) { + roomCoverUrl = url; + Log.d(TAG, "onUpload: 这是开房间的上传"); +// Glide.with(OpenRoomActivity.this).load(roomCoverUrl).into(mIv_cover); + ImageLoadUtils.loadImage(this, roomCoverUrl, mIv_cover, 0); + getDialogManager().dismissDialog(); + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(OpenRoomActivity.this, "正在上传请稍后..."); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + @Override + public void takeCancel() { + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RecordForPKActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RecordForPKActivity.java new file mode 100644 index 000000000..e4274f2db --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RecordForPKActivity.java @@ -0,0 +1,138 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RecordForPKAdapter; +import com.yizhuan.erban.avroom.presenter.RecordForPKPresenter; +import com.yizhuan.erban.avroom.view.IRecordForPKView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRecordInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +/** + * @author jack + * @Description + * @Date 2018/12/29 + */ +@CreatePresenter(RecordForPKPresenter.class) +public class RecordForPKActivity extends BaseMvpActivity + implements IRecordForPKView { + + + private SwipeRefreshLayout srlRefreshContainer; + private RecyclerView rvList; + private RecordForPKAdapter adapter; + + public static void start(Context context) { + Intent intent = new Intent(context, RecordForPKActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_record_for_pk); + + srlRefreshContainer = (SwipeRefreshLayout) findViewById(R.id.srl_refresh_container); + rvList = (RecyclerView) findViewById(R.id.rv_list); + + srlRefreshContainer.setOnRefreshListener(this::refreshData); + + rvList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + rvList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(this, 10), true)); + adapter = new RecordForPKAdapter(this, null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this::loadMoreData, rvList); + rvList.setAdapter(adapter); + + srlRefreshContainer.setRefreshing(true); + refreshData(); + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + refreshData(); + } + + @Override + public void initTitleBar() { + super.initTitleBar(getString(R.string.PK_record)); + } + + public void refreshData() { + getMvpPresenter().refreshData() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List pkRecordInfos) { + srlRefreshContainer.setRefreshing(false); + if (ListUtils.isListEmpty(pkRecordInfos)) { + showNoData(R.drawable.icon_common_failure, "没有PK记录"); + return; + } + adapter.setNewData(pkRecordInfos); + + } + + @Override + public void onError(Throwable e) { + srlRefreshContainer.setRefreshing(false); + showNetworkErr(); + toast(e.getMessage()); + + } + }); + } + + private void loadMoreData() { + getMvpPresenter().loadMoreData() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List pkRecordInfos) { + adapter.loadMoreComplete(); + if (!ListUtils.isListEmpty(pkRecordInfos)) { + adapter.addData(pkRecordInfos); + } else { + adapter.loadMoreEnd(true); + } + } + + @Override + public void onError(Throwable e) { + adapter.loadMoreComplete(); + toast(e.getMessage()); + } + }); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomBlackListActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomBlackListActivity.java new file mode 100644 index 000000000..ddb4f7c6c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomBlackListActivity.java @@ -0,0 +1,194 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomNormalListAdapter; +import com.yizhuan.erban.avroom.presenter.RoomBlackPresenter; +import com.yizhuan.erban.avroom.view.IRoomBlackView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.im.room.IIMRoomCoreClient; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.coremanager.CoreEvent; + +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import io.reactivex.Single; + +/** + * 黑名单 + * + * @author chenran + * @date 2017/10/11 + */ +@CreatePresenter(RoomBlackPresenter.class) +public class RoomBlackListActivity extends BaseMvpActivity + implements RoomNormalListAdapter.OnRoomNormalListOperationClickListener, IRoomBlackView { + private TextView count; + private RecyclerView recyclerView; + private RoomNormalListAdapter normalListAdapter; + + private SuperAdminModel mSuperAdminModel; + + public static void start(Context context) { + Intent intent = new Intent(context, RoomBlackListActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_room_black_list); + initTitleBar("黑名单"); + initView(); + + showLoading(); + loadData(); + + mSuperAdminModel = new SuperAdminModel(); + } + + private void loadData() { + getMvpPresenter().queryBlackList(500); + } + + private void initView() { + count = (TextView) findViewById(R.id.count); + recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + normalListAdapter = new RoomNormalListAdapter(this); + normalListAdapter.setListOperationClickListener(this); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(normalListAdapter); + } + + @Override + public void onRemoveOperationClick(final ChatRoomMember chatRoomMember) { + getDialogManager().showOkCancelDialog( + "是否将" + chatRoomMember.getNick() + "移除黑名单列表?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + //如果登录用户是超管 + if (SuperAdminUtil.isSuperAdmin()) { + //使用接口移除 + AvRoomModel.get().removeBlack(JavaUtil.str2long(chatRoomMember.getAccount())) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error == null) { + toast("操作成功"); + loadData(); + } else { + toast(error); + } + } + }); + mSuperAdminModel.roomOperate(SuperAdminModel.REMOVE_BLACK_LIST, JavaUtil.str2long(chatRoomMember.getAccount())).subscribe(); + return; + } + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + getMvpPresenter().markBlackList(roomInfo.getRoomId(), + chatRoomMember.getAccount(), false); + } + + } + }); + } + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + showLoading(); + loadData(); + } + }; + } + + @CoreEvent(coreClientClass = IIMRoomCoreClient.class) + public void onMemberBeRemoveManager(String account) { + long uid = AuthModel.get().getCurrentUid(); + if (uid == Long.valueOf(account)) { + finish(); + toast(R.string.remove_room_manager); + } + } + + @Override + public void queryBlackListSuccess(List chatRoomMemberList) { + hideStatus(); + if (chatRoomMemberList != null && chatRoomMemberList.size() > 0) { + normalListAdapter.setNormalList(chatRoomMemberList); + normalListAdapter.notifyDataSetChanged(); + count.setText("黑名单" + chatRoomMemberList.size() + "人"); + } else { + showNoData("暂没有设置黑名单"); + count.setText("黑名单0人"); + } + } + + @Override + public void queryBlackListFail() { + showNetworkErr(); + } + + @Override + public void makeBlackListSuccess(ChatRoomMember chatRoomMember, boolean mark) { + if (chatRoomMember == null) return; + List normalList = normalListAdapter.getNormalList(); + if (!ListUtils.isListEmpty(normalList)) { + hideStatus(); + ListIterator iterator = normalList.listIterator(); + for (; iterator.hasNext(); ) { + if (Objects.equals(iterator.next().getAccount(), chatRoomMember.getAccount())) { + iterator.remove(); + } + } + normalListAdapter.notifyDataSetChanged(); + count.setText("黑名单" + normalList.size() + "人"); + if (normalList.size() == 0) { + showNoData("暂没有设置黑名单"); + } + } else { + showNoData("暂没有设置黑名单"); + count.setText("黑名单0人"); + } + toast("操作成功"); + + } + + @Override + public void makeBlackListFail(int code, String error, boolean mark) { +// toast("操作失败,请重试"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomInviteActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomInviteActivity.java new file mode 100644 index 000000000..24b9822a9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomInviteActivity.java @@ -0,0 +1,199 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.widget.Toast; + +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomInviteAdapter; +import com.yizhuan.erban.avroom.presenter.RoomInvitePresenter; +import com.yizhuan.erban.avroom.view.IRoomInviteView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; +import java.util.Map; + +/** + *

抱人上麦

+ * + * @author jiahui + * @date 2017/12/21 + */ +@CreatePresenter(RoomInvitePresenter.class) +public class RoomInviteActivity extends BaseMvpActivity + implements IRoomInviteView, RoomInviteAdapter.OnItemClickListener, RoomInviteAdapter.OnRoomOnlineNumberChangeListener { + private RoomInviteAdapter mRoomInviteAdapter; + private SmartRefreshLayout mRefreshLayout; + private RecyclerView mRecyclerView; + + private int mPage = Constants.PAGE_START; + private int micPosition; + + public static void openActivity(FragmentActivity fragmentActivity, int micPosition) { + Intent intent = new Intent(fragmentActivity, RoomInviteActivity.class); + intent.putExtra(Constants.KEY_POSITION, micPosition); + fragmentActivity.startActivityForResult(intent, 200); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_room_invite); + mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); + mRefreshLayout = (SmartRefreshLayout) findViewById(R.id.refresh_layout); + initTitleBar(getString(R.string.title_online)); + Intent intent = getIntent(); + if (intent != null) + micPosition = intent.getIntExtra(Constants.KEY_POSITION, Integer.MIN_VALUE); + + mRoomInviteAdapter = new RoomInviteAdapter(this, this); + mRecyclerView.setAdapter(mRoomInviteAdapter); + mRoomInviteAdapter.setOnRoomOnlineNumberChangeListener(this); + mRefreshLayout.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(RoomInviteActivity.this)) { + mRefreshLayout.finishLoadmore(); + return; + } + List data = mRoomInviteAdapter.getChatRoomMemberList(); + if (ListUtils.isListEmpty(data)) { + mRefreshLayout.finishLoadmore(); + return; + } + loadData(data.get(data.size() - 1).getEnterTime()); + } + + @Override + public void onRefresh(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(RoomInviteActivity.this)) { + mRefreshLayout.finishRefresh(); + return; + } + firstLoad(); + } + }); + showLoading(); + firstLoad(); + } + + public void firstLoad() { + mPage = Constants.PAGE_START; + loadData(0); + } + + private void loadData(long time) { + getMvpPresenter().requestChatMemberByPage(mPage, time); + } + + @Override + public void onRequestChatMemberByPageSuccess(List memberList, int page) { + + } + + @Override + public void onRequestChatMemberByPageFail(String errorStr, int page) { + mPage = page; + if (mPage == Constants.PAGE_START) { + mRefreshLayout.finishRefresh(0); + showNoData(getString(R.string.data_error)); + } else { + mRefreshLayout.finishLoadmore(0); + } + } + + @Override + public void onMemberInRefresh() { + + } + + @Override + public void onRequestMemberByPageSuccess(List memberList, int page) { + mPage = page; + if (mPage == Constants.PAGE_START) { + List chatRoomMemberList = mRoomInviteAdapter.getChatRoomMemberList(); + if (!ListUtils.isListEmpty(chatRoomMemberList)) + chatRoomMemberList.clear(); + mRefreshLayout.finishRefresh(0); + if (ListUtils.isListEmpty(memberList)) { + showNoData("暂无可抱用户"); + } else { + hideStatus(); + mRoomInviteAdapter.addChatRoomMemberList(memberList); + } + } else { + mRefreshLayout.finishLoadmore(0); + if (!ListUtils.isListEmpty(memberList)) { + mRoomInviteAdapter.addChatRoomMemberList(memberList); + } + } + } + + @Override + public void onClick(ChatRoomMember chatRoomMember) { + if (chatRoomMember == null) return; + + boolean isRobot = true; + Map extension = (Map) chatRoomMember.getExtension(); + if (extension != null) { + Map map = (Map) extension.get(chatRoomMember.getAccount()); + if (map != null) { + String defUser = map.get(UserInfo.DEF_USER) == null ? null : map.get(UserInfo.DEF_USER) + ""; + String resource = map.get(NobleResourceType.KEY_LEVEL) == null ? null : map.get(NobleResourceType.KEY_LEVEL) + ""; + if ((!TextUtils.isEmpty(defUser) && Integer.parseInt(defUser) != UserInfo.USER_TYPE_ROBOT) + || (!TextUtils.isEmpty(resource) && Integer.parseInt(resource) > 0)) { + isRobot = false; + } + } + } + if (isRobot) { +// Toast.makeText(context, context.getResources().getString(R.string.unable_to_up_mic_by_level), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.unable_to_up_mic_by_level); + return; + } + + Intent intent = new Intent(); + intent.putExtra("account", chatRoomMember.getAccount()); + String nick = chatRoomMember.getNick(); + intent.putExtra("nick", nick == null ? "" : nick); + intent.putExtra(Constants.KEY_POSITION, micPosition); + setResult(100, intent); + finish(); + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + showLoading(); + firstLoad(); + } + + @Override + public void onRoomOnlineNumberChange(int number) { + if (number == 0) { + showNoData(); + } + } + + @Override + protected void onDestroy() { + if (mRoomInviteAdapter != null) + mRoomInviteAdapter.onRelease(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomManagerListActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomManagerListActivity.java new file mode 100644 index 000000000..58df52fc9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomManagerListActivity.java @@ -0,0 +1,147 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomNormalListAdapter; +import com.yizhuan.erban.avroom.presenter.RoomManagerPresenter; +import com.yizhuan.erban.avroom.view.IRoomManagerView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +/** + * 房间管理员列表 + * + * @author chenran + * @date 2017/10/11 + */ +@CreatePresenter(RoomManagerPresenter.class) +public class RoomManagerListActivity extends BaseMvpActivity + implements RoomNormalListAdapter.OnRoomNormalListOperationClickListener, IRoomManagerView { + private TextView count; + private RecyclerView recyclerView; + private RoomNormalListAdapter normalListAdapter; + + public static void start(Context context) { + Intent intent = new Intent(context, RoomManagerListActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_room_manager_list); + initTitleBar("管理员"); + initView(); + + showLoading(); + loadData(); + } + + private void loadData() { + getMvpPresenter().queryManagerList(500); + } + + private void initView() { + count = (TextView) findViewById(R.id.count); + recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + normalListAdapter = new RoomNormalListAdapter(this); + normalListAdapter.setListOperationClickListener(this); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(normalListAdapter); + } + + @Override + public void onRemoveOperationClick(final ChatRoomMember chatRoomMember) { + getDialogManager().showOkCancelDialog("是否将" + chatRoomMember.getNick() + "移除管理员列表?", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + getMvpPresenter().markManagerList(roomInfo.getRoomId(), chatRoomMember.getAccount(), false); + } + } + }); + } + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + showLoading(); + loadData(); + } + }; + } + + @Override + public void queryManagerListSuccess(List chatRoomMemberList) { + + hideStatus(); + if (chatRoomMemberList != null && chatRoomMemberList.size() > 0) { + normalListAdapter.setNormalList(chatRoomMemberList); + normalListAdapter.notifyDataSetChanged(); + count.setText("管理员" + chatRoomMemberList.size() + "人"); + } else { + showNoData("暂没有设置管理员"); + count.setText("管理员0人"); + } + } + + @Override + public void queryManagerListFail() { + showNetworkErr(); + } + + @Override + public void markManagerListSuccess(ChatRoomMember chatRoomMember) { + if (chatRoomMember == null) return; + List list = normalListAdapter.getNormalList(); + if (!ListUtils.isListEmpty(list)) { + hideStatus(); + ListIterator iterator = list.listIterator(); + for (; iterator.hasNext(); ) { + if (Objects.equals(iterator.next().getAccount(), chatRoomMember.getAccount())) { + iterator.remove(); + } + } + normalListAdapter.notifyDataSetChanged(); + count.setText("管理员" + list.size() + "人"); + if (list.size() == 0) { + showNoData("暂没有设置管理员"); + } + } else { + showNoData("暂没有设置管理员"); + count.setText("管理员0人"); + } + toast("操作成功"); +// loadData(); + } + + @Override + public void markManagerListFail(int code, String error) { +// toast("操作失败,请重试"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomOnlineUserActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomOnlineUserActivity.java new file mode 100644 index 000000000..934dd80f2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomOnlineUserActivity.java @@ -0,0 +1,59 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.OnlineUserFragment; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.ActivityRoomOnlineUserBinding; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.activity_room_online_user) +public class RoomOnlineUserActivity extends BaseBindingActivity { + + private String [] bgPicture = new String[]{""}; + + public static void start(Context context) { + Intent intent = new Intent(context, RoomOnlineUserActivity.class); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar("在线列表"); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + AVRoomActivity.setBackBg(this, roomInfo, mBinding.svgaImageViewBg, bgPicture, mBinding.view); + getSupportFragmentManager().beginTransaction() + .add(R.id.fragment_container, + new OnlineUserFragment(), + OnlineUserFragment.class.getSimpleName()) + .commitAllowingStateLoss(); + } + + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left_white); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + mTitleBar.setCommonBackgroundColor(getResources().getColor(R.color.transparent)); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mBinding.svgaImageViewBg.isAnimating()) { + mBinding.svgaImageViewBg.clearAnimation(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomRankListActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomRankListActivity.java new file mode 100644 index 000000000..fd59c291d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomRankListActivity.java @@ -0,0 +1,110 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chad.library.adapter.base.entity.MultiItemEntity; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.RoomCharmListFragment; +import com.yizhuan.erban.avroom.fragment.RoomContributeListFragment; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.databinding.ActivityRoomRankListBinding; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 房间排行榜,(魅力榜+贡献榜) + */ +@ActLayoutRes(R.layout.activity_room_rank_list) +public class RoomRankListActivity extends BaseBindingActivity { + + + public static void start(Context context) { + Intent intent = new Intent(context, RoomRankListActivity.class); + context.startActivity(intent); + } + + private String [] bgPicture = new String[]{""}; + + @Override + protected void init() { + mBinding.setClick(this); + List list = new ArrayList<>(); + list.add(RoomCharmListFragment.newInstance()); + list.add(new RoomContributeListFragment()); + mBinding.viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) { + @Override + public Fragment getItem(int position) { + return list.get(position); + } + + @Override + public int getCount() { + return list.size(); + } + }); + mBinding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + mBinding.setPosition(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + AVRoomActivity.setBackBg(this, roomInfo, mBinding.svgaImageViewBg, bgPicture, mBinding.view); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + case R.id.tv_charm_tab: + mBinding.viewPager.setCurrentItem(0); + break; + case R.id.tv_contribute_tab: + mBinding.viewPager.setCurrentItem(1); + break; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mBinding.svgaImageViewBg.isAnimating()) { + mBinding.svgaImageViewBg.clearAnimation(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomSettingActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomSettingActivity.java new file mode 100644 index 000000000..c1871c9f4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomSettingActivity.java @@ -0,0 +1,797 @@ +package com.yizhuan.erban.avroom.activity; + +import android.content.Context; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.TextUtils; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.RelativeLayout; + +import com.donkingliang.labels.LabelsView; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.presenter.RoomSettingPresenter; +import com.yizhuan.erban.avroom.view.IRoomSettingView; +import com.yizhuan.erban.avroom.widget.EditRoomTitleDialog; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityRoomSettingBinding; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.KickOutEvent; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomNoticeAttachment; +import com.yizhuan.xchat_android_core.kick.KickModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomMessageViewNoticeInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomSettingTabInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.GiftValueModel; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.HomePartyModel; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +/** + * @author chenran + * @date 2017/9/26 + */ +@CreatePresenter(RoomSettingPresenter.class) +public class RoomSettingActivity extends BaseMvpActivity + implements LabelsView.OnLabelClickListener, View.OnClickListener, IRoomSettingView { + + private EditText pwdEdit; + private LabelsView labelsView; + private List labels; + private String selectLabel; + private RelativeLayout managerLayout; + private RelativeLayout blackLayout; + private RelativeLayout mRoomBgLayout; + + private RoomInfo roomInfo; + + private View selectLabelView; + + private RoomSettingTabInfo mSelectTabInfo; + private List mTabInfoList; + private ActivityRoomSettingBinding binding; + + public static void start(Context context) { + Intent intent = new Intent(context, RoomSettingActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = DataBindingUtil.setContentView(this,R.layout.activity_room_setting); + initTitleBar(getString(R.string.room_setting)); + binding.setClick(this); + EventBus.getDefault().register(this); +// TitleBar titleBar = (TitleBar) findViewById(R.id.title_bar); +// titleBar.addAction(new TitleBar.TextAction(getString(R.string.save)) { +// @Override +// public void performAction(View view) { +// save(null); +// } +// }); + roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + toast("房间信息为空"); + return; + } + initView(); + initLeaveMode(); + getMvpPresenter().requestRoomInfo(roomInfo.getUid()); + mRoomBgLayout.setVisibility(View.GONE); + if (!AvRoomDataManager.get().isRoomOwner(String.valueOf(AuthModel.get().getCurrentUid()))) { + managerLayout.setVisibility(View.GONE); + } else { + managerLayout.setVisibility(View.VISIBLE); + if (AvRoomDataManager.get().isRoomOwner()) { + mRoomBgLayout.setVisibility(View.VISIBLE); + } + } + if (AvRoomDataManager.get().isCpRoom()) { + binding.queuingMicroModeLayout.setVisibility(View.GONE); + } + //调用更改房间信息接口后,会发消息ROOM_INFO_UPDATE,在此处接收ui改动 + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .filter(roomEvent -> roomEvent.getEvent() == RoomEvent.ROOM_INFO_UPDATE) + .subscribe(roomEvent -> updateRoomInfoView()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + /** + * 隐藏虚拟键盘 + */ + public void hideKeyboard(View v) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null && imm.isActive()) { + imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0); + + } + } + + private void initView() { + pwdEdit = (EditText) findViewById(R.id.pwd_edit); + managerLayout = (RelativeLayout) findViewById(R.id.manager_layout); + blackLayout = (RelativeLayout) findViewById(R.id.black_layout); + mRoomBgLayout = (RelativeLayout) findViewById(R.id.room_bg_layout); + + managerLayout.setOnClickListener(this); + blackLayout.setOnClickListener(this); + mRoomBgLayout.setOnClickListener(this); + + binding.switchAudio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked){ + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("开启高品质音效效果将导致声音较大延迟,请慎重选择"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + binding.switchAudio.setChecked(false); + } + + @Override + public void onOk() { + binding.switchAudio.setChecked(true); + } + }); + } + } + }); + updateRoomInfoView(); + } + + /** + * 非cp房,牌照房,房主可设置离开模式 + */ + private void initLeaveMode() { + + if (AvRoomDataManager.get().isRoomOwner() && !AvRoomDataManager.get().isCpRoom() && roomInfo.getIsPermitRoom() == 1) { + binding.leaveModeLayout.setVisibility(View.VISIBLE); + } else { + binding.leaveModeLayout.setVisibility(View.GONE); + } + } + + /** + * 更改房间设置的消息 + */ + private void updateRoomInfoView() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + return; + } + roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + binding.tvRoomName.setText(RegexUtil.getPrintableString(roomInfo.getTitle())); + + + selectLabel = roomInfo.getRoomTag(); + if (selectLabel == null) { + selectLabel = ""; + } + binding.tvRoomLabel.setText(selectLabel); + binding.switchAudio.setChecked(roomInfo.getAudioQuality() == 2); + if (TextUtils.isEmpty(roomInfo.getRoomPwd())) { + binding.layoutPwdResult.setVisibility(View.GONE); + binding.ivRoomLock.setSelected(false); + binding.ivRoomLock.setImageResource(R.drawable.icon_room_set_lock_false); + } else { + binding.layoutPwdResult.setVisibility(View.VISIBLE); + try { + binding.tvPassword.setText(DESUtils.DESAndBase64Decrypt(roomInfo.getRoomPwd())); + } catch (Exception e) { + e.printStackTrace(); + } + binding.ivRoomLock.setSelected(true); + binding.ivRoomLock.setImageResource(R.drawable.icon_room_set_lock_true); + } + setupSwitch(roomInfo); + if (roomInfo.getType() == RoomInfo.ROOMTYPE_CP) { + binding.rlPwd.setVisibility(View.GONE); + binding.layoutPwdResult.setVisibility(View.GONE); + } + } + + private void save(final String name, final String pwd, String label) { + save(name, pwd, label, false, + roomInfo.isHasAnimationEffect()); + } + + /** + * 保存用户信息,不需要改动的传null + * @param name 房间名字 + * @param pwd 房间密码 + * @param label 房间标签 + * @param isUpdateGiftEffect 是否改动了礼物特效 + * @param giftEffect 是否开启礼物特效 + */ + private void save(final String name, final String pwd, String label, boolean isUpdateGiftEffect, + boolean giftEffect) { + String desc = null; + getDialogManager().showProgressDialog(this, "请稍后..."); + int id = roomInfo.tagId; + if (mSelectTabInfo != null) { + id = mSelectTabInfo.getId(); + } + //更新房间接口调用成功后,会发事件RoomEvent.ROOM_INFO_UPDATE + RoomSettingModel model = new RoomSettingModel(); + BeanObserver observer = new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + getDialogManager().dismissDialog(); + } + + @Override + public void onSuccess(RoomInfo info) { + getDialogManager().dismissDialog(); + if (isUpdateGiftEffect && !giftEffect) { + getMvpPresenter().updateGiftEffect(info); + } + } + }; + if (AvRoomDataManager.get().isRoomOwner()) { + model.updateRoomInfo(name, desc, roomInfo.getIntroduction(), pwd, label, id, + AuthModel.get().getCurrentUid(), + AuthModel.get().getTicket(), + giftEffect, + binding.switchAudio.isChecked() ? 2 : 1, + roomInfo.getLimitType(),roomInfo.isPureMode()) + .compose(bindToLifecycle()) + .subscribe(observer); + StatisticManager.Instance().sortLogFileByLastModified(); + + } else if (AvRoomDataManager.get().isRoomAdmin()) { + model.updateByAdmin(roomInfo.getUid(), name, desc, roomInfo.getIntroduction(), pwd, label, id, + AuthModel.get().getCurrentUid(), + AuthModel.get().getTicket(), + giftEffect, + binding.switchAudio.isChecked() ? 2 : 1, + roomInfo.isPureMode()) + .compose(bindToLifecycle()) + .subscribe(observer); + } + } + + @Override + public void onLabelClick(View label, String labelText, int position) { + if (!ListUtils.isListEmpty(mTabInfoList)) { + mSelectTabInfo = mTabInfoList.get(position); + } + selectLabel = labelText; + labelsView.setSelects(position); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.manager_layout: + RoomManagerListActivity.start(this); + break; + case R.id.black_layout: + RoomBlackListActivity.start(this); + break; + case R.id.room_bg_layout: + CommonWebViewActivity.start(this, UriProvider.getRoomBg()); + break; + + case R.id.layout_room_name_edit: + EditRoomTitleDialog nameDialog = new EditRoomTitleDialog(this, + EditRoomTitleDialog.TYPE_EDIT_NAME, binding.tvRoomName.getText().toString()); + nameDialog.show(); + nameDialog.setOnEditTitleListner(new EditRoomTitleDialog.OnEditTitleListner() { + @Override + public void onEditTitleListner(String newName) { + if (newName.equals(roomInfo.getTitle())) { + return; + } + save(newName, null, null); + } + }); + break; + case R.id.iv_room_lock: + if (binding.ivRoomLock.isSelected()) { + //直接调接口取消密码 + save(null, "", null); + break; + } + //不break调,走编辑密码的逻辑 + case R.id.tv_password: + EditRoomTitleDialog pwdDialog = new EditRoomTitleDialog(this, + EditRoomTitleDialog.TYPE_EDIT_PASSWORD, binding.tvPassword.getText().toString()); + pwdDialog.setOnEditTitleListner(new EditRoomTitleDialog.OnEditTitleListner() { + @Override + public void onEditPwdListner(String newPwd) { + String encryptPwd = DESUtils.DESAndBase64(newPwd); + if (encryptPwd.equals(roomInfo.getRoomPwd())) { + return; + } + save(null, encryptPwd, null); + } + }); + pwdDialog.show(); + break; + case R.id.layout_label: + if (selectLabelView == null) { + selectLabelView = binding.vsLabels.getViewStub().inflate(); + labelsView = selectLabelView.findViewById(R.id.labels_view); + } + selectLabelView.setVisibility(View.VISIBLE); + selectLabelView.findViewById(R.id.iv_close_label).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selectLabelView.setVisibility(View.GONE); + } + }); + selectLabelView.findViewById(R.id.tv_select_lable).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selectLabelView.setVisibility(View.GONE); + //选择的是同一个则不处理 + if (TextUtils.isEmpty(selectLabel) || selectLabel.equals(roomInfo.getRoomTag())) { + return; + } +// StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_LIST_LABEL, +// "区分房间标签:" + selectLabel); + save(null, null, selectLabel); + } + }); + labelsView.setOnLabelClickListener(this); + getMvpPresenter().requestTagAll(); + break; + case R.id.switch_gift: + if (binding.switchGift.isSelected()) { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("关闭后将看不到礼物特效,运作更加流畅,是否确认关闭礼物特效"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + save(null, null, null, true, false); + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.EVENT_ROOM_CLOSE_GIFT_EFFECTS_CLICK, "关闭礼物特效", null); + } + }); + return; + } + //开启礼物特效 + save(null, null, null, true, true); + break; + case R.id.switch_screen: + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + getDialogManager().showProgressDialog(this, "请稍后..."); + AvRoomModel.get().closeScreen(roomInfo.getRoomId(), + !roomInfo.isCloseScreen()) + .compose(bindToLifecycle()) + .flatMap(data -> IMNetEaseManager.get().closeOpenScreen( + data.getRoomId(), data)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + } + + @Override + public void onSuccess(Object o) { + roomInfo.setCloseScreen(!roomInfo.isCloseScreen()); + binding.switchScreen.setImageResource(!roomInfo.isCloseScreen() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + getDialogManager().dismissDialog(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + } + }); + break; + + case R.id.switch_queuing_micro_mode: + if (AvRoomDataManager.get().isOpenPKMode()) { + toast("PK模式已开启排麦"); + return; + } + if (!AvRoomDataManager.get().isQueuingMicro()) { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("开启排麦模式要排队才能上麦,确定开启吗?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getMvpPresenter().openQueuingMicMode(); + } + }); + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.EVENT_ROOM_OPEN_PLATOON_CLICK, "开启排麦模式", null); + } else { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("关闭排麦模式后会清空排麦列表哦,确定关闭吗?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getMvpPresenter().closeQueuingMicMode(); + } + }); + } + break; + + case R.id.switch_room_pure_mode: + if (!AvRoomDataManager.get().isOpenPureMode()) { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("开启纯净模式后,砸蛋消息将不在当前房间展示,确认开启吗?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getMvpPresenter().openRoomPureMode(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.ROOM_OPEN_PURE_MODE, "开启纯净模式"); + } + }); + } else { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("确认关闭纯净模式吗?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + // TODO: 2019/3/12 调用打开纯净模式的接口 + getMvpPresenter().closeRoomPureMode(); + } + }); + } + break; + + case R.id.switch_leave_mode: // 离开模式 + RoomInfo roomInfo1 = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo1 == null) + return; + + if (roomInfo1.isOpenKTV) { + toast("开启离开模式请先关闭ktv"); + return; + } + + if (!roomInfo1.isLeaveMode()) { + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("开启离开模式后,房主会固定显示在房主位,确认开启吗?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(RoomSettingActivity.this, "请稍后..."); + downMicroFirst(); + } + }); + + } else { + getDialogManager().showProgressDialog(RoomSettingActivity.this, "请稍后..."); + if (AvRoomDataManager.get().isShowGiftValue()) // 礼物值模式下关闭离开模式需要执行礼物值下麦清除礼物值 + GiftValueMrg.get().requestDownMic(-1, String.valueOf(AuthModel.get().getCurrentUid())); + getMvpPresenter().leaveModeClose(roomInfo1.getUid()); + } + break; + + default: + } + } + + + @Override + public void onResultRequestTagAllSuccess(List tabInfoList) { + mTabInfoList = tabInfoList; + if (ListUtils.isListEmpty(tabInfoList)) { + toast("房间标签为空"); + return; + } + labels = new ArrayList<>(); + for (RoomSettingTabInfo tabInfo : tabInfoList) { + labels.add(tabInfo.getName()); + } + labelsView.setLabels((ArrayList) labels); + if (roomInfo != null && !TextUtils.isEmpty(roomInfo.getRoomTag())) { + if (labels.contains(roomInfo.getRoomTag())) { + labelsView.setSelects(labels.indexOf(roomInfo.getRoomTag())); + } + } + } + + + @Override + public void onResultRequestTagAllFail(String error) { + toast(error); + } + + @Override + public void updateRoomInfoSuccess(RoomInfo roomInfo) { + + } + + @Override + public void reQuestRoomInfo(RoomInfo roomInfo) { + AvRoomDataManager.get().mCurrentRoomInfo = roomInfo; + setupSwitch(roomInfo); + } + + private void setupSwitch(RoomInfo roomInfo) { + // 礼物特效开关状态 + binding.switchGift.setSelected(roomInfo.isHasAnimationEffect()); + binding.switchGift.setImageResource(roomInfo.isHasAnimationEffect() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + // 公屏开关状态 + binding.switchScreen.setSelected(!roomInfo.isCloseScreen()); + binding.switchScreen.setImageResource(!roomInfo.isCloseScreen() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + // 排麦模式的开关状态 + binding.switchQueuingMicroMode.setSelected(AvRoomDataManager.get().isQueuingMicro()); + binding.switchQueuingMicroMode.setImageResource(AvRoomDataManager.get().isQueuingMicro() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + // 纯净模式的开关状态 + binding.switchRoomPureMode.setSelected(roomInfo.isPureMode()); + binding.switchRoomPureMode.setImageResource(roomInfo.isPureMode() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + // 纯净模式提示语 + binding.tvTipsRoomPureMode.setVisibility(binding.switchRoomPureMode.isSelected() ? + View.VISIBLE : View.GONE); + + // 离开模式 + binding.switchLeaveMode.setSelected(roomInfo.isLeaveMode()); + binding.switchLeaveMode.setImageResource(roomInfo.isLeaveMode() ? + R.drawable.icon_room_set_lock_true : R.drawable.icon_room_set_lock_false); + binding.tvTipsLeaveMode.setVisibility(roomInfo.isLeaveMode() ? View.VISIBLE : View.GONE); + } + + @Override + public void updateRoomInfoFail(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccessToFinish() { + finish(); + } + + @Override + public void onFailToToast(String error) { + toast(error); + } + + @Override + public void onUpdateRoomPureMode(RoomInfo roomInfo) { + getDialogManager().dismissDialog(); + setupSwitch(roomInfo); + sendRoomPureModeMsg(roomInfo.isPureMode()); + } + + @SuppressWarnings("CheckResult") + private void downMicroFirst() { + RoomInfo tempRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (tempRoomInfo == null) + return; + + // 新版房主位优先判断麦序是否有人,麦序没人再判断是否是离开模式(防止新版展示离开模式,实际麦位有人) + + int position = AvRoomDataManager.get().getMicPosition(tempRoomInfo.getUid()); + if (position != AvRoomDataManager.POSITON_NOT_ON_MIC) { // 房主在麦上 + // 房主下麦 + IMNetEaseManager.get().downMicroPhoneBySdk(position, new CallBack() { + @Override + public void onSuccess(String data) { + getDialogManager().dismissDialog(); + getMvpPresenter().leaveModeOpen(AvRoomDataManager.get().getRoomUid()); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + } + }); + + if (position != -1) { // 房主不在房主位, 房主位上的用户下麦 + RoomQueueInfo queueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(-1); + if (queueInfo != null && queueInfo.mChatRoomMember != null) { // 房主麦没人 + ChatRoomMember tempChatRoomMember = queueInfo.mChatRoomMember; + long micUid = JavaUtil.str2long(tempChatRoomMember.getAccount()); + String nick = tempChatRoomMember.getNick(); + // 下麦旁听 + IMNetEaseManager.get().downMicroPhoneBySdk(-1, new CallBack() { + @Override + public void onSuccess(String data) { + IMNetEaseManager.get().kickMicroPhoneBySdk(micUid, nick, tempRoomInfo.getRoomId()).subscribe(chatRoomMessage -> { + KickModel.get().onSendRoomMessageSuccess(chatRoomMessage); + } + , Throwable::printStackTrace); + + } + + @Override + public void onFail(int code, String error) { + + } + }); + } + + } + + } else { // 房主不在麦上 + RoomQueueInfo queueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(-1); + if (queueInfo == null || queueInfo.mChatRoomMember == null) { // 房主麦没人 + getMvpPresenter().leaveModeOpen(AvRoomDataManager.get().getRoomUid()); + + } else {// 房主麦有人 + // 下麦旁听 + ChatRoomMember tempChatRoomMember = queueInfo.mChatRoomMember; + long micUid = JavaUtil.str2long(tempChatRoomMember.getAccount()); + String nick = tempChatRoomMember.getNick(); + + IMNetEaseManager.get().downMicroPhoneBySdk(-1, new CallBack() { + @Override + public void onSuccess(String data) { + getDialogManager().dismissDialog(); + getMvpPresenter().leaveModeOpen(AvRoomDataManager.get().getRoomUid()); + + IMNetEaseManager.get().kickMicroPhoneBySdk(micUid, nick, tempRoomInfo.getRoomId()).subscribe(chatRoomMessage -> { + KickModel.get().onSendRoomMessageSuccess(chatRoomMessage); + } + , Throwable::printStackTrace); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + } + }); + } + + } + + } + + @SuppressWarnings("CheckResult") + @Override + public void leaveModeOpenSuccess() { + getDialogManager().dismissDialog(); + } + + @Override + public void leaveModeOpenFail(String msg) { + getDialogManager().dismissDialog(); + } + + @Override + public void leaveModeCloseSuccess() { + getDialogManager().dismissDialog(); + RoomInfo roomInfo1 = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo1 == null) + return; + + if (roomInfo1.isShowGiftValue()) + GiftValueModel.get().downMic(-1, String.valueOf(AuthModel.get().getCurrentUid())).subscribe(); + } + + @Override + public void leaveModeCloseFail(String msg) { + getDialogManager().dismissDialog(); + + } + + @SuppressWarnings("CheckResult") + public void sendRoomPureModeMsg(boolean isRoomPureMode) { + String contentText; + if (isRoomPureMode) { + contentText = "管理员开启纯净模式,砸蛋消息将不在当前房间公屏展示"; + } else { + contentText = "管理员关闭纯净模式"; + } + RoomMessageViewNoticeInfo messageViewNoticeInfo = new RoomMessageViewNoticeInfo(); + messageViewNoticeInfo.setTips(contentText); + RoomNoticeAttachment attachment = new RoomNoticeAttachment(CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO, + CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_NOTICE); + attachment.setRoomMessageViewNoticeInfo(messageViewNoticeInfo); + ChatRoomMessage screenMsg = ChatRoomMessageBuilder.createChatRoomCustomMessage( + String.valueOf(AvRoomDataManager.get().getRoomId()), + attachment + ); + IMNetEaseManager.get().sendChatRoomMessage(screenMsg, false) + .subscribe((message, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + IMNetEaseManager.get().addMessagesImmediately(message); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onKickedOutEvent(KickOutEvent event) { + finish(); + } + + @Override + protected void onReceiveChatRoomEvent(RoomEvent roomEvent) { + super.onReceiveChatRoomEvent(roomEvent); + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.KICK_OUT_ROOM: + finish(); + break; + case RoomEvent.ROOM_MANAGER_REMOVE: + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + toast(R.string.remove_room_manager); + finish(); + } + break; + default: + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomTitleEditActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomTitleEditActivity.java new file mode 100644 index 000000000..10c681d03 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/activity/RoomTitleEditActivity.java @@ -0,0 +1,174 @@ +package com.yizhuan.erban.avroom.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityRoomTitleEditBinding; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; + +@ActLayoutRes(R.layout.activity_room_title_edit) +public class RoomTitleEditActivity extends BaseBindingActivity implements BiConsumer { + public static final int ROOM_TITLE_EDIT_REQUEST_CODE = 9999; + public static final String ROOM_TITLE_EDIT_REQUEST_RESULT = "room_info"; + + private CompositeDisposable mDisposable; + private DialogManager mDialogManager; + + public static void startForResult(Activity context, String title, String desc) { + Intent intent = new Intent(context, RoomTitleEditActivity.class); + intent.putExtra("title", title); + intent.putExtra("desc", desc); + + context.startActivityForResult(intent, ROOM_TITLE_EDIT_REQUEST_CODE); + } + + private TextWatcher mTitleWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + mBinding.tvTitleCount.setText(s.length() + "/15"); + } + }; + + private TextWatcher mDescWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + mBinding.tvDescCount.setText(s.length() + "/300"); + } + }; + + @Override + protected void init() { + initTitleBar(getResources().getString(R.string.title_room_title_edit)); + mBinding.setClick(this); + mBinding.etTitle.addTextChangedListener(mTitleWatcher); + mBinding.etDesc.addTextChangedListener(mDescWatcher); + + Intent intent = getIntent(); + + String title = intent.getStringExtra("title"); + String desc = intent.getStringExtra("desc"); + mBinding.etTitle.setText(title); + mBinding.etDesc.setText(desc); + + mDisposable = new CompositeDisposable(); + mDialogManager = new DialogManager(this); + + mBinding.tvConfirm.setOnClickListener(this); + + } + + private void commit(String desc, String introduction) { + + if (TextUtils.isEmpty(desc)) { +// Toast.makeText(this, "主题不能为空", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("主题不能为空"); + return; + } + + if (TextUtils.isEmpty(introduction)) { + introduction = ""; + } +// if (TextUtils.isEmpty(introduction)) { +// Toast.makeText(this, "介绍不能为空", Toast.LENGTH_SHORT).show(); +// return; +// } + + RoomInfo info = AvRoomDataManager.get().mCurrentRoomInfo; + if (info == null) return; + + RoomSettingModel roomSettingModel = new RoomSettingModel(); + long currentUid = AuthModel.get().getCurrentUid(); + String ticket = AuthModel.get().getTicket(); + if (AvRoomDataManager.get().isRoomOwner()) { + mDialogManager.showProgressDialog(this); + Disposable disposable = roomSettingModel.updateRoomInfo(info.title, desc, introduction, info.roomPwd, info.getRoomTag(), info.tagId, currentUid, + ticket, info.isHasAnimationEffect(), info.getAudioQuality(), info.getLimitType(),info.isPureMode()) + .subscribe(this); + + mDisposable.add(disposable); + + } else if (AvRoomDataManager.get().isRoomAdmin()) { + mDialogManager.showProgressDialog(this); + Disposable disposable = roomSettingModel.updateByAdmin(info.getUid(), info.title, desc, introduction, info.roomPwd, info.getRoomTag(), info.tagId, currentUid, + ticket, info.isHasAnimationEffect(), info.getAudioQuality(),info.isPureMode()) + .subscribe(this); + + mDisposable.add(disposable); + } + + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.tv_confirm: + commit(mBinding.etTitle.getText().toString().trim(), + mBinding.etDesc.getText().toString().trim()); + break; + } + + } + + @Override + public void accept(RoomInfo roomInfo, Throwable throwable) throws Exception { + mDialogManager.dismissDialog(); + + if (throwable != null) { +// Toast.makeText(this, "设置失败", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("设置失败"); + } else { + Intent intent = new Intent(); + Bundle bundle = new Bundle(); + bundle.putSerializable(ROOM_TITLE_EDIT_REQUEST_RESULT, roomInfo); + intent.putExtras(bundle); + setResult(RESULT_OK, intent); + finish(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mDialogManager.dismissDialog(); + mDisposable.clear(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListAdapter.java new file mode 100644 index 000000000..4f70f59e0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListAdapter.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.avroom.adapter; + +import com.yizhuan.xchat_android_library.list.ArrayListAdapter; +import com.yizhuan.xchat_android_library.list.ListItem; + +import java.util.List; + +/** + * Created by chenran on 2017/8/9. + */ + +public class AuctionListAdapter extends ArrayListAdapter{ + public static final int VIEW_TYPE_COUNT = 5;//列表有4种类型 + + public static final int VIEW_TYPE_WEEK_ITEM = 0;//周榜 + public static final int VIEW_TYPE_TOTAL_ITEM = 1;//总榜 + public static final int VIEW_TYPE_EMPTY = 2;//空内容 + public static final int VIEW_TYPE_WEEK_HEADER = 3;//周榜header + public static final int VIEW_TYPE_TOTAL_HEADER = 4;//总榜header + + + private List items = getItems(); + + public void clear(int except) { + if (except >= 0 && except < items.size()) { + ListItem item = items.get(except); + items.clear(); + items.add(item); + } + } + + @Override + public int getViewTypeCount() { + return VIEW_TYPE_COUNT; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListEmptyItem.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListEmptyItem.java new file mode 100644 index 000000000..d88bb3e44 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListEmptyItem.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.list.BaseGroupItem; +import com.yizhuan.xchat_android_library.list.ViewHolder; + +/** + * Created by chenran on 2017/8/9. + */ + +public class AuctionListEmptyItem extends BaseGroupItem{ + + public AuctionListEmptyItem(Context context, int viewType) { + super(context, viewType); + } + + @Override + public ViewHolder createViewHolder(ViewGroup group) { + View view = LayoutInflater.from(getContext()).inflate(R.layout.list_item_auction_empty, null); + AuctionListEmptyItem.AuctionListEmptyHolder holder = new AuctionListEmptyItem.AuctionListEmptyHolder(view); + return holder; + } + + @Override + public void updateHolder(ViewHolder holder, int groupPos, int childPos) { + + } + + private static class AuctionListEmptyHolder extends ViewHolder { + private TextView textView; + public AuctionListEmptyHolder(View itemView) { + super(itemView); + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListHeaderItem.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListHeaderItem.java new file mode 100644 index 000000000..b4bd0d880 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListHeaderItem.java @@ -0,0 +1,48 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.list.BaseGroupItem; +import com.yizhuan.xchat_android_library.list.ViewHolder; + +/** + * Created by chenran on 2017/8/9. + */ + +public class AuctionListHeaderItem extends BaseGroupItem{ + public AuctionListHeaderItem(Context context, int viewType) { + super(context, viewType); + } + + @Override + public ViewHolder createViewHolder(ViewGroup group) { + View view = LayoutInflater.from(getContext()).inflate(R.layout.list_item_auction_header, null); + AuctionListHeaderItem.AuctionListHeaderHolder holder = new AuctionListHeaderItem.AuctionListHeaderHolder(view); + return holder; + } + + @Override + public void updateHolder(ViewHolder holder, int groupPos, int childPos) { + AuctionListHeaderItem.AuctionListHeaderHolder auctionListHolder = (AuctionListHeaderItem.AuctionListHeaderHolder) holder; + if (auctionListHolder != null) { + if (getViewType() == AuctionListAdapter.VIEW_TYPE_WEEK_HEADER) { + auctionListHolder.image.setImageResource(R.drawable.icon_week_auction_list); + } else { + auctionListHolder.image.setImageResource(R.drawable.icon_total_auction_list); + } + } + } + + private static class AuctionListHeaderHolder extends ViewHolder { + private ImageView image; + public AuctionListHeaderHolder(View itemView) { + super(itemView); + image = (ImageView) itemView.findViewById(R.id.auction_list_header); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListItem.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListItem.java new file mode 100644 index 000000000..a59ed5a20 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/AuctionListItem.java @@ -0,0 +1,123 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.auction.bean.AuctionListUserInfo; +import com.yizhuan.xchat_android_library.list.BaseGroupItem; +import com.yizhuan.xchat_android_library.list.ViewHolder; + +/** + * Created by chenran on 2017/8/9. + */ + +public class AuctionListItem extends BaseGroupItem implements View.OnClickListener{ + private AuctionListUserInfo auctionListUserInfo; + private OnAuctionListItemClick onAuctionListItemClick; + private int position; + + public AuctionListItem(Context context, int viewType, AuctionListUserInfo auctionListUserInfo, int position) { + super(context, viewType); + this.auctionListUserInfo = auctionListUserInfo; + this.position = position; + } + + public void setOnAuctionListItemClick(OnAuctionListItemClick onAuctionListItemClick) { + this.onAuctionListItemClick = onAuctionListItemClick; + } + + @Override + public ViewHolder createViewHolder(ViewGroup group) { + View view = LayoutInflater.from(getContext()).inflate(R.layout.list_item_auction_list, null); + AuctionListHolder holder = new AuctionListHolder(view); + return holder; + } + + @Override + public void updateHolder(ViewHolder holder, int groupPos, int childPos) { + AuctionListHolder auctionListHolder = (AuctionListHolder) holder; + if (auctionListHolder != null) { + auctionListHolder.nick.setText(auctionListUserInfo.getNick()); + auctionListHolder.coinText.setText(auctionListUserInfo.getPrice() + ""); + auctionListHolder.avatar.setOnClickListener(this); + ImageLoadUtils.loadAvatar(getContext(), auctionListUserInfo.getAvatar(), auctionListHolder.avatar); + Drawable drawable; + if (auctionListUserInfo.getGender() == 1) { + Drawable drawMan = getContext().getResources().getDrawable(R.drawable.ic_male); + drawable = drawMan; + } else { + Drawable drawFemale = getContext().getResources().getDrawable(R.drawable.ic_female); + drawable = drawFemale; + } + auctionListHolder.nick.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); + + if (getViewType() == AuctionListAdapter.VIEW_TYPE_WEEK_ITEM) { + if (position <= 2) { + auctionListHolder.numberText.setVisibility(View.GONE); + auctionListHolder.numberImage.setVisibility(View.VISIBLE); + if (position == 0) { + auctionListHolder.numberImage.setImageResource(R.drawable.icon_auction_week_list_first); + } else if (position == 1) { + auctionListHolder.numberImage.setImageResource(R.drawable.icon_auction_week_list_second); + } else { + auctionListHolder.numberImage.setImageResource(R.drawable.icon_auction_week_list_third); + } + } else { + auctionListHolder.numberText.setVisibility(View.VISIBLE); + auctionListHolder.numberImage.setVisibility(View.GONE); + auctionListHolder.numberText.setText("NO."+(position+1)); + } + } else { + auctionListHolder.numberText.setVisibility(View.VISIBLE); + auctionListHolder.numberImage.setVisibility(View.GONE); + auctionListHolder.numberText.setText("NO."+(position + 1)); + if (position <= 2) { + auctionListHolder.numberText.setTextColor(0xffeecb7f); + } else { + auctionListHolder.numberText.setTextColor(Color.WHITE); + } + } + } + } + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public void onClick(View v) { + if(onAuctionListItemClick != null) { + onAuctionListItemClick.onAuctionListItemClick(auctionListUserInfo); + } + } + + private static class AuctionListHolder extends ViewHolder { + private ImageView numberImage; + private TextView numberText; + private TextView nick; + private TextView coinText; + private CircleImageView avatar; + public AuctionListHolder(View itemView) { + super(itemView); + numberImage = (ImageView) itemView.findViewById(R.id.auction_number_image); + numberText = (TextView) itemView.findViewById(R.id.auction_number_text); + nick = (TextView) itemView.findViewById(R.id.nick); + avatar = (CircleImageView) itemView.findViewById(R.id.avatar); + coinText = (TextView) itemView.findViewById(R.id.coin_text); + } + } + + public interface OnAuctionListItemClick { + void onAuctionListItemClick(AuctionListUserInfo auctionListUserInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/BaseMicroViewAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/BaseMicroViewAdapter.java new file mode 100644 index 000000000..1a6edf2fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/BaseMicroViewAdapter.java @@ -0,0 +1,292 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.ViewAdapter; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +/** + * @author xiaoyu + * @date 2017/12/18 + */ + +public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter { + // 麦位类型;用于左右滑动切换房间时判断是否需要更换麦位adapter + public static final String MICRO_TYPE_CP = "cp"; + public static final String MICRO_TYPE_KTV = "ktv"; + public static final String MICRO_TYPE_NORMAL = "normal"; + + private OnMicroItemClickListener onMicroItemClickListener; + + protected Context context; + private int mTagHeight; + + public BaseMicroViewAdapter(Context context) { + this.context = context; + mTagHeight = context.getResources().getDimensionPixelOffset(R.dimen.tag_height); + } + + public void setOnMicroItemClickListener(OnMicroItemClickListener onMicroItemClickListener) { + this.onMicroItemClickListener = onMicroItemClickListener; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(position - 1); + if (roomQueueInfo == null) return; + NormalMicroViewHolder holder = (NormalMicroViewHolder) viewHolder; + holder.bind(roomQueueInfo, position - 1); + } + + public abstract String microType(); + + @Override + public int getItemCount() { + return 9; + } + + protected static final int TYPE_KING = 2; + protected static final int TYPE_BOSS = 1; + protected static final int TYPE_NORMAL = 0; + protected static final int TYPE_INVALID = -2; + + @Override + public int getItemViewType(int position) { + return (position == 0) ? TYPE_BOSS : TYPE_NORMAL; + } + + @Override + public long getItemId(int position) { + return position; + } + + public class NormalMicroViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView tvNick; + ImageView ivUpImage; + ImageView ivLockImage; + ImageView ivMuteImage; + ImageView ivHeadWear; + CircleImageView ivAvatar; + ImageView ivHalo; + TextView tvNumber; + + TextView tvCharmValue; + View viewCenterOfCharm; + View llCharmClick; + + NormalMicroViewHolder(View itemView) { + super(itemView); + ivHalo = itemView.findViewById(R.id.iv_halo); + ivUpImage = itemView.findViewById(R.id.up_image); + ivLockImage = itemView.findViewById(R.id.lock_image); + ivMuteImage = itemView.findViewById(R.id.mute_image); + ivAvatar = itemView.findViewById(R.id.avatar); + ivHeadWear = itemView.findViewById(R.id.iv_head_wear); + tvNick = itemView.findViewById(R.id.nick); + tvNumber = itemView.findViewById(R.id.tv_number); + + ivUpImage.setOnClickListener(this); + ivLockImage.setOnClickListener(this); + ivAvatar.setOnClickListener(this); + } + + RoomQueueInfo info; + int position = TYPE_INVALID; + + public void clear() { + info = null; + position = TYPE_INVALID; + ivHalo.setBackground(null); + ivHalo.clearAnimation(); + ivHeadWear.setImageDrawable(null); + + ivUpImage.setVisibility(View.VISIBLE); + ivLockImage.setVisibility(View.GONE); + ivMuteImage.setVisibility(View.GONE); + ivAvatar.setVisibility(View.GONE); + tvNick.setVisibility(View.INVISIBLE); + } + + void bind(RoomQueueInfo info, int position) { + this.info = info; + this.position = position; + RoomMicInfo roomMicInfo = info.mRoomMicInfo; + ChatRoomMember chatRoomMember = info.mChatRoomMember; + // 清除动画 + ivHalo.setBackground(null); + ivHalo.clearAnimation(); + // 清除头饰 + ivHeadWear.setImageDrawable(null); + ivHeadWear.clearAnimation(); + GlideApp.with(context).clear(ivHeadWear); + //设置一个tag,用于解决第一次进房间,空坑位显示头饰的问题 + ivHeadWear.setTag(R.id.mic_item_head_wear, null); + if (roomMicInfo == null) { + ivUpImage.setVisibility(View.VISIBLE); + ivLockImage.setVisibility(View.GONE); + ivMuteImage.setVisibility(View.GONE); + ivAvatar.setVisibility(View.GONE); + setDefalutText(position); + return; + } + + + //显示,先展示人,无视坑的锁 + if (chatRoomMember != null) { + ivLockImage.setVisibility(View.GONE); + ivMuteImage.setVisibility(roomMicInfo.isMicMute() ? View.VISIBLE : View.GONE); + + if (!TextUtils.isEmpty(chatRoomMember.getAccount()) && Long.valueOf(chatRoomMember.getAccount()) > 0) { + ivUpImage.setVisibility(View.GONE); + ivAvatar.setVisibility(View.VISIBLE); +// tvNick.setText(StringUtil.removeBlanks(chatRoomMember.getNick())); +// tvNick.setTextColor(context.getResources().getColor(R.color.white)); +// if (AvRoomDataManager.get().isOpenPKMode()) { +// ViewAdapter.setViewBackground(tvNick, R.color.black_transparent_20, 50, 0, 0); +// } else { +// int nickBgColor = context.getResources().getColor( +// info.gender == 1 ? R.color.color_male_16AEFD : R.color.color_female_FE3F77); +// ViewAdapter.setViewBackground(tvNick, nickBgColor, 50, 0, 0); +// } + setSelectText(position, chatRoomMember.getNick(), info.gender); + ImageLoadUtils.loadAvatar(BasicConfig.INSTANCE.getAppContext(), chatRoomMember.getAvatar(), ivAvatar); + // 加载贵族 + updateNobleView(chatRoomMember); + } else { + ivUpImage.setVisibility(View.VISIBLE); + ivAvatar.setVisibility(View.GONE); + setDefalutText(position); + } + } else { + //锁坑 + ivMuteImage.setVisibility(roomMicInfo.isMicMute() ? View.VISIBLE : View.GONE); + if (roomMicInfo.isMicLock()) { + ivUpImage.setVisibility(View.GONE); + ivLockImage.setVisibility(View.VISIBLE); + ivAvatar.setVisibility(View.GONE); + } else { + ivUpImage.setVisibility(View.VISIBLE); + ivAvatar.setVisibility(View.GONE); + ivLockImage.setVisibility(View.GONE); + } + setDefalutText(position); + } + + + } + + protected void setDefalutText(int index) { + tvNick.setTextColor(context.getResources().getColor(R.color.white_transparent_30)); +// ViewAdapter.setViewBackground( +// tvNick, context.getResources().getColor(R.color.white_transparent_12), 50, 0, 0); +// tvNick.setText(String.format(context.getString(R.string.number_mic_position), index + 1)); + tvNick.setText("号麦位"); + + if (tvNumber != null) { + tvNumber.setBackgroundResource(R.drawable.icon_bg_number_default); + tvNumber.setTextColor(context.getResources().getColor(R.color.white_transparent_30)); + tvNumber.setText(String.valueOf(index + 1)); + } + + } + + protected void setSelectText(int index, String nick, int gender) { + tvNick.setText(StringUtil.removeBlanks(nick)); + tvNick.setTextColor(context.getResources().getColor(R.color.white)); + + if (tvNumber != null) { +// tvNumber.setBackgroundResource(gender == 1 ? R.drawable.bg_number_male : R.drawable.bg_number_female); +// tvNumber.setTextColor(context.getResources().getColor(R.color.white)); +// tvNumber.setText(String.valueOf(index + 1)); + + if (AvRoomDataManager.get().isOpenPKMode()) { // pk模式不加性别背景 + tvNumber.setBackgroundResource(R.drawable.icon_bg_number_default); + tvNumber.setTextColor(context.getResources().getColor(R.color.white_transparent_30)); + } else { + tvNumber.setBackgroundResource(gender == 1 ? R.drawable.bg_number_male : R.drawable.bg_number_female); + tvNumber.setTextColor(context.getResources().getColor(R.color.white)); + } + tvNumber.setText(String.valueOf(index + 1)); + } + + } + + private void updateNobleView(ChatRoomMember chatRoomMember) { + String nobleHeadWear = (String) NobleUtil.getResource(NobleResourceType.KEY_HEAD_WEAR, chatRoomMember); + String headWear=NobleUtil.getHeadResource(HeadWearInfo.PIC, chatRoomMember); + if (!TextUtils.isEmpty(headWear)) { + // 头饰 + ivHeadWear.setVisibility(View.VISIBLE); + ivHeadWear.setTag(R.id.mic_item_head_wear, headWear); + NobleUtil.loadMicHeadWear(headWear, ivHeadWear, R.id.mic_item_head_wear, headWear); + } else if (!TextUtils.isEmpty(nobleHeadWear)) { + // 头饰 + NobleUtil.loadResource(nobleHeadWear, ivHeadWear); + } + } + + @Override + public void onClick(View v) { + if (info == null || position == TYPE_INVALID || + onMicroItemClickListener == null) return; + if (v.getId() == R.id.up_image || v.getId() == R.id.lock_image) { + onMicroItemClickListener.onUpMicBtnClick(position, info.mChatRoomMember); + } else if (v.getId() == R.id.lock_image) { + onMicroItemClickListener.onLockBtnClick(position); + } else if (v.getId() == R.id.avatar) { + onMicroItemClickListener.onAvatarBtnClick(position); + } else if (v.getId() == R.id.tv_room_desc || v.getId() == R.id.tv_room_type + || v.getId() == R.id.iv_room_can_edit) { + onMicroItemClickListener.onRoomSettingsClick(); + } + } + } + + public void clear(NormalMicroViewHolder holder) { + holder.clear(); + } + + public abstract void bindToRecyclerView(RecyclerView recyclerView); + public abstract void dispose(); + + @Override + public void onDetachedFromRecyclerView(RecyclerView recyclerView) { + onMicroItemClickListener = null; + super.onDetachedFromRecyclerView(recyclerView); + } + + public void setBossViewGender(TextView tvNick, boolean isMale) { + + if (AvRoomDataManager.get().isOpenPKMode()) { // pk模式不加性别背景 + tvNick.setCompoundDrawablePadding(4); + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } else { + if (isMale) { + tvNick.setCompoundDrawablePadding(4); + tvNick.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_male, 0, 0, 0); + } else { + tvNick.setCompoundDrawablePadding(4); + tvNick.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_female, 0, 0, 0); + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/CpMicroViewAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/CpMicroViewAdapter.java new file mode 100644 index 000000000..9bae1eca2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/CpMicroViewAdapter.java @@ -0,0 +1,138 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; + +public class CpMicroViewAdapter extends BaseMicroViewAdapter { + + + public CpMicroViewAdapter(Context context) { + super(context); + } + + @Override + public String microType() { + return BaseMicroViewAdapter.MICRO_TYPE_CP; + } + + @Override + public void bindToRecyclerView(RecyclerView recyclerView) { + GridLayoutManager layoutManager = new GridLayoutManager(context, 3); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 0) { + return 2; + } else { + return 1; + } + } + }); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(this); + } + + @Override + public void dispose() { + + } + + @Override + public int getItemCount() { + return 2; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View item; + if (viewType == TYPE_BOSS) { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.item_cp_boss_micro, parent, false); + return new CpBossMicroViewHolder(item); + } else { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_micro_cp, parent, false); + return new CpMicroViewHolder(item); + } + } + + public class CpMicroViewHolder extends NormalMicroViewHolder { + CpMicroViewHolder(View itemView) { + super(itemView); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); +// ViewAdapter.setViewBackground( +// tvNick, context.getResources().getColor(R.color.black_transparent_20), 50, 0, 0); + } + + @Override + protected void setDefalutText(int index) { + super.setDefalutText(index); + tvNick.setText("未上座"); + } + } + + public class CpBossMicroViewHolder extends NormalMicroViewHolder { + /** + * 主席位特有 + */ + TextView tvRoomType; + TextView tvRoomDesc; + View ivRoomCanEdit; + + CpBossMicroViewHolder(View itemView) { + super(itemView); +// tvRoomType = itemView.findViewById(R.id.tv_room_type); +// tvRoomDesc = itemView.findViewById(R.id.tv_room_desc); +// ivRoomCanEdit = itemView.findViewById(R.id.iv_room_can_edit); +// tvRoomDesc.setOnClickListener(this); +// tvRoomType.setOnClickListener(this); +// ivRoomCanEdit.setOnClickListener(this); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); +// ViewAdapter.setViewBackground( +// tvNick, context.getResources().getColor(R.color.black_transparent_20), 50, 0, 0); + // onRoomInfoUpdate(); +// tvNick.setBackgroundColor(context.getResources().getColor(R.color.transparent)); +// tvNick.setTextColor(context.getResources().getColor(R.color.white)); +// if (AvRoomDataManager.get().isManager()) { +// ivRoomCanEdit.setVisibility(View.VISIBLE); +// } else { +// ivRoomCanEdit.setVisibility(View.GONE); +// } + } + @Override + protected void setDefalutText(int index) { + super.setDefalutText(index); + tvNick.setText("未上座"); + } + + @Override + public void clear() { + super.clear(); + } + + @Override + public void onClick(View v) { + super.onClick(v); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/HomePartyPageAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/HomePartyPageAdapter.java new file mode 100644 index 000000000..8b0462a91 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/HomePartyPageAdapter.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public class HomePartyPageAdapter extends FragmentPagerAdapter { + + private List mFragmentList; + + public HomePartyPageAdapter(FragmentManager fm, List fragmentList) { + super(fm); + mFragmentList = fragmentList; + } + + @Override + public Fragment getItem(int position) { + return (mFragmentList == null || mFragmentList.size() == 0 ? null : mFragmentList.get(position)); + } + + @Override + public int getCount() { + return mFragmentList == null ? 0 : mFragmentList.size(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/InviteFriendListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/InviteFriendListAdapter.java new file mode 100644 index 000000000..4dd47ae00 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/InviteFriendListAdapter.java @@ -0,0 +1,132 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.app.Activity; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.CheckBox; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.public_chat_hall.bean.PublicChatHallFriendInfo; +import com.yizhuan.erban.public_chat_hall.event.AitFriendEvent; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; + +public class InviteFriendListAdapter extends BaseQuickAdapter { + + private Activity context; + + public InviteFriendListAdapter(Activity context) { + super(R.layout.item_public_chat_hall_friend_list); + this.context = context; + } + + private OnItemClickListener onItemClickListener; + + public interface OnItemClickListener { + void sendListener(UserInfo attentionInfo); + } + + public void setRylListener(OnItemClickListener onClickListener) { + onItemClickListener = onClickListener; + } + + @Override + protected void convert(BaseViewHolder helper, PublicChatHallFriendInfo pchFriendInfo) { + if (pchFriendInfo == null) return; + final UserInfo item = pchFriendInfo.getUserInfo(); + + CheckBox cbFriend = helper.getView(R.id.cb_friend); + + helper.setText(R.id.tv_userName, item.getNick()) + .setText(R.id.tv_user_desc, item.getUserDesc() != null ? + item.getUserDesc() + : helper.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) + .setVisible(R.id.view_line, helper.getLayoutPosition() != getItemCount() - 1) + ; + + NobleAvatarView nobleAvatarView = helper.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(47, 70, 13); + nobleAvatarView.setData(item.getAvatar(), item.getNobleUsers()); + + + AppCompatImageView ivGender = helper.getView(R.id.iv_gender); + if (item.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + AppCompatImageView ivNobleLevel = helper.getView(R.id.iv_noble_level); + if (item.getNobleUsers() != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(item.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + AppCompatImageView ivUserLevel = helper.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = helper.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + + cbFriend.setChecked(pchFriendInfo.isSelected()); +// cbFriend.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// onSelect(cbFriend, pchFriendInfo, item); +// } +// }); +// cbFriend.setOnCheckedChangeListener((buttonView, isChecked) -> { +// +// }); + helper.getView(R.id.container).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onSelect(cbFriend, pchFriendInfo, item); + } + }); + + } + + private void onSelect(CheckBox cbFriend, PublicChatHallFriendInfo pchFriendInfo, UserInfo item) { + int count = 0; + for (PublicChatHallFriendInfo publicChatHallFriendInfo : getData()) { + if (publicChatHallFriendInfo.isSelected()) { + count++; + } + } + if (count == 20 && !pchFriendInfo.isSelected()) { + SingleToastUtil.showToast("最多只能选择20个好友哦"); + return; + } + cbFriend.setChecked(!cbFriend.isChecked()); + pchFriendInfo.setSelected(!pchFriendInfo.isSelected()); + EventBus.getDefault().post(new AitFriendEvent() + .setType(pchFriendInfo.isSelected() ? AitFriendEvent.TYPE_ADD : AitFriendEvent.TYTPE_REMOVE) + .setUid(String.valueOf(item.getUid())) + .setNick(item.getNick())); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/KtvMicroViewAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/KtvMicroViewAdapter.java new file mode 100644 index 000000000..04e052dec --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/KtvMicroViewAdapter.java @@ -0,0 +1,189 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.ktv.KtvMusicManager; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.ktv.event.MusicCountEvent; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.utils.StringUtils; +import com.yizhuan.xchat_android_library.rxbus.RxBus; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; + +/** + * @author xiaoyu + * @date 2017/12/18 + */ + +public class KtvMicroViewAdapter extends BaseMicroViewAdapter { + + private int[] realPositions = {1, 5, 2, 6, 0, 3, 7, 4, 8}; + + private ViewGroup.LayoutParams microParams; + private ViewGroup.LayoutParams bossParams; + + public KtvMicroViewAdapter(Context context) { + super(context); + int itemWidth = (int) (ScreenUtil.screenWidth * 0.1875); + microParams = new ViewGroup.LayoutParams(itemWidth, UIUtil.dip2px(context, 80)); + bossParams = new ViewGroup.LayoutParams(ScreenUtil.screenWidth / 4, UIUtil.dip2px(context, 160)); + disposables.add(RxBus.get().toFlowable(MusicCountEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(musicCountEvent -> notifyDataSetChanged())); + } + + /** + * Set LayoutManager and bind this to {@link RecyclerView} + */ + @Override + public void bindToRecyclerView(RecyclerView recyclerView) { + GridLayoutManager layoutManager = new GridLayoutManager(context, 2); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return position == 4 ? 2 : 1; + } + }); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(this); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()) + .inflate(viewType == TYPE_BOSS ? R.layout.item_ktv_boss_micro : R.layout.list_item_ktv_micro, parent, false); + return new KtvMicroViewHolder(item, viewType == TYPE_BOSS); + + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) { + int realPosition = realPositions[position]; + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(realPosition - 1); + viewHolder.itemView.setLayoutParams(position == 4 ? bossParams : microParams); + if (roomQueueInfo == null) return; + NormalMicroViewHolder holder = (NormalMicroViewHolder) viewHolder; + holder.bind(roomQueueInfo, realPosition - 1); + } + + @Override + public String microType() { + return BaseMicroViewAdapter.MICRO_TYPE_KTV; + } + + @Override + public int getItemViewType(int position) { + return (position == 4) ? TYPE_BOSS : TYPE_NORMAL; + } + + class KtvMicroViewHolder extends NormalMicroViewHolder { + + ImageView ivSinger; + TextView tvPkMark; + boolean mIsBoss; + KtvMicroViewHolder(View itemView, boolean isBoss) { + super(itemView); + ivSinger = itemView.findViewById(R.id.iv_singer); + tvPkMark = (TextView) itemView.findViewById(R.id.tv_pk_mark); + mIsBoss = isBoss; + + } + + @Override + public void clear() { + super.clear(); + ivSinger.setVisibility(View.GONE); + tvPkMark.setVisibility(View.GONE); + } + + @Override + protected void setDefalutText(int index) { + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + if (mIsBoss) { + tvNick.setTextColor(context.getResources().getColor(R.color.white_transparent_30)); + tvNick.setText("未上座"); + } else + super.setDefalutText(index); + } + + @Override + protected void setSelectText(int index, String nick, int gender) { + super.setSelectText(index, nick, gender); + + if (mIsBoss) { + setBossViewGender(tvNick, gender == 1); + } else + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); + + if (info.groupType == PKTeamInfo.TEAM_RED) { + tvPkMark.setVisibility(View.VISIBLE); + tvPkMark.setBackgroundResource(R.drawable.shape_pk_mic_queue_mark_red); + tvPkMark.setText("红队"); + ivSinger.setVisibility(View.GONE); + if (isSinging(info.mChatRoomMember)) { + tvPkMark.setCompoundDrawablesWithIntrinsicBounds(tvPkMark.getResources().getDrawable(R.drawable.ktv_pk_singing_mark), null, null, null); + } else { + tvPkMark.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + } + } else if (info.groupType == PKTeamInfo.TEAM_BLUE) { + tvPkMark.setVisibility(View.VISIBLE); + tvPkMark.setBackgroundResource(R.drawable.shape_pk_mic_queue_mark_blue); + tvPkMark.setText("蓝队"); + ivSinger.setVisibility(View.GONE); + if (isSinging(info.mChatRoomMember)) { + tvPkMark.setCompoundDrawablesWithIntrinsicBounds(tvPkMark.getResources().getDrawable(R.drawable.ktv_pk_singing_mark), null, null, null); + } else { + tvPkMark.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + } + } else { + tvPkMark.setVisibility(View.GONE); + if (isSinging(info.mChatRoomMember)) { + ivSinger.setVisibility(View.VISIBLE); + } else { + ivSinger.setVisibility(View.GONE); + } + } + + } + + private boolean isSinging(ChatRoomMember chatRoomMember) { + return chatRoomMember != null && KtvMusicManager.INSTANCE.getCurrMusic().getUid() == StringUtils.toLong(chatRoomMember.getAccount()); + } + } + + + private CompositeDisposable disposables = new CompositeDisposable(); + + @Override + public void onDetachedFromRecyclerView(RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + disposables.dispose(); + } + + @Override + public void dispose(){ + disposables.dispose(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicQueueAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicQueueAdapter.java new file mode 100644 index 000000000..2eac4400e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicQueueAdapter.java @@ -0,0 +1,82 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.graphics.drawable.GradientDrawable; +import android.support.v7.widget.AppCompatImageView; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.QueuingMicMemeberInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/12/14 + */ +public class MicQueueAdapter extends BaseQuickAdapter { + + public MicQueueAdapter(List list) { + super(R.layout.item_mic_queue_list, list); + } + + @Override + protected void convert(BaseViewHolder helper, final QueuingMicMemeberInfo item) { + helper.setText(R.id.tv_userName, item.getNick()) + .setText(R.id.tv_no, (helper.getAdapterPosition() + 1) + ""); + + + CircleImageView ivAvatar = helper.getView(R.id.iv_avatar_view); + GlideApp.with(ivAvatar.getContext()) + .load(item.getAvatar()) + .placeholder(R.drawable.default_avatar) + .into(ivAvatar); + + AppCompatImageView ivGender = helper.getView(R.id.iv_gender); + if (item.getGender() == UserInfo.GENDER_MALE) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + TextView tvOpt = helper.getView(R.id.tv_opt); + GradientDrawable attentionBg = (GradientDrawable) tvOpt.getBackground(); + if (AvRoomDataManager.get().isManager()) { + tvOpt.setText("抱上麦"); + tvOpt.setTextColor(mContext.getResources().getColor(R.color.color_white)); + attentionBg.setColor(mContext.getResources().getColor(R.color.appColor)); + final int itemPos = helper.getAdapterPosition(); + tvOpt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onUpMicListener != null) { + onUpMicListener.onUpMic(item, itemPos); + } + } + }); + } else { + tvOpt.setText("排麦中"); + tvOpt.setTextColor(mContext.getResources().getColor(R.color.appColor)); + attentionBg.setColor(mContext.getResources().getColor(R.color.color_f0f0f0)); + tvOpt.setOnClickListener(null); + } + + } + + public interface OnUpMicListener { + void onUpMic(QueuingMicMemeberInfo uid, int itemPos); + } + + private OnUpMicListener onUpMicListener; + + public void setOnUpMicListener(OnUpMicListener onUpMicListener) { + this.onUpMicListener = onUpMicListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicroViewAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicroViewAdapter.java new file mode 100644 index 000000000..efa839b3e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/MicroViewAdapter.java @@ -0,0 +1,460 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.arch.lifecycle.Observer; +import android.content.Context; +import android.graphics.drawable.BitmapDrawable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.bean.GiftValueData; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueFormat; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +/** + * @author xiaoyu + * @date 2017/12/18 + */ + +public class MicroViewAdapter extends BaseMicroViewAdapter { + + public MicroViewAdapter(Context context) { + super(context); + } + + /** + * Set LayoutManager and bind this to RecyclerView + */ + @Override + public void bindToRecyclerView(RecyclerView recyclerView) { + GridLayoutManager layoutManager = new GridLayoutManager(context, 4); + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 0) { + return 4; + } else { + return 1; + } + } + }); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(this); + } + + @Override + public void dispose() { + + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item; + if (viewType == TYPE_BOSS) { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.item_boss_micro, parent, false); + return new BossMicroViewHolder(item); + } else if (viewType == TYPE_NORMAL) { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_micro, parent, false); + return new GiftValueViewHolder(item); + } else { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_micro_king, parent, false); + return new MicroViewHolder(item); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(position - 1); + if (roomQueueInfo == null) return; + NormalMicroViewHolder holder = (NormalMicroViewHolder) viewHolder; + holder.bind(roomQueueInfo, position - 1); + } + + @Override + public String microType() { + return BaseMicroViewAdapter.MICRO_TYPE_NORMAL; + } + + @Override + public int getItemViewType(int position) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (position == 0) return TYPE_BOSS; + + // 新秀房,牌照房展示老板位 + if (roomInfo != null && (roomInfo.getIsPermitRoom() == 1 || roomInfo.getIsPermitRoom() == 3) && position == 8) + return TYPE_KING; + return TYPE_NORMAL; + } + + /** + * 增加礼物值展示 + */ + class GiftValueViewHolder extends BasicMicroViewHolder { + + TextView tvCharmValue; + View viewCenterOfCharm; + View llCharmClick; + View clParentGiftValue; + + GiftValueViewHolder(View itemView) { + super(itemView); + tvCharmValue = itemView.findViewById(R.id.tv_charm_value); + viewCenterOfCharm = itemView.findViewById(R.id.view_center_of_charm); + llCharmClick = itemView.findViewById(R.id.ll_charm_click); + clParentGiftValue = itemView.findViewById(R.id.cl_parent_gift_value); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); + //增加非空判断,防止被非法继承 + if (isNpe()) { + return; + } + if (info == null) { + return; + } + GiftValueData charmData = info.giftValueData; + if (charmData == null) { + return; + } + if (!AvRoomDataManager.get().isShowGiftValue()) { + clParentGiftValue.setVisibility(View.GONE); + return; + } + clParentGiftValue.setVisibility(View.VISIBLE); + charmData.removeObserver(); + //控制是否展示礼物值 + Observer showObserver = showValue -> + clParentGiftValue.setVisibility(showValue != null && showValue ? View.VISIBLE : View.GONE); + charmData.getLdShow().observeForever(showObserver); + charmData.setShowObserver(showObserver); + //礼物值的增加显示 + Observer valueObserver = longValue -> { + if (longValue == null) { + return; + } + if (isNpe()) { + return; + } + tvCharmValue.setText(GiftValueFormat.longToString(longValue)); + llCharmClick.setOnLongClickListener(v -> { + if (longValue < 100 * 10000L) { + //小于100万,不需要长按弹框 + return false; + } + View contentView = View.inflate(context, R.layout.popwindow_mic_charm_value, null); + SuperTextView stv_mic_charm_value = contentView.findViewById(R.id.stv_mic_charm_value); + String gvString; + if (longValue >= 10000 * 10000L) { + gvString = "99999999+"; + } else { + gvString = String.valueOf(longValue); + } + stv_mic_charm_value.setText(gvString); + PopupWindow window = new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, true); + //设置透明度 + ActivityUtil.addAlpha(context, 0.7f); + window.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + window.setOutsideTouchable(true); + window.setFocusable(true); + window.setBackgroundDrawable(new BitmapDrawable()); + int width = window.getContentView().getMeasuredWidth(); + + int[] location = new int[2]; + viewCenterOfCharm.getLocationOnScreen(location); + int showWidth = UIUtil.getScreenWidth(context) - location[0] - UIUtil.dip2px(context, 1); + int offsetX = width / 2; + //以下的处理就是当popWindow靠近屏幕右边的时候,要计算箭头的位置 + if (showWidth < offsetX) { + View iv_center_arrow = contentView.findViewById(R.id.iv_center_arrow); + View iv_move_arrow = contentView.findViewById(R.id.iv_move_arrow); + iv_center_arrow.setVisibility(View.GONE); + iv_move_arrow.setVisibility(View.VISIBLE); + if (iv_move_arrow.getLayoutParams() instanceof RelativeLayout.LayoutParams) { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) iv_move_arrow.getLayoutParams(); + params.leftMargin = width / 2 + offsetX - showWidth - UIUtil.dip2px(context, 6.5f); + } + offsetX = offsetX + offsetX - showWidth + UIUtil.dip2px(context, 2); + } + int offsetY = UIUtil.dip2px(context, 19.5f + 39f); + window.showAsDropDown(viewCenterOfCharm, + -offsetX, -offsetY); + window.setOnDismissListener(() -> ActivityUtil.removeAlpha(context)); + return true; + }); + }; + charmData.getLdValue().observeForever(valueObserver); + charmData.setValueObserver(valueObserver); + } + + private boolean isNpe() { + return tvCharmValue == null || llCharmClick == null || + viewCenterOfCharm == null || clParentGiftValue == null; + } + } + + public class BossMicroViewHolder extends GiftValueViewHolder { + /** + * 主席位特有 + */ + TextView tvRoomType; + TextView tvRoomDesc; + View ivRoomCanEdit; + ImageView ivTag; + TextView tvLabelLeaveMode; + CircleImageView ivLeaveMode; + + BossMicroViewHolder(View itemView) { + super(itemView); + tvRoomType = itemView.findViewById(R.id.tv_room_type); + tvRoomDesc = itemView.findViewById(R.id.tv_room_desc); + ivRoomCanEdit = itemView.findViewById(R.id.iv_room_can_edit); + ivTag = itemView.findViewById(R.id.iv_tag); + tvLabelLeaveMode = itemView.findViewById(R.id.tv_label_leave_mode); + ivLeaveMode = itemView.findViewById(R.id.iv_bg_leave_mode); + tvRoomDesc.setOnClickListener(this); + tvRoomType.setOnClickListener(this); + ivRoomCanEdit.setOnClickListener(this); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); + onRoomInfoUpdate(); + + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) + return; + + // 新版房主位优先判断麦序是否有人,麦序没人再判断是否是离开模式(防止新版展示离开模式,实际麦位有人) + ChatRoomMember chatRoomMember = info.mChatRoomMember; + if (chatRoomMember == null) { + if (roomInfo.isLeaveMode()) { + tvLabelLeaveMode.setVisibility(View.VISIBLE); + ivLeaveMode.setVisibility(View.VISIBLE); + ImageLoadUtils.loadDefaultImage(BasicConfig.INSTANCE.getAppContext(), ivLeaveMode, R.drawable.bg_leave_mode); + + ivAvatar.setVisibility(View.VISIBLE); + ivLockImage.setVisibility(View.INVISIBLE); + ivUpImage.setVisibility(View.INVISIBLE); + + AvRoomDataManager avRoomDataManager = AvRoomDataManager.get(); + ImageLoadUtils.loadAvatar(BasicConfig.INSTANCE.getAppContext(), avRoomDataManager.avatar, ivAvatar); + setSelectText(-1, avRoomDataManager.nick, avRoomDataManager.gender); + + } else { + ivLeaveMode.setVisibility(View.GONE); + tvLabelLeaveMode.setVisibility(View.GONE); + + } + + } else { + ivLeaveMode.setVisibility(View.GONE); + tvLabelLeaveMode.setVisibility(View.GONE); + + } + + tvNick.setBackgroundColor(context.getResources().getColor(R.color.transparent)); + tvNick.setTextColor(context.getResources().getColor(R.color.white)); + if (AvRoomDataManager.get().isManager()) { + ivRoomCanEdit.setVisibility(View.VISIBLE); + } else { + ivRoomCanEdit.setVisibility(View.GONE); + } + + } + + @Override + protected void setDefalutText(int index) { + //重新覆盖掉用户名的逻辑 + tvNick.setText(""); + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + ivTag.setVisibility(View.GONE); + } + + @Override + protected void setSelectText(int index, String nick, int gender) { + super.setSelectText(index, nick, gender); + if (UserModel.get().getCacheLoginUserInfo() != null && + UserModel.get().getCacheLoginUserInfo().getUserInfoSkillVo() != null) { + if (AvRoomDataManager.get().isRoomOwner() && !TextUtils.isEmpty(UserModel.get().getCacheLoginUserInfo().getUserInfoSkillVo().getSkillTag())) { + ImageLoadUtils.loadImage(context, UserModel.get().getCacheLoginUserInfo().getUserInfoSkillVo().getSkillTag(), ivTag); + ivTag.setVisibility(View.VISIBLE); + tvNick.setCompoundDrawablePadding(4); + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } else { + setBossViewGender(tvNick, gender == 1); + ivTag.setVisibility(View.GONE); + } + } + + } + + void onRoomInfoUpdate() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + if (!TextUtils.isEmpty(roomInfo.getRoomDesc())) { + tvRoomDesc.setText(RegexUtil.getPrintableString(roomInfo.getRoomDesc())); + } else { + if (AvRoomDataManager.get().isManager()) { + tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_manager_edit_desc)); + } else { + tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_no_desc)); + } + } + tvRoomType.setText(roomInfo.getRoomTag()); + } + + @Override + public void clear() { + super.clear(); + tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_no_desc)); + tvRoomType.setText("聊天"); + ivTag.setVisibility(View.GONE); + } + + @Override + public void onClick(View v) { + super.onClick(v); + } + } + + + class BasicMicroViewHolder extends NormalMicroViewHolder { + + TextView tvPkMark; + BasicMicroViewHolder(View itemView) { + super(itemView); + tvPkMark = (TextView) itemView.findViewById(R.id.tv_pk_mark); + } + + @Override + public void clear() { + super.clear(); + if (tvPkMark != null) { + tvPkMark.setVisibility(View.GONE); + } + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); + if (tvPkMark == null) { + return; + } + if (info.groupType == PKTeamInfo.TEAM_RED) { + tvPkMark.setVisibility(View.VISIBLE); + tvPkMark.setBackgroundResource(R.drawable.shape_pk_mic_queue_mark_red); + tvPkMark.setText("红队"); + } else if (info.groupType == PKTeamInfo.TEAM_BLUE) { + tvPkMark.setVisibility(View.VISIBLE); + tvPkMark.setBackgroundResource(R.drawable.shape_pk_mic_queue_mark_blue); + tvPkMark.setText("蓝队"); + } else { + tvPkMark.setVisibility(View.GONE); + } + } + } + + public class MicroViewHolder extends GiftValueViewHolder { + + ImageView ivBossChair; + + FrameLayout flKing; + + ImageView ivKing; + + MicroViewHolder(View itemView) { + super(itemView); + ivBossChair = itemView.findViewById(R.id.iv_boss_chair); +// flKing = itemView.findViewById(R.id.fl_king); +// ivKing = itemView.findViewById(R.id.up_image_img); + } + + @Override + void bind(RoomQueueInfo info, int position) { + super.bind(info, position); + ChatRoomMember chatRoomMember = info.mChatRoomMember; + if (rotateAnimation==null){ + rotateAnimation = new RotateAnimation(0, 359, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation.setDuration(3000); + rotateAnimation.setFillAfter(true); + rotateAnimation.setRepeatMode(Animation.RESTART); + rotateAnimation.setInterpolator(new LinearInterpolator()); + rotateAnimation.setRepeatCount(-1); + } + +// ivKing.startAnimation(rotateAnimation); +// boolean canShowKingBack = false; +// +// if (chatRoomMember != null) { +// flKing.setVisibility(View.GONE); +// } else { +// +// // 锁麦,隐藏动销 +// RoomMicInfo roomMicInfo = info.mRoomMicInfo; +// if (roomMicInfo != null) { +// if (roomMicInfo.isMicLock()) { +// flKing.setVisibility(View.GONE); +// } else { +// flKing.setVisibility(View.VISIBLE); +// canShowKingBack = true; +// } +// +// } +// +// } +// +// if (canShowKingBack) { +// ivKing.startAnimation(rotateAnimation); +// ivKing.setVisibility(View.VISIBLE); +// } else { +// rotateAnimation.cancel(); +// ivKing.setAnimation(null); // 为什么置空情况下gone/invisible才生效 +// ivKing.setVisibility(View.INVISIBLE); +// } + + } + + private RotateAnimation rotateAnimation; + + @Override + public void clear() { + super.clear(); + if (rotateAnimation!=null) rotateAnimation.cancel(); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnMicroItemClickListener.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnMicroItemClickListener.java new file mode 100644 index 000000000..31f1d0936 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnMicroItemClickListener.java @@ -0,0 +1,16 @@ +package com.yizhuan.erban.avroom.adapter; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +/** + * Created by lvzebiao on 2018/11/5. + */ +public interface OnMicroItemClickListener { + void onAvatarBtnClick(int position); + + void onUpMicBtnClick(int position, ChatRoomMember chatRoomMember); + + void onLockBtnClick(int position); + + void onRoomSettingsClick(); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnlineUserAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnlineUserAdapter.java new file mode 100644 index 000000000..63b6b07fe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/OnlineUserAdapter.java @@ -0,0 +1,331 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.AppCompatImageView; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.impl.cache.NimUserInfoCache; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.uinfo.constant.GenderEnum; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.ViewAdapter; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.level.UserLevelResourceType; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.disposables.Disposable; + +/** + *

房间在线人数列表 (上麦,房主,游客,管理员)

+ * + * @author Administrator + * @date 2017/12/4 + */ +public class OnlineUserAdapter extends BaseMultiItemQuickAdapter { + + private boolean mIsHomeParty; + private Disposable mDisposable; + private Context context; + + + public OnlineUserAdapter(Context context, boolean isHomeParty) { + super(null); + addItemType(OnlineChatMember.NORMAL, R.layout.list_item_online_user); + addItemType(OnlineChatMember.NOBLE, R.layout.list_item_online_user_noble); + addItemType(OnlineChatMember.TEXT, R.layout.list_item_online_user_text); + mIsHomeParty = isHomeParty; + this.context = context; + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + registerRoomEvent(); + } + + + @Override + protected void convert(BaseViewHolder baseViewHolder, OnlineChatMember onlineChatMember) { + if (onlineChatMember != null) { + switch (onlineChatMember.getItemType()) { + case OnlineChatMember.NOBLE: + setNobleData(baseViewHolder, onlineChatMember); + break; + case OnlineChatMember.NORMAL: + if (onlineChatMember.chatRoomMember != null) + setNormalData(baseViewHolder, onlineChatMember); + break; + default: + } + } + } + + private void setNobleData(BaseViewHolder baseViewHolder, OnlineChatMember onlineChatMember) { + TextView tvNick = baseViewHolder.getView(R.id.tv_nick); + int color; + if (onlineChatMember.gender == 1) { + color = context.getResources().getColor(R.color.color_male_16AEFD); + } else if (onlineChatMember.gender == 2) { + color = context.getResources().getColor(R.color.color_female_FE3F77); + } else { + color = context.getResources().getColor(R.color.white_transparent_12); + } + ViewAdapter.setViewBackground(tvNick, color, 10, 0, 0); + + if (onlineChatMember.chatRoomMember == null) { + tvNick.setTextColor(context.getResources().getColor(R.color.white_transparent_50)); + } else { + tvNick.setTextColor(context.getResources().getColor(R.color.white)); + } + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(55, 80, 15); + if (onlineChatMember.nobleUsers != null && onlineChatMember.nobleUsers.isNobleEnterHide()) { + onlineChatMember.avatar = context.getResources().getString(R.string.url_mystery_man); + tvNick.setText(context.getResources().getString(R.string.mystery_man)); + } else { + tvNick.setText(RegexUtil.getPrintableString(onlineChatMember.nick)); + } + nobleAvatarView.setData(onlineChatMember); + + } + + private void setNormalData(BaseViewHolder baseViewHolder, OnlineChatMember onlineChatMember) { + setSexData(baseViewHolder, onlineChatMember); + + ImageView roomOwnnerTag = baseViewHolder.getView(R.id.room_owner_logo); + ImageView managerLogo = baseViewHolder.getView(R.id.manager_logo); + if (onlineChatMember.isOnMic) { + baseViewHolder.setVisible(R.id.manager_logo, onlineChatMember.isAdmin || onlineChatMember.isRoomOwer); + managerLogo.setVisibility(onlineChatMember.isAdmin || onlineChatMember.isRoomOwer ? View.VISIBLE : View.GONE); + managerLogo.setImageResource(onlineChatMember.isAdmin ? R.drawable.icon_admin_logo + : R.drawable.icon_user_list_room_ownner); + roomOwnnerTag.setImageResource(R.drawable.icon_user_list_up_mic); + roomOwnnerTag.setVisibility((!mIsHomeParty && onlineChatMember.isRoomOwer) ? View.GONE : View.VISIBLE); + } else { + baseViewHolder.getView(R.id.manager_logo).setVisibility(View.GONE); + roomOwnnerTag.setVisibility((onlineChatMember.isAdmin || onlineChatMember.isRoomOwer) + ? View.VISIBLE : View.GONE); + roomOwnnerTag.setImageResource(onlineChatMember.isAdmin ? R.drawable.icon_admin_logo + : R.drawable.icon_user_list_room_ownner); + } + + Object isEnterHide = NobleUtil.getResource(NobleResourceType.KEY_ENTER_HIDE, onlineChatMember.chatRoomMember); + + if ((isEnterHide instanceof Boolean && (Boolean) isEnterHide) + || (isEnterHide instanceof String) && ((String) isEnterHide).equals("1")) { + onlineChatMember.chatRoomMember.setAvatar(context.getResources().getString(R.string.url_mystery_man)); + onlineChatMember.chatRoomMember.setNick(context.getResources().getString(R.string.mystery_man)); + } + + baseViewHolder.setText(R.id.nick, RegexUtil.getPrintableString(onlineChatMember.chatRoomMember.getNick())); + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(37, 54, 0); + nobleAvatarView.setData(onlineChatMember.chatRoomMember); + + View container = baseViewHolder.getView(R.id.container); + int position = baseViewHolder.getLayoutPosition(); + + TextView nick = baseViewHolder.getView(R.id.nick); + if (mIsHomeParty) { + nick.setTextColor(Color.WHITE); + //container.setBackgroundColor(position % 2 == 0 ? Color.parseColor("#05FFFFFF") : 0); + } else { + nick.setTextColor(ContextCompat.getColor(mContext, R.color.color_333333)); + container.setBackgroundResource(R.drawable.bg_common_touch_while); + } + // 官字 + baseViewHolder.getView(R.id.iv_user_official).setVisibility(onlineChatMember.isOfficial() ? View.VISIBLE : View.GONE); + //经验等级 + AppCompatImageView ivUserExper = baseViewHolder.getView(R.id.iv_user_exper); + String experLevelUrl = NobleUtil.getLevel(UserLevelResourceType.EXPER_URL, onlineChatMember.chatRoomMember); + boolean isExperLevelUrlEmpty = TextUtils.isEmpty(experLevelUrl); + ivUserExper.setVisibility(!isExperLevelUrlEmpty ? View.VISIBLE : View.GONE); + if (!isExperLevelUrlEmpty) { + ImageLoadUtils.loadImage(mContext, experLevelUrl, ivUserExper); + } + //魅力等级 + AppCompatImageView ivUserCharm = baseViewHolder.getView(R.id.iv_user_charm); + String charmLevelUrl = NobleUtil.getLevel(UserLevelResourceType.CHARM_URL, onlineChatMember.chatRoomMember); + boolean isCharmLevelUrlEmpty = TextUtils.isEmpty(charmLevelUrl); + ivUserCharm.setVisibility(!isCharmLevelUrlEmpty ? View.VISIBLE : View.GONE); + if (!isCharmLevelUrlEmpty) { + ImageLoadUtils.loadImage(mContext, charmLevelUrl, ivUserCharm); + } + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_noble_level); + String resource = (String) NobleUtil.getResource(NobleResourceType.KEY_BADGE, onlineChatMember.chatRoomMember); + if (TextUtils.isEmpty(resource)) { + ivUserLevel.setVisibility(View.GONE); + return; + } + ivUserLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(resource, ivUserLevel); + } + + private void setSexData(BaseViewHolder baseViewHolder, OnlineChatMember onlineChatMember) { + final ImageView sexImage = baseViewHolder.getView(R.id.sex); + + NimUserInfo nimUserInfo = NimUserInfoCache.getInstance().getUserInfo(onlineChatMember.chatRoomMember.getAccount()); + if (nimUserInfo == null) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(onlineChatMember.chatRoomMember.getAccount(), + new RequestCallbackWrapper() { + @Override + public void onResult(int i, NimUserInfo nimUserInfo, Throwable throwable) { + if (nimUserInfo != null) { + if (nimUserInfo.getGenderEnum() == GenderEnum.MALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_male); + } else if (nimUserInfo.getGenderEnum() == GenderEnum.FEMALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_female); + } else { + sexImage.setVisibility(View.GONE); + } + } + } + }); + } else { + if (nimUserInfo.getGenderEnum() == GenderEnum.MALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_male); + } else if (nimUserInfo.getGenderEnum() == GenderEnum.FEMALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_female); + } else { + sexImage.setVisibility(View.GONE); + } + } + } + + private void registerRoomEvent() { + mDisposable = IMNetEaseManager.get() + .getChatRoomEventObservable() + .subscribe(roomEvent -> { + if (roomEvent == null) return; + int event = roomEvent.getEvent(); + if (roomEvent.getEvent() == RoomEvent.ADD_BLACK_LIST || + roomEvent.getEvent() == RoomEvent.DOWN_MIC || + roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM) { + if (roomEvent.getEvent() == RoomEvent.ADD_BLACK_LIST || + roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM) { + if (mListener != null + && !AvRoomDataManager.get().isOwner(AuthModel.get().getCurrentUid())) { + mListener.addMemberBlack(); + return; + } + } + if (ListUtils.isListEmpty(mData)) return; + if (mIsHomeParty && roomEvent.getEvent() == RoomEvent.DOWN_MIC) { + updateDownUpMic(roomEvent.getAccount(), false); + return; + } + + if (mListener != null) + mListener.addMemberBlack(); + } else if (roomEvent.getEvent() == RoomEvent.ROOM_MANAGER_ADD + || roomEvent.getEvent() == RoomEvent.ROOM_MANAGER_REMOVE) { + updateManager(roomEvent); + } else if (roomEvent.getEvent() == RoomEvent.UP_MIC) { + updateDownUpMic(roomEvent.getAccount(), true); + } else if (event == RoomEvent.ROOM_MEMBER_IN) { + updateMemberIn(roomEvent); + } else if (event == RoomEvent.ROOM_MEMBER_EXIT) { + if (mListener != null) { + mListener.onMemberExit(roomEvent.getAccount(), mData); + } + } + }); + } + + private void updateMemberIn(RoomEvent roomEvent) { + if (mListener != null) { + mListener.onMemberIn(roomEvent.getAccount(), mData); + } + } + + private void updateManager(RoomEvent roomEvent) { + if (mListener != null) + mListener.onUpdateMemberManager(roomEvent.getAccount(), + roomEvent.getEvent() == RoomEvent.ROOM_MANAGER_REMOVE, mData); + } + + + private void updateDownUpMic(String account, boolean isUpMic) { + if (mListener != null) { + mListener.onMemberDownUpMic(account, isUpMic, mData); + } + } + + public void release() { + if (mDisposable != null) { + mDisposable.dispose(); + mDisposable = null; + } + } + + private OnRoomOnlineNumberChangeListener mListener; + + public void setListener(OnRoomOnlineNumberChangeListener listener) { + mListener = listener; + } + + public interface OnRoomOnlineNumberChangeListener { + /** + * 成员进来回调 + * + * @param account + */ + void onMemberIn(String account, List dataList); + + /** + * 成员出去回调 + * + * @param account + * @param dataList + */ + void onMemberExit(String account, List dataList); + + /** + * 成员上下麦更新 + * + * @param account + * @param isUpMic + * @param dataList + */ + void onMemberDownUpMic(String account, boolean isUpMic, + List dataList); + + /** + * 设置管理员回调 + * + * @param account + * @param dataList + */ + void onUpdateMemberManager(String account, boolean isRemoveManager, + List dataList); + + void addMemberBlack(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/PKMicQueueAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/PKMicQueueAdapter.java new file mode 100644 index 000000000..d6581abb9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/PKMicQueueAdapter.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.support.v7.widget.AppCompatImageView; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.pk.bean.PKQueuingMicMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/12/14 + */ +public class PKMicQueueAdapter extends BaseQuickAdapter { + + public PKMicQueueAdapter(List list) { + super(R.layout.item_pk_mic_queue_list, list); + } + + @Override + protected void convert(BaseViewHolder helper, final PKQueuingMicMemberInfo item) { + helper.setText(R.id.tv_userName, item.getNick()) + .setText(R.id.tv_no, (helper.getAdapterPosition() + 1) + ""); + + + CircleImageView ivAvatar = helper.getView(R.id.iv_avatar_view); + GlideApp.with(ivAvatar.getContext()) + .load(item.getAvatar()) + .placeholder(R.drawable.default_avatar) + .into(ivAvatar); + + AppCompatImageView ivGender = helper.getView(R.id.iv_gender); + if (item.getGender() == UserInfo.GENDER_MALE) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + TextView tvOpt = helper.getView(R.id.tv_opt); + tvOpt.setTextColor(mContext.getResources().getColor(R.color.color_FFFFFF)); + if (AvRoomDataManager.get().isManager()) { + if (item.getGroupType() == PKTeamInfo.TEAM_RED) { + tvOpt.setText("抱上红队"); + tvOpt.setBackgroundResource(R.drawable.shape_pk_join_red_team_mark); + } else if (item.getGroupType() == PKTeamInfo.TEAM_BLUE) { + tvOpt.setText("抱上蓝队"); + tvOpt.setBackgroundResource(R.drawable.shape_pk_join_blue_team_mark); + } else { + tvOpt.setText("抱上麦"); + tvOpt.setBackgroundResource(R.drawable.shape_bg_add_attention); + } + final int itemPos = helper.getAdapterPosition(); + tvOpt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onUpMicListener != null) { + onUpMicListener.onUpMic(item, itemPos); + } + } + }); + } else { + if (item.getGroupType() == PKTeamInfo.TEAM_RED) { + tvOpt.setText("已选红队"); + tvOpt.setBackgroundResource(R.drawable.shape_pk_join_red_team_mark); + } else if (item.getGroupType() == PKTeamInfo.TEAM_BLUE) { + tvOpt.setText("已选蓝队"); + tvOpt.setBackgroundResource(R.drawable.shape_pk_join_blue_team_mark); + } else { + tvOpt.setText("排麦中"); + tvOpt.setBackgroundResource(R.drawable.shape_bg_add_attention); + } + tvOpt.setOnClickListener(null); + } + + } + + public interface OnUpMicListener { + void onUpMic(PKQueuingMicMemberInfo memeberInfo, int itemPos); + } + + private OnUpMicListener onUpMicListener; + + public void setOnUpMicListener(OnUpMicListener onUpMicListener) { + this.onUpMicListener = onUpMicListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RecordForPKAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RecordForPKAdapter.java new file mode 100644 index 000000000..45c0f9df1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RecordForPKAdapter.java @@ -0,0 +1,152 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.graphics.drawable.GradientDrawable; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRecordInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamMember; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/12/29 + */ +public class RecordForPKAdapter extends BaseQuickAdapter { + + private Context context; + private SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd\nHH:mm:ss"); + + public RecordForPKAdapter(Context context, @Nullable List data) { + super(R.layout.item_record_for_pk, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, PKRecordInfo item) { + if (item.getVoteMode() == RoomPkData.VOTE_MODE_GIFT) { + helper.setText(R.id.tv_pk_type, context.getResources().getString(R.string.vote_type_gift_value)); + } else if (item.getVoteMode() == RoomPkData.VOTE_MODE_PERSON) { + helper.setText(R.id.tv_pk_type, context.getResources().getString(R.string.vote_type_gift_member)); + } + helper.setText(R.id.tv_time, formater.format(new Date(item.getBeginTime()))); + + LinearLayout llRedTeamMembers = (LinearLayout) helper.getView(R.id.ll_red_team_members); + LinearLayout llBlueTeamMembers = (LinearLayout) helper.getView(R.id.ll_blue_team_members); + + TextView tvRedTeamScore = (TextView) helper.getView(R.id.tv_red_team_score); + TextView tvRedTeamResult = (TextView) helper.getView(R.id.tv_red_team_result); + + TextView tvBlueTeamScore = (TextView) helper.getView(R.id.tv_blue_team_score); + TextView tvBlueTeamResult = (TextView) helper.getView(R.id.tv_blue_team_result); + GradientDrawable redTeamMembersBackground = (GradientDrawable) llRedTeamMembers.getBackground(); + GradientDrawable blueTeamMembersBackground = (GradientDrawable) llBlueTeamMembers.getBackground(); + + + TextView tvRedTeamMember1 = (TextView) helper.getView(R.id.tv_red_team_member_1); + TextView tvRedTeamMember3 = (TextView) helper.getView(R.id.tv_red_team_member_3); + TextView tvRedTeamMember2 = (TextView) helper.getView(R.id.tv_red_team_member_2); + TextView tvRedTeamMember4 = (TextView) helper.getView(R.id.tv_red_team_member_4); + TextView tvBlueTeamMember1 = (TextView) helper.getView(R.id.tv_blue_team_member_1); + TextView tvBlueTeamMember3 = (TextView) helper.getView(R.id.tv_blue_team_member_3); + TextView tvBlueTeamMember2 = (TextView) helper.getView(R.id.tv_blue_team_member_2); + TextView tvBlueTeamMember4 = (TextView) helper.getView(R.id.tv_blue_team_member_4); + + List redTeamMemberViews = new ArrayList<>(); + redTeamMemberViews.add(tvRedTeamMember1); + redTeamMemberViews.add(tvRedTeamMember2); + redTeamMemberViews.add(tvRedTeamMember3); + redTeamMemberViews.add(tvRedTeamMember4); + + List blueTeamMemberViews = new ArrayList<>(); + blueTeamMemberViews.add(tvBlueTeamMember1); + blueTeamMemberViews.add(tvBlueTeamMember2); + blueTeamMemberViews.add(tvBlueTeamMember3); + blueTeamMemberViews.add(tvBlueTeamMember4); + + + PKTeamInfo teamRed = findPKTeam(PKTeamInfo.TEAM_RED, item.getTeams()); + PKTeamInfo teamBlue = findPKTeam(PKTeamInfo.TEAM_BLUE, item.getTeams()); + + if (teamRed != null) { + tvRedTeamScore.setText(FormatUtils.formatToShortHalfUp(teamRed.getScore())); + for (int i = 0; i < redTeamMemberViews.size(); i++) { + if (i < teamRed.getTeamMembers().size()) { + PKTeamMember pkTeamMember = teamRed.getTeamMembers().get(i); + redTeamMemberViews.get(i).setVisibility(View.VISIBLE); + redTeamMemberViews.get(i).setText(pkTeamMember.getNick()); + } else { + redTeamMemberViews.get(i).setVisibility(View.GONE); + } + } + } + + if (teamBlue != null) { + tvBlueTeamScore.setText(FormatUtils.formatToShortHalfUp(teamBlue.getScore())); + for (int i = 0; i < blueTeamMemberViews.size(); i++) { + if (i < teamBlue.getTeamMembers().size()) { + PKTeamMember pkTeamMember = teamBlue.getTeamMembers().get(i); + blueTeamMemberViews.get(i).setVisibility(View.VISIBLE); + blueTeamMemberViews.get(i).setText(pkTeamMember.getNick()); + } else { + blueTeamMemberViews.get(i).setVisibility(View.GONE); + } + } + } + + if (PKTeamInfo.TEAM_RED == item.getResult()) { + redTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_FD4D72)); + blueTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + tvRedTeamResult.setText("胜利"); + tvRedTeamResult.setBackgroundResource(R.drawable.bg_pk_record_red_team); + tvBlueTeamResult.setText("失败"); + tvBlueTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + + } else if (PKTeamInfo.TEAM_BLUE == item.getResult()) { + redTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + blueTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_3B74FE)); + tvRedTeamResult.setText("失败"); + tvRedTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + tvBlueTeamResult.setText("胜利"); + tvBlueTeamResult.setBackgroundResource(R.drawable.bg_pk_record_blue_team); + } else if (RoomPkData.PK_RESULT_DRAW == item.getResult()) { + redTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + blueTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + tvRedTeamResult.setText("平局"); + tvRedTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + tvBlueTeamResult.setText("平局"); + tvBlueTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + } else { + redTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + blueTeamMembersBackground.setColor(context.getResources().getColor(R.color.color_CCCCCC)); + tvRedTeamResult.setText("失败"); + tvRedTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + tvBlueTeamResult.setText("失败"); + tvBlueTeamResult.setBackgroundResource(R.drawable.bg_pk_record_loser); + } + } + + private PKTeamInfo findPKTeam(int teamMark, List pkTeamInfoList) { + for (PKTeamInfo pkTeamInfo : pkTeamInfoList) { + if (teamMark == pkTeamInfo.getTeam()) { + return pkTeamInfo; + } + } + return null; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomBlackListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomBlackListAdapter.java new file mode 100644 index 000000000..0b012edab --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomBlackListAdapter.java @@ -0,0 +1,46 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import java.util.List; + + +/** + * 右滑操作的,写了暂时不用 + * Created by lvzebiao + */ + +public class RoomBlackListAdapter extends BaseQuickAdapter{ + + private Context context; + + private int itemWidth; + + public RoomBlackListAdapter(Context context) { + super(R.layout.list_item_room_black); + this.context = context; + itemWidth = UIUtil.getScreenWidth(context); + } + + @Override + protected void convert(BaseViewHolder helper, ChatRoomMember chatRoomMember) { + helper.setText(R.id.nick, chatRoomMember.getNick()); + ImageLoadUtils.loadAvatar(context, chatRoomMember.getAvatar(), helper.getView(R.id.avatar)); + helper.getView(R.id.layout_item).getLayoutParams().width = itemWidth; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumeListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumeListAdapter.java new file mode 100644 index 000000000..60c7260a1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumeListAdapter.java @@ -0,0 +1,194 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; + +import java.math.BigDecimal; +import java.util.ArrayList; + +/** + *

房间消费adapter

+ * + * @author Administrator + * @date 2017/11/20 + */ +public class RoomConsumeListAdapter extends BaseMultiItemQuickAdapter { + + private Context context; + + public RoomConsumeListAdapter(Context context) { + super(new ArrayList<>()); + this.context = context; + addItemType(RoomContributeUserInfo.TYPE_GRID, R.layout.list_item_room_consume_first); + addItemType(RoomRankMultiItem.TYPE_LINEAR, R.layout.list_item_room_consume); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, RoomContributeUserInfo roomConsumeInfo) { + if (roomConsumeInfo == null) { + return; + } + if (roomConsumeInfo.getItemType() == RoomRankMultiItem.TYPE_LINEAR) { + setLinearData(baseViewHolder, roomConsumeInfo); + } else { + setGridData(baseViewHolder, roomConsumeInfo); + } + } + + private void setGridData(BaseViewHolder baseViewHolder, RoomContributeUserInfo roomConsumeInfo) { + RelativeLayout avatarContainer = baseViewHolder.getView(R.id.avatar_container); + int position = baseViewHolder.getLayoutPosition(); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) avatarContainer.getLayoutParams(); + + ImageView ivAvatar = baseViewHolder.getView(R.id.iv_avatar); + ViewGroup.LayoutParams avatarParams = ivAvatar.getLayoutParams(); + + RelativeLayout.LayoutParams nickLayoutParams = (RelativeLayout.LayoutParams) + baseViewHolder.getView(R.id.nick_layout).getLayoutParams(); + + if (position == 0) { //排行榜第二名 + params.topMargin = UIUtil.dip2px(context, 33); + params.width = params.height = UIUtil.dip2px(context, 90); + avatarParams.width = avatarParams.height = UIUtil.dip2px(context, 58); + nickLayoutParams.topMargin = UIUtil.dip2px(context, 118); + } else if (position == 1) {//排行榜第一名 + params.topMargin = 0; + params.width = params.height = UIUtil.dip2px(context, 110); + avatarParams.width = avatarParams.height = UIUtil.dip2px(context, 71); + nickLayoutParams.topMargin = UIUtil.dip2px(context, 105); + } else {//排行榜第三名 + params.topMargin = UIUtil.dip2px(context, 26); + params.width = params.height = UIUtil.dip2px(context, 90); + avatarParams.width = avatarParams.height = UIUtil.dip2px(context, 58); + nickLayoutParams.topMargin = UIUtil.dip2px(context, 111); + } + ImageView ivRankIcon = baseViewHolder.getView(R.id.iv_rank_icon); + int emptyPic; + //虚位以待,没数据展示,隐藏相关即可 + baseViewHolder.setVisible(R.id.tv_nick, !roomConsumeInfo.isEmptyBean()) + .setVisible(R.id.tv_erban_id, !roomConsumeInfo.isEmptyBean()) + .setVisible(R.id.coin_text, !roomConsumeInfo.isEmptyBean()) + .setVisible(R.id.tv_empty_text, roomConsumeInfo.isEmptyBean()); + if (roomConsumeInfo.isEmptyBean()) { + if (position == 0) { + emptyPic = R.drawable.icon_consume_second_empty; + } else if (position == 1) { + emptyPic = R.drawable.icon_consume_first_empty; + } else { + emptyPic = R.drawable.icon_consume_third_empty; + } + ivAvatar.setVisibility(View.GONE); + ivRankIcon.setImageResource(emptyPic); + } else { + if (position == 0) { + emptyPic = R.drawable.icon_consume_second; + } else if (position == 1) { + emptyPic = R.drawable.icon_consume_first; + } else { + emptyPic = R.drawable.icon_consume_third; + } + ivAvatar.setVisibility(View.VISIBLE); + if (roomConsumeInfo.isHide()) { + ImageLoadUtils.loadBigAvatar(mContext, context.getResources().getString(R.string.url_mystery_man), ivAvatar, true); + } else { + ImageLoadUtils.loadBigAvatar(mContext, roomConsumeInfo.getAvatar(), ivAvatar, true); + } + ivRankIcon.setImageResource(emptyPic); + + setCommonView(baseViewHolder, roomConsumeInfo); + + } + + + } + + private void setLinearData(BaseViewHolder baseViewHolder, RoomContributeUserInfo roomConsumeInfo) { + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(45, 66, 14); + NobleInfo nobleInfo = new NobleInfo(); + nobleInfo.setBadge(roomConsumeInfo.getBadge()); + nobleInfo.setHeadWear(roomConsumeInfo.getMicDecorate()); + if (roomConsumeInfo.isHide()) { + nobleAvatarView.setData(context.getResources().getString(R.string.url_mystery_man), nobleInfo); + } else { + nobleAvatarView.setData(roomConsumeInfo.getAvatar(), nobleInfo); + } + + AppCompatImageView ivNobleLevel = baseViewHolder.getView(R.id.iv_noble_level); + ivNobleLevel.setVisibility(View.GONE); + String nobleBadge; + if (!TextUtils.isEmpty((nobleBadge = roomConsumeInfo.getBadge()))) { + ivNobleLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(nobleBadge, ivNobleLevel); + } + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (!TextUtils.isEmpty(roomConsumeInfo.getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, roomConsumeInfo.getExperUrl(), ivUserLevel); + } + + + TextView numberText = baseViewHolder.getView(R.id.auction_number_text); + ImageView numberImage = baseViewHolder.getView(R.id.auction_number_image); + int position = baseViewHolder.getLayoutPosition(); + if (position <= 2) { + numberText.setVisibility(View.INVISIBLE); + numberImage.setVisibility(View.VISIBLE); + if (position == 0) { + numberImage.setImageResource(R.drawable.icon_auction_week_list_first); + } else if (position == 1) { + numberImage.setImageResource(R.drawable.icon_auction_week_list_second); + } else { + numberImage.setImageResource(R.drawable.icon_auction_week_list_third); + } + } else { + numberText.setVisibility(View.VISIBLE); + numberImage.setVisibility(View.GONE); + numberText.setText(mContext.getString(R.string.consume_position, (position + 1))); + } + setCommonView(baseViewHolder, roomConsumeInfo); + } + + /** + * 设置共同的部分 + */ + private void setCommonView(BaseViewHolder baseViewHolder, RoomContributeUserInfo roomConsumeInfo) { + String goldAmount; + if (roomConsumeInfo.getGoldAmount() >= 10000) { + BigDecimal b = new BigDecimal(roomConsumeInfo.getGoldAmount() / 10000.0); + double df = b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue(); + goldAmount = String.valueOf(df) + "万"; + } else { + goldAmount = String.valueOf(roomConsumeInfo.getGoldAmount()); + } + baseViewHolder.setText(R.id.tv_erban_id, roomConsumeInfo.isHide() ? "****" : "ID:" + roomConsumeInfo.getErbanNo()) + .setImageResource(R.id.iv_sex, + roomConsumeInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female) + .setText(R.id.coin_text, goldAmount) + .setText(R.id.tv_nick, roomConsumeInfo.isHide() ? + context.getResources().getString(R.string.mystery_man) + : RegexUtil.getPrintableString(roomConsumeInfo.getNick())); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumerListAdapterTemp.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumerListAdapterTemp.java new file mode 100644 index 000000000..ac8982793 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomConsumerListAdapterTemp.java @@ -0,0 +1,205 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.RoomRankDialogUtils; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; + +import java.util.ArrayList; + +public class RoomConsumerListAdapterTemp extends BaseMultiItemQuickAdapter { + + public final static int TYPE_EMPTY = 3; + private RoomConsumerTopThreeListener mRoomConsumerTopThreeListener; + + public RoomConsumerListAdapterTemp(Context context) { + super(new ArrayList<>()); + addItemType(RoomContributeUserInfo.TYPE_GRID, R.layout.layout_room_rank_top_three); + addItemType(RoomRankMultiItem.TYPE_LINEAR, R.layout.list_item_room_consume); + addItemType(TYPE_EMPTY, R.layout.item_empty_list); + } + + public void setmRoomConsumerTopThreeListener(RoomConsumerTopThreeListener mRoomConsumerTopThreeListener) { + this.mRoomConsumerTopThreeListener = mRoomConsumerTopThreeListener; + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, RoomRankMultiItem roomConsumeInfo) { + if (roomConsumeInfo == null) { + return; + } + if (roomConsumeInfo.getItemType() == RoomRankMultiItem.TYPE_LINEAR) { + setLinearData(baseViewHolder, roomConsumeInfo); + } else if (roomConsumeInfo.getItemType() == TYPE_EMPTY) { + + } else { + setGridView(baseViewHolder, roomConsumeInfo); + } + } + + private void setGridView(BaseViewHolder baseViewHolder, RoomRankMultiItem roomRankMultiItem) { + ArrayList data = (ArrayList) roomRankMultiItem.getData(); + View root = baseViewHolder.itemView; + + RelativeLayout rlTopOne = root.findViewById(R.id.layout_room_rank_top_1); + CircleImageView ciTopOne = root.findViewById(R.id.iv_room_rank_top_1_avatar); + ImageView ivGenderOne = root.findViewById(R.id.iv_room_rank_gender_one); + ImageView ivBgOne = root.findViewById(R.id.iv_room_rank_top_1_avatar_default); + TextView tvOneId = root.findViewById(R.id.tv_number_one_id); + TextView tvLabelOne = root.findViewById(R.id.tv_label_no_1); + TextView tvOneName = root.findViewById(R.id.tv_label_number_one); + + RelativeLayout rlTopTwo = root.findViewById(R.id.layout_room_rank_top_2); + CircleImageView ciTopTwo = root.findViewById(R.id.iv_room_rank_top_2_avatar); + ImageView ivGenderTwo = root.findViewById(R.id.iv_room_rank_gender_two); + ImageView ivBgTwo = root.findViewById(R.id.iv_room_rank_top_2_avatar_default); + TextView tvTwoId = root.findViewById(R.id.tv_number_two_id); + TextView tvLabelTwo = root.findViewById(R.id.tv_two_to_last); + TextView tvTwoName = root.findViewById(R.id.tv_label_number_two); + + RelativeLayout rlTopThree = root.findViewById(R.id.layout_room_rank_top_3); + CircleImageView ciTopThree = root.findViewById(R.id.iv_room_rank_top_3_avatar); + ImageView ivGenderThree = root.findViewById(R.id.iv_room_rank_gender_three); + ImageView ivBgThree = root.findViewById(R.id.iv_room_rank_top_3_avatar_default); + TextView tvThreeId = root.findViewById(R.id.tv_number_three_id); + TextView tvLabelThree = root.findViewById(R.id.tv_three_to_last); + TextView tvThreeName = root.findViewById(R.id.tv_label_number_three); + + if (data != null) { + + for (int i = 0; i < data.size(); i++) { + RoomContributeUserInfo userInfo = data.get(i); + + if (userInfo != null) { + // 无数据状态需要展示 虚位以待 + boolean isEmptyBean = userInfo.isEmptyBean(); + + if (i == 0) { + + if (!TextUtils.isEmpty(userInfo.getAvatar())) + ImageLoadUtils.loadBigAvatar(mContext, userInfo.getAvatar(), ciTopOne, true); + + + ivGenderOne.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + ivGenderOne.setImageResource(userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + + ciTopOne.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + tvLabelOne.setText(isEmptyBean ? "" : RoomRankDialogUtils.getRoomRankValueText(userInfo.getGoldAmount())); + ivBgOne.setImageResource(isEmptyBean ? R.drawable.icon_consume_first_empty : R.drawable.icon_consume_first); + tvOneId.setText(isEmptyBean? "" : "ID:" + userInfo.getErbanNo()); + tvOneName.setText(isEmptyBean ? "" : userInfo.getNick()); + rlTopOne.setOnClickListener(isEmptyBean ? null : new View.OnClickListener() { + @Override + public void onClick(View v) { + if (userInfo.isHide()) return; + if (userInfo.isEmptyBean()) return; + if (mRoomConsumerTopThreeListener != null) + mRoomConsumerTopThreeListener.topThreeListener(userInfo.getUid()); + } + }); + } else if (i == 1) { + + if (!TextUtils.isEmpty(userInfo.getAvatar())) + ImageLoadUtils.loadBigAvatar(mContext, userInfo.getAvatar(), ciTopTwo, true); + ivGenderTwo.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + ivGenderTwo.setImageResource(userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + + ciTopTwo.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + tvLabelTwo.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + ivBgTwo.setImageResource(isEmptyBean ? R.drawable.icon_consume_second_empty : R.drawable.icon_consume_second); + tvTwoId.setText(isEmptyBean ? "" : "ID:" + userInfo.getErbanNo()); + tvTwoName.setText(isEmptyBean ? "" : userInfo.getNick()); + tvLabelTwo.setText(RoomRankDialogUtils.getRoomRankValueText(userInfo.getGoldAmount())); + rlTopTwo.setOnClickListener(isEmptyBean ? null : new View.OnClickListener() { + @Override + public void onClick(View v) { + if (userInfo.isHide()) return; + if (userInfo.isEmptyBean()) return; + if (mRoomConsumerTopThreeListener != null) + mRoomConsumerTopThreeListener.topThreeListener(userInfo.getUid()); + } + }); + } else if (i == 2) { + + if (!TextUtils.isEmpty(userInfo.getAvatar())) + ImageLoadUtils.loadBigAvatar(mContext, userInfo.getAvatar(), ciTopThree, true); + + ivGenderThree.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + ivGenderThree.setImageResource(userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + + ciTopThree.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + tvLabelThree.setVisibility(isEmptyBean ? View.GONE : View.VISIBLE); + ivBgThree.setImageResource(isEmptyBean ? R.drawable.icon_consume_third_empty : R.drawable.icon_consume_third); + tvThreeId.setText(isEmptyBean ? "" : "ID:" + userInfo.getErbanNo()); + tvThreeName.setText(isEmptyBean ? "" : userInfo.getNick()); + tvLabelThree.setText(RoomRankDialogUtils.getRoomRankValueText(userInfo.getGoldAmount())); + rlTopThree.setOnClickListener(isEmptyBean ? null : new View.OnClickListener() { + @Override + public void onClick(View v) { + if (userInfo.isHide()) return; + if (userInfo.isEmptyBean()) return; + if (mRoomConsumerTopThreeListener != null) + mRoomConsumerTopThreeListener.topThreeListener(userInfo.getUid()); + } + }); + } + + + } + } + + } + + } + + private void setLinearData(BaseViewHolder baseViewHolder, RoomRankMultiItem roomConsumeInfo) { + + RoomContributeUserInfo roomContributeUserInfo = (RoomContributeUserInfo) roomConsumeInfo.getData(); + + CircleImageView avatarView = baseViewHolder.getView(R.id.avatar_view); + ImageLoadUtils.loadAvatar(mContext, roomContributeUserInfo.getAvatar(), avatarView, true); + + AppCompatImageView ivNobleLevel = baseViewHolder.getView(R.id.iv_noble_level); + ivNobleLevel.setVisibility(View.GONE); + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + + ImageView numberImage = baseViewHolder.getView(R.id.auction_number_image); + numberImage.setVisibility(View.GONE); + int drawable = RoomRankDialogUtils.getNumberImage(roomContributeUserInfo.getRanking()); + if (drawable != 0) { + baseViewHolder.setImageResource(R.id.iv_number, drawable); + } + setCommonView(baseViewHolder, roomContributeUserInfo); + } + + /** + * 设置共同的部分 + */ + private void setCommonView(BaseViewHolder baseViewHolder, RoomContributeUserInfo roomConsumeInfo) { + String goldAmount = RoomRankDialogUtils.getRoomRankValueText(roomConsumeInfo.getGoldAmount()); + baseViewHolder.setText(R.id.tv_erban_id, "ID:" + roomConsumeInfo.getErbanNo()) + .setImageResource(R.id.iv_sex, + roomConsumeInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female) + .setText(R.id.coin_text, goldAmount) + .setText(R.id.tv_nick, RegexUtil.getPrintableString(roomConsumeInfo.getNick())); + } + + public interface RoomConsumerTopThreeListener { + void topThreeListener(long uid); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomContributeListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomContributeListAdapter.java new file mode 100644 index 000000000..169207780 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomContributeListAdapter.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.List; + +/** + * Created by MadisonRong on 25/04/2018. + */ + +public class RoomContributeListAdapter extends FragmentPagerAdapter { + + private List fragmentList; + + public RoomContributeListAdapter(FragmentManager fm, List fragmentList) { + super(fm); + this.fragmentList = fragmentList; + } + + public RoomContributeListAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomInviteAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomInviteAdapter.java new file mode 100644 index 000000000..33fa40115 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomInviteAdapter.java @@ -0,0 +1,214 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.util.DiffUtil; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.impl.cache.NimUserInfoCache; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.uinfo.constant.GenderEnum; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.ChatMemberDiffUtilCallback; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +/** + *

+ * + * @author jiahui + * @date 2017/12/21 + */ +public class RoomInviteAdapter extends RecyclerView.Adapter { + + private List mChatRoomMemberList; + private Context mContext; + private OnItemClickListener mOnItemClickListener; + private LayoutInflater mInflater; + private Disposable mDisposable; + + public RoomInviteAdapter(Context context, OnItemClickListener onItemClickListener) { + mInflater = LayoutInflater.from(context); + mContext = context; + mOnItemClickListener = onItemClickListener; + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + mDisposable = IMNetEaseManager.get().getChatRoomEventObservable() + .subscribe(new Consumer() { + @Override + public void accept(RoomEvent roomEvent) throws Exception { + if (roomEvent == null) return; + int event = roomEvent.getEvent(); + if (roomEvent.getEvent() == RoomEvent.ADD_BLACK_LIST || + roomEvent.getEvent() == RoomEvent.DOWN_MIC || + event == RoomEvent.ROOM_MEMBER_EXIT || + roomEvent.getEvent() == RoomEvent.KICK_OUT_ROOM) { + if (ListUtils.isListEmpty(mChatRoomMemberList)) return; + ListIterator iterator = mChatRoomMemberList.listIterator(); + for (; iterator.hasNext(); ) { + ChatRoomMember onlineChatMember = iterator.next(); + if (onlineChatMember != null + && Objects.equals(onlineChatMember.getAccount(), roomEvent.getAccount())) { + iterator.remove(); + } + } + notifyDataSetChanged(); + if (mOnRoomOnlineNumberChangeListener != null) + mOnRoomOnlineNumberChangeListener.onRoomOnlineNumberChange(getItemCount()); + } else if (event == RoomEvent.ROOM_MEMBER_IN) { + updateMemberIn(roomEvent); + } + } + }); + } + + public void onRelease() { + if (mDisposable != null) { + mDisposable.dispose(); + mDisposable = null; + } + } + + private void updateMemberIn(RoomEvent roomEvent) { + ChatRoomMember chatRoomMember = AvRoomDataManager.get().getChatRoomMember(roomEvent.getAccount()); + if (chatRoomMember == null) return; + if (!ListUtils.isListEmpty(mChatRoomMemberList)) { + for (ChatRoomMember temp : mChatRoomMemberList) { + if (Objects.equals(temp.getAccount(), chatRoomMember.getAccount())) + return; + } + } + List list = new ArrayList<>(1); + list.add(chatRoomMember); + addChatRoomMemberList(list); + if (mOnRoomOnlineNumberChangeListener != null) + mOnRoomOnlineNumberChangeListener.onRoomOnlineNumberChange(getItemCount()); + } + + public void addChatRoomMemberList(final List chatRoomMemberList) { + if (ListUtils.isListEmpty(mChatRoomMemberList)) { + mChatRoomMemberList = chatRoomMemberList; + notifyDataSetChanged(); + } else { + mChatRoomMemberList.addAll(chatRoomMemberList); + DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( + new ChatMemberDiffUtilCallback(mChatRoomMemberList, chatRoomMemberList), true); + diffResult.dispatchUpdatesTo(this); + } + } + + public List getChatRoomMemberList() { + return mChatRoomMemberList; + } + + @Override + public RoomInviteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new RoomInviteViewHolder(mInflater.inflate(R.layout.room_invite_list_item_layout, parent, false)); + } + + @Override + public void onBindViewHolder(RoomInviteViewHolder holder, int position) { + + final ChatRoomMember chatRoomMember = mChatRoomMemberList.get(position); + if (chatRoomMember == null) return; + NimUserInfo nimUserInfo = NimUserInfoCache.getInstance().getUserInfo(chatRoomMember.getAccount()); + final ImageView sexImage = holder.sexImage; + if (nimUserInfo == null) { + NimUserInfoCache.getInstance().getUserInfoFromRemote(chatRoomMember.getAccount(), + new RequestCallbackWrapper() { + @Override + public void onResult(int i, NimUserInfo nimUserInfo, Throwable throwable) { + if (nimUserInfo != null) { + if (nimUserInfo.getGenderEnum() == GenderEnum.MALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_male); + } else if (nimUserInfo.getGenderEnum() == GenderEnum.FEMALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_female); + } else { + sexImage.setVisibility(View.GONE); + } + } + } + }); + } else { + if (nimUserInfo.getGenderEnum() == GenderEnum.MALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_male); + } else if (nimUserInfo.getGenderEnum() == GenderEnum.FEMALE) { + sexImage.setVisibility(View.VISIBLE); + sexImage.setImageResource(R.drawable.ic_female); + } else { + sexImage.setVisibility(View.GONE); + } + } + holder.mViewLine.setVisibility(position == getItemCount() - 1 ? View.GONE : View.VISIBLE); + ImageLoadUtils.loadAvatar(mContext, chatRoomMember.getAvatar(), holder.mIvAvatar); + holder.mTvMemberName.setText(chatRoomMember.getNick()); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mOnItemClickListener != null) + mOnItemClickListener.onClick(chatRoomMember); + } + }); + } + + @Override + public int getItemCount() { + return mChatRoomMemberList != null ? mChatRoomMemberList.size() : 0; + } + + + static class RoomInviteViewHolder extends RecyclerView.ViewHolder { + private ImageView mIvAvatar; + private ImageView sexImage; + private TextView mTvMemberName; + View mViewLine; + + RoomInviteViewHolder(View itemView) { + super(itemView); + mIvAvatar = itemView.findViewById(R.id.iv_avatar); + sexImage = itemView.findViewById(R.id.sex); + mTvMemberName = itemView.findViewById(R.id.tv_member_name); + mViewLine = itemView.findViewById(R.id.view_line); + } + } + + + public interface OnItemClickListener { + void onClick(ChatRoomMember chatRoomMember); + } + + private OnRoomOnlineNumberChangeListener mOnRoomOnlineNumberChangeListener; + + public void setOnRoomOnlineNumberChangeListener(OnRoomOnlineNumberChangeListener listener) { + mOnRoomOnlineNumberChangeListener = listener; + } + + public interface OnRoomOnlineNumberChangeListener { + void onRoomOnlineNumberChange(int number); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomNormalListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomNormalListAdapter.java new file mode 100644 index 000000000..72a51f763 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomNormalListAdapter.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; + +import java.util.List; + + +/** + * Created by chenran on 2017/10/11. + */ + +public class RoomNormalListAdapter extends RecyclerView.Adapter implements View.OnClickListener{ + private Context context; + private List normalList; + private OnRoomNormalListOperationClickListener listOperationClickListener; + + public RoomNormalListAdapter(Context context) { + this.context = context; + } + + public void setNormalList(List normalList) { + this.normalList = normalList; + } + + public List getNormalList() { + return normalList; + } + + public void setListOperationClickListener(OnRoomNormalListOperationClickListener listOperationClickListener) { + this.listOperationClickListener = listOperationClickListener; + } + + @Override + public RoomNormalListHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_room_normal, parent, false); + return new RoomNormalListHolder(view); + } + + @Override + public void onBindViewHolder(RoomNormalListHolder holder, int position) { + ChatRoomMember chatRoomMember = normalList.get(position); + holder.nick.setText(chatRoomMember.getNick()); + holder.operationImg.setTag(chatRoomMember); + holder.operationImg.setOnClickListener(this); + ImageLoadUtils.loadAvatar(context, chatRoomMember.getAvatar(), holder.avatar); + } + + @Override + public int getItemCount() { + if (normalList == null) { + return 0; + } else { + return normalList.size(); + } + } + + @Override + public void onClick(View v) { + if (v.getTag() != null && v.getTag() instanceof ChatRoomMember) { + ChatRoomMember chatRoomMember = (ChatRoomMember) v.getTag(); + if (listOperationClickListener != null) { + listOperationClickListener.onRemoveOperationClick(chatRoomMember); + } + } + } + + public class RoomNormalListHolder extends RecyclerView.ViewHolder { + private CircleImageView avatar; + private TextView nick; + private TextView erbanNo; + private TextView operationImg; + + public RoomNormalListHolder(View itemView) { + super(itemView); + avatar = (CircleImageView) itemView.findViewById(R.id.avatar); + nick = (TextView) itemView.findViewById(R.id.nick); + erbanNo = (TextView) itemView.findViewById(R.id.erban_no); + operationImg = (TextView) itemView.findViewById(R.id.remove_opration); + } + } + + public interface OnRoomNormalListOperationClickListener { + void onRemoveOperationClick(ChatRoomMember chatRoomMember); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankFragmentPageAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankFragmentPageAdapter.java new file mode 100644 index 000000000..4df26181b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankFragmentPageAdapter.java @@ -0,0 +1,27 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.List; + +public class RoomRankFragmentPageAdapter extends FragmentPagerAdapter { + + private List fragmentList; + + public RoomRankFragmentPageAdapter(FragmentManager fm, List fragmentList) { + super(fm); + this.fragmentList = fragmentList; + } + + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankHalfHourListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankHalfHourListAdapter.java new file mode 100644 index 000000000..c883fd446 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/RoomRankHalfHourListAdapter.java @@ -0,0 +1,63 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.RoomRankDialogUtils; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourRankInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; + +import java.util.ArrayList; + +public class RoomRankHalfHourListAdapter extends BaseMultiItemQuickAdapter { + + public final static int TYPE_TIPS = 4; + + public RoomRankHalfHourListAdapter(Context context) { + super(new ArrayList<>()); + addItemType(RoomRankMultiItem.TYPE_LINEAR, R.layout.item_room_rank_layout); + addItemType(RoomRankMultiItem.TYPE_EMPTY, R.layout.item_empty_list); + addItemType(TYPE_TIPS, R.layout.item_rank_half_tips); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, RoomRankMultiItem roomConsumeInfo) { + if (roomConsumeInfo == null) { + return; + } + if (roomConsumeInfo.getItemType() == RoomRankMultiItem.TYPE_LINEAR) { + setLinearData(baseViewHolder, roomConsumeInfo); + } else if (roomConsumeInfo.getItemType() == RoomRankMultiItem.TYPE_EMPTY) { + + } + } + + private void setLinearData(BaseViewHolder baseViewHolder, RoomRankMultiItem roomConsumeInfo) { + if (roomConsumeInfo == null) { + return; + } + + RoomRankHalfHourRankInfo roomRankHalfHourRankInfo = (RoomRankHalfHourRankInfo) roomConsumeInfo.getData(); + if (roomRankHalfHourRankInfo == null) + return; + + // 值 + TextView valueTV = baseViewHolder.getView(R.id.tv_room_rank_value); + valueTV.setText(RoomRankDialogUtils.getRoomRankValueText(roomRankHalfHourRankInfo.getTotalNum())); + + int drawable = RoomRankDialogUtils.getNumberImage(roomRankHalfHourRankInfo.getSeqNo()); + if (drawable != 0) + baseViewHolder.setImageResource(R.id.iv_number, drawable); + // 标题 + baseViewHolder.setText(R.id.tv_room_rank_title, roomRankHalfHourRankInfo.getRoomTitle()); + // 头像 + CircleImageView avatarView = baseViewHolder.getView(R.id.iv_room_rank_avatar); + ImageLoadUtils.loadAvatar(mContext, roomRankHalfHourRankInfo.getAvatar(), avatarView, true); + baseViewHolder.setText(R.id.tv_room_rank_id, "ID:" + roomRankHalfHourRankInfo.getErbanNo()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/adapter/UpMicAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/adapter/UpMicAdapter.java new file mode 100644 index 000000000..7f2b3f874 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/adapter/UpMicAdapter.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.avroom.adapter; + +import android.content.Context; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +/** + * Created by huangmeng1 on 2018/7/27. + * modify by lvzebiao on 2018/11/14. + */ + +public class UpMicAdapter extends BaseQuickAdapter { + + private Context context; + + private Consumer consumer; + + public UpMicAdapter(Context context, Consumer consumer) { + super(R.layout.item_user_card_up_mic); + this.context = context; + this.consumer = consumer; + List list = new ArrayList<>(); + int size = AvRoomDataManager.get().isCpRoom() ? 2 : 9; + for (int i = 0; i < size; i++) { + list.add(""); + } + setNewData(list); + } + + @Override + protected void convert(BaseViewHolder helper, String item) { + int position = helper.getAdapterPosition(); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(position - 1); + if (roomQueueInfo == null) return; + + boolean isUp = false; + ImageView imageView = helper.getView(R.id.iv_mic); + if (roomQueueInfo.mChatRoomMember == null) { + + if (AvRoomDataManager.get().isLeaveMode() && position == 0) { // 离开模式房主位不可上麦 + isUp = true; + + } else { + imageView.setImageResource(R.drawable.icon_up_mic_false); + helper.itemView.setClickable(true); + helper.itemView.setOnClickListener(v -> Single.just(position).subscribe(consumer)); + } + + } else { + isUp = true; + } + + if (isUp) { + imageView.setImageResource(R.drawable.icon_up_mic_ture); + helper.itemView.setClickable(false); + } + + TextView textView = helper.getView(R.id.tv_pos); + if (position == 0) { + textView.setText("房主位"); + } else { + textView.setText(String.format( + context.getResources().getString(R.string.which_mic_position), position)); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/MicQueueDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/MicQueueDialog.java new file mode 100644 index 000000000..171829819 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/MicQueueDialog.java @@ -0,0 +1,550 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.MicQueueAdapter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.HomePartyModel; +import com.yizhuan.xchat_android_core.room.model.MicQueueModel; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.QueuingMicMemeberInfo; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.RespQueuingMicListInfo; +import com.yizhuan.xchat_android_core.user.bean.BaseInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/12/14 + */ +public class MicQueueDialog extends BaseDialog implements + LoadPageDataHelper.LoadData> { + + + @BindView(R.id.tv_mic_queue_tip) + TextView tvMicQueueTip; + @BindView(R.id.rv_mic_queue) + RecyclerView rvMicQueue; + @BindView(R.id.srl_refresh_container) + SwipeRefreshLayout srlRefreshContainer; + @BindView(R.id.tv_no_data_tip) + TextView tvNoDataTip; + @BindView(R.id.ll_no_data_container) + FrameLayout llNoDataContainer; + @BindView(R.id.tv_apply_mic_queue) + TextView tvApplyMicQueue; + @BindView(R.id.ll_container) + RelativeLayout llContainer; + @BindView(R.id.fl_queue_count) + FrameLayout flQueueCount; + @BindView(R.id.fl_bottom_button) + FrameLayout flBottomButton; + @BindView(R.id.fl_main_content) + FrameLayout flMainContent; + private LoadPageDataHelper> loadPageDataHelper; + private boolean noMoreData = false; + private MicQueueAdapter adapter; + + private CompositeDisposable compositeDisposable = new CompositeDisposable(); + + private Context context; + + public MicQueueDialog(@NonNull Context context) { + super(context, R.style.bottom_dialog); + this.context = context; + loadPageDataHelper = new LoadPageDataHelper<>(this); + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams lps = window.getAttributes(); + lps.width = WindowManager.LayoutParams.MATCH_PARENT; + lps.height = WindowManager.LayoutParams.WRAP_CONTENT; + lps.gravity = Gravity.BOTTOM; + window.setAttributes(lps); + } + } + + private List dataList = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_mic_queue); + ButterKnife.bind(this); + + + srlRefreshContainer.setOnRefreshListener(this::refreshData); + + rvMicQueue.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); + rvMicQueue.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(getContext(), 5), true)); + + adapter = new MicQueueAdapter(dataList); + adapter.setOnUpMicListener(new MicQueueAdapter.OnUpMicListener() { + @Override + public void onUpMic(QueuingMicMemeberInfo member, final int itemPos) { + long targetUid = member.getUid(); + if (AvRoomDataManager.get().isOnMic(member.getUid())) { + toast("TA已经在麦上了"); + return; + } + AvRoomDataManager.get().checkMemberInRoomById(targetUid) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(ChatRoomMember mem) { + inviteToMic(member, itemPos); + } + }); + + } + }); + rvMicQueue.setAdapter(adapter); + + srlRefreshContainer.setRefreshing(true); + //加载更多 + rvMicQueue.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (loadPageDataHelper.isLoading() || noMoreData) { + return; + } + if (adapter.getItemCount() <= 0) { + return; + } + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + LinearLayoutManager manager = (LinearLayoutManager) rvMicQueue.getLayoutManager(); + int lastIndex = manager.findLastVisibleItemPosition(); + if (lastIndex == adapter.getItemCount() - 1) { + loadMoreData(); + } + } + } + }); + refreshData(); + } + + /**抱TA上麦*/ + private void inviteToMic(QueuingMicMemeberInfo member, int itemPos) { + int micPosition = -1; + for (int i = 0; i < AvRoomDataManager.get().mMicQueueMemberMap.size(); i++) { + int key = AvRoomDataManager.get().mMicQueueMemberMap.keyAt(i); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(key); + //-1这个位置是 房主,不让上去 + //排麦模式下,选择被锁的坑,即是排麦坑才能上 + if (key != -1 && roomQueueInfo != null + && roomQueueInfo.mRoomMicInfo != null + && roomQueueInfo.mRoomMicInfo.isMicLock() + && roomQueueInfo.mChatRoomMember == null) { + micPosition = key; + break; + } + } + //房主的坑位key是-1 ,剩下的 8个坑的key从0 - 7 + if (micPosition != -1 && micPosition < 8) { + if (itemPos < adapter.getItemCount()) { + dataList.remove(itemPos); + adapter.notifyDataSetChanged(); + } + reduceQueueInfo(); + if (dataList.size() == 0) { + showNoDataLayout(); + } else { + setTopLayout(); + } + HomePartyModel model = new HomePartyModel(); + long targetUid = member.getUid(); + if (AvRoomDataManager.get().isOwner(targetUid)) { + //如果是自己,就是自己上麦 + final int finalMicPos = micPosition; + model.upMicroPhone( + micPosition, + String.valueOf(targetUid), + String.valueOf(AvRoomDataManager.get().getRoomId()), + true, + new CallBack() { + @Override + public void onSuccess(String data) { + GiftValueMrg.get().requestUpMic(finalMicPos, String.valueOf(targetUid)); + } + + @Override + public void onFail(int code, String error) { + + } + }); + return; + } + //抱别人上麦 + model.inviteMicroPhone(new BaseInfo(targetUid, member.getNick()), micPosition) + .subscribe(); + + } else { + toast("麦上没空位啦"); + } + } + + + /**将队列减一*/ + private void reduceQueueInfo() { + if (queueMicListInfo != null) { + int count = queueMicListInfo.getCount(); + count --; + if (count < 0) { + count = 0; + } + queueMicListInfo.setCount(count); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (compositeDisposable != null) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + } + + public void addDisposable(Disposable disposable) { + compositeDisposable.add(disposable); + } + + /** + * 刷新麦序 + */ + public void refreshData() { + if (loadPageDataHelper.isLoading()) { + srlRefreshContainer.setRefreshing(false); + return; + } + noMoreData = false; + loadPageDataHelper.refreshData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onSuccess(List memberList) { + if (ListUtils.isListEmpty(memberList)) { + showNoDataLayout(); + noMoreData = true; + } else { + showHaveDataLayout(); + dataList = memberList; + adapter.setNewData(memberList); + } + srlRefreshContainer.setRefreshing(false); + } + + @Override + public void onError(Throwable e) { + srlRefreshContainer.setRefreshing(false); +// Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + } + + private void showHaveDataLayout() { + llContainer.setBackgroundColor(getContext().getResources().getColor(R.color.color_F5F5F5)); + srlRefreshContainer.setVisibility(View.VISIBLE); + llNoDataContainer.setVisibility(View.GONE); + setTopLayout(); + tvApplyMicQueue.setClickable(true); + if (AvRoomDataManager.get().isManager()) { + flBottomButton.setVisibility(View.GONE); + } else { + if (queueMicListInfo != null) { + flBottomButton.setVisibility(View.VISIBLE); + if (queueMicListInfo.getMyPos() < 0) { + //我不在队列 + //点击报名 + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + //如果我在麦上 设置不可点击 + tvApplyMicQueue.setClickable(false); + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_dbdbdb_corner); + } else { + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_appcolor_corner); + } + tvApplyMicQueue.setTextColor(context.getResources().getColor(R.color.white)); + tvApplyMicQueue.setText(context.getResources().getString(R.string.apply_mic_queue)); + } else { + //我在队列 + //取消报名 + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_dbdbdb_corner); + tvApplyMicQueue.setTextColor(context.getResources().getColor(R.color.color_333333)); + tvApplyMicQueue.setText(context.getResources().getString(R.string.cancel_mic_queue)); + } + } + } + } + + private void showNoDataLayout() { + llContainer.setBackgroundColor(getContext().getResources().getColor(R.color.color_white)); + srlRefreshContainer.setVisibility(View.GONE); + llNoDataContainer.setVisibility(View.VISIBLE); + flBottomButton.setVisibility(View.VISIBLE); + tvApplyMicQueue.setClickable(true); + if (AvRoomDataManager.get().isManager()) { + flQueueCount.setVisibility(View.GONE); + //立即邀请 + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_appcolor_corner); + tvApplyMicQueue.setTextColor(context.getResources().getColor(R.color.white)); + tvApplyMicQueue.setText(R.string.invite_to_mic_queue); + tvNoDataTip.setText(getContext().getResources().getString(R.string.manager_no_mic_queue_tip)); + } else { + flQueueCount.setVisibility(View.VISIBLE); + tvMicQueueTip.setText(R.string.apply_mic_queue_tip); + //点击报名 + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + tvApplyMicQueue.setClickable(false); + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_dbdbdb_corner); + } else { + tvApplyMicQueue.setBackgroundResource(R.drawable.shape_appcolor_corner); + } + tvApplyMicQueue.setTextColor(context.getResources().getColor(R.color.white)); + tvApplyMicQueue.setText(R.string.apply_mic_queue); + + tvNoDataTip.setText(getContext().getResources().getString(R.string.no_mic_queue_tip)); + } + } + + + private void loadMoreData() { + loadPageDataHelper.loadMoreData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onSuccess(List userInfos) { + if (!ListUtils.isListEmpty(userInfos)) { + adapter.addData(userInfos); + } else { + noMoreData = true; + } + } + + @Override + public void onError(Throwable e) { +// Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + + } + + private RespQueuingMicListInfo queueMicListInfo; + + @Override + public Single> loadData(int curPage) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + return MicQueueModel.get().loadMicQueueList(roomInfo.getUid(), curPage, Constants.PAGE_SIZE) + .flatMap(info -> { + queueMicListInfo = info; + AvRoomDataManager.get().myIsInQueue = info.getMyPos() >= 0; + List list = info.getQueue(); + if (list == null) { + list = new ArrayList<>(); + } + return Single.just(list); + }); + } else { + return Single.error(new Throwable("没有房间信息")); + } + } + + private SpannableStringBuilder createBuilder(String normalText, String spannableText) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append(normalText); + SpannableString spannableString = new SpannableString(spannableText); + spannableString.setSpan( + new ForegroundColorSpan(getContext().getResources().getColor(R.color.appColor)), + 0, + spannableString.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.append(spannableString); + return builder; + } + + public void updateQueueInfo(RespQueuingMicListInfo info) { + if (info == null) { + return; + } + queueMicListInfo = info; + AvRoomDataManager.get().myIsInQueue = info.getMyPos() >= 0; + List list = queueMicListInfo.getQueue(); + if (list == null) { + list = new ArrayList<>(); + } + dataList = list; + adapter.setNewData(dataList); + if (!ListUtils.isListEmpty(list)) { + showHaveDataLayout(); + } else { + showNoDataLayout(); + } + loadPageDataHelper.setCurPage(Constants.PAGE_START + 1); + } + + public void removeQueueMember(String account) { + long removeUid = JavaUtil.str2long(account); + int removeIndex = -1; + int myQueuePos = -1; + for (int i = 0; i < dataList.size(); i++) { + if (dataList.get(i).getUid() == removeUid) { + removeIndex = i; + } + if (dataList.get(i).getUid() == AuthModel.get().getCurrentUid()) { + myQueuePos = i; + } + } + if (removeIndex >= 0) { + //判断自己的位置是否需要减一 + if (AvRoomDataManager.get().myIsInQueue) { + if (myQueuePos >= 0 && myQueuePos > removeIndex) { + int newMyPos = queueMicListInfo.getMyPos() - 1; + if (newMyPos < 1) { + newMyPos = 1; + } + queueMicListInfo.setMyPos(newMyPos); + } + } + dataList.remove(removeIndex); + adapter.notifyDataSetChanged(); + } + queueMicListInfo.setQueue(dataList); + reduceQueueInfo(); + if (dataList.size() == 0) { + showNoDataLayout(); + return; + } + setTopLayout(); + } + + /** + * 顶部的布局 + */ + private void setTopLayout() { + if (AvRoomDataManager.get().isManager()) { + if (queueMicListInfo != null) { + tvMicQueueTip.setText( + createBuilder( + context.getResources().getString(R.string.curr_queue_member_count), + String.valueOf(queueMicListInfo.getCount()) + ) + ); + } + } else { + if (queueMicListInfo != null) { + if (queueMicListInfo.getMyPos() < 0) { + tvMicQueueTip.setText(R.string.please_to_apply_queue); + } else { + tvMicQueueTip.setText( + createBuilder( + context.getResources().getString(R.string.my_pos_in_queue), + String.valueOf(queueMicListInfo.getMyPos()) + ) + ); + } + } + } + } + + @OnClick(R.id.tv_apply_mic_queue) + public void onViewClicked() { + if (queueMicListInfo == null) { + return; + } + //报名排麦 + if (AvRoomDataManager.get().isManager()) { + if (actionListener != null) { + actionListener.onShareRoom(MicQueueDialog.this); + } + } else { + if (actionListener != null) { + if (queueMicListInfo.getMyPos() < 0) { + if (!AvRoomDataManager.get().isQueuingMicro()) { + toast("排麦模式已关闭"); + return; + } + actionListener.onApplyMicQueue(MicQueueDialog.this); + } else { + actionListener.onCancelMicQueue(MicQueueDialog.this); + } + } + } + } + + /********************************回调*******************************************/ + + private OnActionListener actionListener; + + public interface OnActionListener { + void onShareRoom(MicQueueDialog micQueueDialog); + + void onApplyMicQueue(MicQueueDialog micQueueDialog); + + void onCancelMicQueue(MicQueueDialog micQueueDialog); + } + + public void setActionListener(OnActionListener actionListener) { + this.actionListener = actionListener; + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/NewUserTaskDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/NewUserTaskDialog.java new file mode 100644 index 000000000..cc5a9eb9e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/NewUserTaskDialog.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +import java.util.Timer; +import java.util.TimerTask; + +public class NewUserTaskDialog extends DialogFragment { + + private OnReceiveNewUserAwardListener onReceiveNewUserAwardListener; + private TextView button; + + public static NewUserTaskDialog newInstance(OnReceiveNewUserAwardListener onReceiveNewUserAwardListener) { + + Bundle args = new Bundle(); + NewUserTaskDialog fragment = new NewUserTaskDialog(); + fragment.setArguments(args); + if (onReceiveNewUserAwardListener != null) { + fragment.setOnReceiveNewUserAwardListener(onReceiveNewUserAwardListener); + } + return fragment; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Dialog dialog = super.onCreateDialog(savedInstanceState); + Window window = dialog.getWindow(); + if (window != null) { + WindowManager.LayoutParams wlp = window.getAttributes(); + wlp.gravity = Gravity.CENTER; + wlp.width = WindowManager.LayoutParams.MATCH_PARENT; + wlp.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(wlp); + + } + return dialog; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_new_user_task, container, false); + getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); + if (getDialog().getWindow() != null) { + getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent); + } + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + button = view.findViewById(R.id.tv_button); + button.setOnClickListener(v -> { + if (onReceiveNewUserAwardListener != null) { + onReceiveNewUserAwardListener.onReceiveAward(); + } + }); + } + + public void refreshDialogWithReceiveAwardFinish() { + button.setText("已经领取"); + button.setEnabled(false); + Timer t = new Timer(); + t.schedule(new TimerTask() { + public void run() { + if (isVisible()) { + dismiss(); + } + t.cancel(); + } + }, 3000); + } + + public interface OnReceiveNewUserAwardListener { + void onReceiveAward(); + } + + public void setOnReceiveNewUserAwardListener(OnReceiveNewUserAwardListener onReceiveNewUserAwardListener) { + this.onReceiveNewUserAwardListener = onReceiveNewUserAwardListener; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKMicQueueDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKMicQueueDialog.java new file mode 100644 index 000000000..627c18dd0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKMicQueueDialog.java @@ -0,0 +1,547 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.PKMicQueueAdapter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; +import com.yizhuan.erban.ui.widget.dialog.CommonLoadingDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKQueuingMicMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRespQueuingMicListInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPKInvitedUpMicMember; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Predicate; + +/** + * @author jack + * @Description + * @Date 2019/1/2 + */ +public class PKMicQueueDialog extends BaseDialog implements + LoadPageDataHelper.LoadData> { + + private FrameLayout flQueueCount; + private TextView tvMicQueueTip; + private FrameLayout flMainContent; + private SwipeRefreshLayout srlRefreshContainer; + private RecyclerView rvMicQueue; + private FrameLayout llNoDataContainer; + private TextView tvNoDataTip; + private FrameLayout flBottomButton; + private LinearLayout llJoinQueue; + private TextView tvJoinRed; + private TextView tvJoinBlue; + private TextView tvExitQueue; + private TextView tvShareRoom; + + private PKMicQueueAdapter adapter; + private LoadPageDataHelper> loadPageDataHelper; + private PKRespQueuingMicListInfo queueMicListInfo; + + private CompositeDisposable compositeDisposable = new CompositeDisposable(); + + private CommonLoadingDialog loadingDialog; + private String inviteAccount = ""; + + public PKMicQueueDialog(Context context) { + super(context, R.style.bottom_dialog); + loadPageDataHelper = new LoadPageDataHelper<>(this); + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams lps = window.getAttributes(); + lps.width = WindowManager.LayoutParams.MATCH_PARENT; + lps.height = WindowManager.LayoutParams.WRAP_CONTENT; + lps.gravity = Gravity.BOTTOM; + window.setAttributes(lps); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_pk_mic_queue); + + flQueueCount = (FrameLayout) findViewById(R.id.fl_queue_count); + tvMicQueueTip = (TextView) findViewById(R.id.tv_mic_queue_tip); + flMainContent = (FrameLayout) findViewById(R.id.fl_main_content); + srlRefreshContainer = (SwipeRefreshLayout) findViewById(R.id.srl_refresh_container); + rvMicQueue = (RecyclerView) findViewById(R.id.rv_mic_queue); + llNoDataContainer = (FrameLayout) findViewById(R.id.ll_no_data_container); + tvNoDataTip = (TextView) findViewById(R.id.tv_no_data_tip); + flBottomButton = (FrameLayout) findViewById(R.id.fl_bottom_button); + llJoinQueue = (LinearLayout) findViewById(R.id.ll_join_queue); + tvJoinRed = (TextView) findViewById(R.id.tv_join_red); + tvJoinBlue = (TextView) findViewById(R.id.tv_join_blue); + tvExitQueue = (TextView) findViewById(R.id.tv_exit_queue); + tvShareRoom = (TextView) findViewById(R.id.tv_share_room); + + + srlRefreshContainer.setOnRefreshListener(this::refreshData); + + rvMicQueue.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); + rvMicQueue.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(getContext(), 5), true)); + + adapter = new PKMicQueueAdapter(null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this::loadMoreData, rvMicQueue); + adapter.setOnUpMicListener(new PKMicQueueAdapter.OnUpMicListener() { + @Override + public void onUpMic(PKQueuingMicMemberInfo member, final int itemPos) { + long targetUid = member.getUid(); + if (AvRoomDataManager.get().isOnMic(member.getUid())) { + toast("TA已经在麦上了"); + return; + } + + if (!isTeamMemberCountUnderLimit(member.getGroupType())) { + toast("一个队伍不能超过4人哦"); + return; + } + + loadingDialog = new CommonLoadingDialog(getContext(), "邀请中...").showDialog(); + inviteAccount = String.valueOf(member.getUid()); + AvRoomDataManager.get().checkMemberInRoomById(targetUid) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + loadingDialog.dismiss(); + } + + @Override + public void onSuccess(ChatRoomMember mem) { + inviteToMic(member, itemPos); + } + }); + + } + }); + rvMicQueue.setAdapter(adapter); + + tvExitQueue.setOnClickListener(v -> { + if (actionListener != null && queueMicListInfo != null && queueMicListInfo.getMyPos() >= 0) { + actionListener.onCancelMicQueue(PKMicQueueDialog.this); + } + }); + + tvJoinRed.setOnClickListener(v -> { + if (actionListener != null && queueMicListInfo != null && queueMicListInfo.getMyPos() < 0) { + actionListener.onApplyMicQueue(PKMicQueueDialog.this, PKTeamInfo.TEAM_RED); + } + }); + + tvJoinBlue.setOnClickListener(v -> { + if (actionListener != null && queueMicListInfo != null && queueMicListInfo.getMyPos() < 0) { + actionListener.onApplyMicQueue(PKMicQueueDialog.this, PKTeamInfo.TEAM_BLUE); + } + }); + + tvShareRoom.setOnClickListener(v -> { + if (actionListener != null) { + actionListener.onShareRoom(PKMicQueueDialog.this); + } + }); + + + srlRefreshContainer.setRefreshing(true); + refreshData(); + } + + private boolean isTeamMemberCountUnderLimit(int groupType) { + int teamSize = 0; + for (PKMemberInfo pkMemberInfo : PkModel.get().getPkMemberInfoList()) { + if (pkMemberInfo.getTeamId() == groupType) { + teamSize++; + } + } + return teamSize < PkModel.TEAM_MAX_SIZE; + } + + @Override + protected void onStop() { + super.onStop(); + if (compositeDisposable != null) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + } + + public void addDisposable(Disposable disposable) { + compositeDisposable.add(disposable); + } + + @Override + public Single> loadData(int curPage) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + return PkModel.get().loadPKMicQueueList( + curPage, + Constants.PAGE_SIZE + ) + .flatMap(info -> { + queueMicListInfo = info; + AvRoomDataManager.get().myIsInQueue = info.getMyPos() >= 0; + List list = info.getQueue(); + if (list == null) { + list = new ArrayList<>(); + } + return Single.just(list); + }); + } else { + return Single.error(new Throwable("没有房间信息")); + } + } + + public void refreshData() { + if (loadPageDataHelper.isLoading()) { + srlRefreshContainer.setRefreshing(false); + return; + } + loadPageDataHelper.refreshData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onSuccess(List memberList) { + if (ListUtils.isListEmpty(memberList)) { + showNoDataLayout(); + } else { + showHaveDataLayout(); + adapter.setNewData(memberList); + } + srlRefreshContainer.setRefreshing(false); + } + + @Override + public void onError(Throwable e) { + srlRefreshContainer.setRefreshing(false); +// Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + } + + private void loadMoreData() { + loadPageDataHelper.loadMoreData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onSuccess(List userInfos) { + adapter.loadMoreComplete(); + if (!ListUtils.isListEmpty(userInfos)) { + adapter.addData(userInfos); + } else { + adapter.loadMoreEnd(); + } + } + + @Override + public void onError(Throwable e) { + adapter.loadMoreComplete(); +// Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + } + + public void updateQueueInfo(PKRespQueuingMicListInfo info) { + if (info == null) { + return; + } + queueMicListInfo = info; + AvRoomDataManager.get().myIsInQueue = info.getMyPos() >= 0; + List list = queueMicListInfo.getQueue(); + if (list == null) { + list = new ArrayList<>(); + } + adapter.setNewData(list); + if (!ListUtils.isListEmpty(list)) { + showHaveDataLayout(); + } else { + showNoDataLayout(); + } + loadPageDataHelper.setCurPage(Constants.PAGE_START + 1); + } + + + /** + * 抱TA上麦 + */ + private void inviteToMic(PKQueuingMicMemberInfo member, int itemPos) { + int micPosition = -1; + for (int i = 0; i < AvRoomDataManager.get().mMicQueueMemberMap.size(); i++) { + int key = AvRoomDataManager.get().mMicQueueMemberMap.keyAt(i); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(key); + //-1这个位置是 房主,不让上去 + //排麦模式下,选择被锁的坑,即是排麦坑才能上 + if (key != -1 && roomQueueInfo != null + && roomQueueInfo.mRoomMicInfo != null + && roomQueueInfo.mRoomMicInfo.isMicLock() + && roomQueueInfo.mChatRoomMember == null) { + micPosition = key; + break; + } + } + //房主的坑位key是-1 ,剩下的 8个坑的key从0 - 7 + if (micPosition != -1 && micPosition < 8) { + if (itemPos < adapter.getItemCount()) { + adapter.remove(itemPos); + adapter.notifyDataSetChanged(); + } + reduceQueueInfo(); + if (adapter.getData().size() == 0) { + showNoDataLayout(); + } else { + setTopLayout(); + } + + RoomPKInvitedUpMicMember upMicMember = new RoomPKInvitedUpMicMember(); + upMicMember.setUid(String.valueOf(member.getUid())); + upMicMember.setNick(member.getNick()); + upMicMember.setGroupType(member.getGroupType()); + upMicMember.setPosition(micPosition); + PkModel.get().inviteInTeam( + Collections.singletonList(upMicMember) + ) + .subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (throwable != null) { +// Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(throwable.getMessage()); + loadingDialog.dismiss(); + } + } + }); + + } else { + toast("麦上没空位啦"); + loadingDialog.dismiss(); + } + } + + /** + * 将队列减一 + */ + private void reduceQueueInfo() { + if (queueMicListInfo != null) { + int count = queueMicListInfo.getCount(); + count--; + if (count < 0) { + count = 0; + } + queueMicListInfo.setCount(count); + } + } + + + public void removeQueueMember(String account) { + long removeUid = JavaUtil.str2long(account); + int removeIndex = -1; + int myQueuePos = -1; + for (int i = 0; i < adapter.getData().size(); i++) { + if (adapter.getData().get(i).getUid() == removeUid) { + removeIndex = i; + } + if (adapter.getData().get(i).getUid() == AuthModel.get().getCurrentUid()) { + myQueuePos = i; + } + } + if (removeIndex >= 0) { + //判断自己的位置是否需要减一 + if (AvRoomDataManager.get().myIsInQueue) { + if (myQueuePos >= 0 && myQueuePos > removeIndex) { + int newMyPos = queueMicListInfo.getMyPos() - 1; + if (newMyPos < 1) { + newMyPos = 1; + } + queueMicListInfo.setMyPos(newMyPos); + } + } + adapter.getData().remove(removeIndex); + adapter.notifyDataSetChanged(); + } + queueMicListInfo.setQueue(adapter.getData()); + reduceQueueInfo(); + if (adapter.getData().size() == 0) { + showNoDataLayout(); + return; + } + setTopLayout(); + } + + private void showNoDataLayout() { + srlRefreshContainer.setVisibility(View.GONE); + llNoDataContainer.setVisibility(View.VISIBLE); + flBottomButton.setVisibility(View.VISIBLE); + llJoinQueue.setVisibility(View.VISIBLE); + if (AvRoomDataManager.get().isManager()) { + flQueueCount.setVisibility(View.GONE); + tvNoDataTip.setText(getContext().getResources().getString(R.string.manager_no_mic_queue_tip)); + llJoinQueue.setVisibility(View.GONE); + tvExitQueue.setVisibility(View.GONE); + tvShareRoom.setVisibility(View.VISIBLE); + } else { + tvExitQueue.setVisibility(View.GONE); + tvShareRoom.setVisibility(View.GONE); + flQueueCount.setVisibility(View.VISIBLE); + tvMicQueueTip.setText(R.string.apply_mic_queue_tip); + //点击报名 + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + llJoinQueue.setVisibility(View.VISIBLE); + } else { + tvJoinRed.setBackgroundResource(R.drawable.shape_pk_join_red_team_btn); + tvJoinBlue.setBackgroundResource(R.drawable.shape_pk_join_blue_team_btn); + } + tvNoDataTip.setText(getContext().getResources().getString(R.string.no_mic_queue_tip)); + } + } + + + private void showHaveDataLayout() { + srlRefreshContainer.setVisibility(View.VISIBLE); + llNoDataContainer.setVisibility(View.GONE); + setTopLayout(); + llJoinQueue.setVisibility(View.VISIBLE); + if (AvRoomDataManager.get().isManager()) { + flBottomButton.setVisibility(View.GONE); + } else { + tvShareRoom.setVisibility(View.GONE); + if (queueMicListInfo != null) { + flBottomButton.setVisibility(View.VISIBLE); + if (queueMicListInfo.getMyPos() < 0) { + //我不在队列 + //点击报名 + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + //如果我在麦上 设置不可点击 + llJoinQueue.setVisibility(View.VISIBLE); + tvExitQueue.setVisibility(View.GONE); + } else { + llJoinQueue.setVisibility(View.VISIBLE); + tvExitQueue.setVisibility(View.GONE); + } + } else { + //我在队列 + //取消报名 + llJoinQueue.setVisibility(View.GONE); + tvExitQueue.setVisibility(View.VISIBLE); + } + } + } + } + + /** + * 顶部的布局 + */ + private void setTopLayout() { + if (AvRoomDataManager.get().isManager()) { + if (queueMicListInfo != null) { + tvMicQueueTip.setText( + createBuilder( + getContext().getResources().getString(R.string.curr_queue_member_count), + String.valueOf(queueMicListInfo.getCount()) + ) + ); + } + } else { + if (queueMicListInfo != null) { + if (queueMicListInfo.getMyPos() < 0) { + tvMicQueueTip.setText(R.string.please_to_apply_queue); + } else { + tvMicQueueTip.setText( + createBuilder( + getContext().getResources().getString(R.string.my_pos_in_queue), + String.valueOf(queueMicListInfo.getMyPos()) + ) + ); + } + } + } + } + + private SpannableStringBuilder createBuilder(String normalText, String spannableText) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append(normalText); + SpannableString spannableString = new SpannableString(spannableText); + spannableString.setSpan( + new ForegroundColorSpan(getContext().getResources().getColor(R.color.appColor)), + 0, + spannableString.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.append(spannableString); + return builder; + } + + //人邀请上麦后回来 + public void onUpMicro(String account) { + if (inviteAccount.equals(account) && loadingDialog != null && loadingDialog.isShowing()) { + loadingDialog.dismiss(); + } + } + + + /********************************回调*******************************************/ + + private OnActionListener actionListener; + + public interface OnActionListener { + void onShareRoom(PKMicQueueDialog micQueueDialog); + + void onApplyMicQueue(PKMicQueueDialog micQueueDialog, int teamId); + + void onCancelMicQueue(PKMicQueueDialog micQueueDialog); + } + + public void setActionListener(OnActionListener actionListener) { + this.actionListener = actionListener; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKResultDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKResultDialog.java new file mode 100644 index 000000000..002edfb07 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKResultDialog.java @@ -0,0 +1,358 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamMember; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +/** + * @author jack + * @Description + * @Date 2019/1/4 + */ +public class PKResultDialog extends BaseDialog { + private final static int TEAM_RED = PKTeamInfo.TEAM_RED; + private final static int TEAM_BLUE = PKTeamInfo.TEAM_BLUE; + + private final static int PK_RESULT_VICTORY = 1; + private final static int PK_RESULT_FAIL = -1; + private final static int PK_RESULT_TIE = 0; + + private LinearLayout llGuardianName; + private LinearLayout llGuardianValue; + private LinearLayout llPkMember; + private LinearLayout llScore; + private ImageView ivResultBottom; + private ImageView ivResultTop; + private RecyclerView rvList; + private TextView tvScore; + private TextView tvGuardianName; + private TextView tvGuardianValue; + private TextView tvTeamStatus; + private TextView tvSeeOtherTeam; + private TextView tvTeamLose; + private LinearLayout llResultTie; + private TextView tvTieScore; + + private int pkResult = PK_RESULT_TIE; + private boolean isShowOpponent = false;//是否在显示对手 + private PkResultMemberAdapter adapter; + private RoomPkData roomPkData; + private PKTeamInfo teamInfo; + + public PKResultDialog(Context context, RoomPkData roomPkData) { + super(context, R.style.full_screen_dialog); + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams lps = window.getAttributes(); + lps.width = WindowManager.LayoutParams.MATCH_PARENT; + lps.height = WindowManager.LayoutParams.WRAP_CONTENT; + lps.gravity = Gravity.CENTER; + window.setAttributes(lps); + } + this.roomPkData = roomPkData; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_pk_result); + + llPkMember = (LinearLayout) findViewById(R.id.ll_pk_member); + llScore = (LinearLayout) findViewById(R.id.ll_score); + + ivResultBottom = (ImageView) findViewById(R.id.iv_result_bottom); + ivResultTop = (ImageView) findViewById(R.id.iv_result_top); + rvList = (RecyclerView) findViewById(R.id.rv_list); + + tvScore = (TextView) findViewById(R.id.tv_score); + llGuardianName = (LinearLayout) findViewById(R.id.ll_guardian_name); + llGuardianValue = (LinearLayout) findViewById(R.id.ll_guardian_value); + tvGuardianName = (TextView) findViewById(R.id.tv_guardian_name); + tvGuardianValue = (TextView) findViewById(R.id.tv_guardian_value); + tvTeamStatus = (TextView) findViewById(R.id.tv_team_status); + tvSeeOtherTeam = (TextView) findViewById(R.id.tv_see_other_team); + tvTeamLose = (TextView) findViewById(R.id.tv_team_lose); + + llResultTie = (LinearLayout) findViewById(R.id.ll_result_tie); + tvTieScore = (TextView) findViewById(R.id.tv_tie_score); + + + adapter = new PkResultMemberAdapter(null); + rvList.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + rvList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, Utils.dip2px(getContext(), 10), 0, true)); + rvList.setAdapter(adapter); + + tvSeeOtherTeam.setOnClickListener(v -> { + if (!isShowOpponent) { + showOpponentResult(); + } else { + showMyResult(); + } + }); + + init(); + } + + private void init() { + if (roomPkData == null) { + return; + } + if (roomPkData.getVoteMode() == RoomPkData.VOTE_MODE_PERSON) { + llGuardianName.setVisibility(View.GONE); + llGuardianValue.setVisibility(View.GONE); + } + int result = roomPkData.getResult(); + int teamId = findTeamIdByAccount(String.valueOf(AuthModel.get().getCurrentUid())); + if (teamId == PKTeamInfo.TEAM_NONE) { + //观众 + if (result == RoomPkData.PK_RESULT_DRAW) { + pkResult = PK_RESULT_TIE; + tvTeamStatus.setText("·势均力敌·"); + llPkMember.setVisibility(View.GONE); + llScore.setVisibility(View.GONE); + llGuardianName.setVisibility(View.GONE); + llGuardianValue.setVisibility(View.GONE); + llResultTie.setVisibility(View.VISIBLE); + tvTieScore.setText(roomPkData.getTeams().get(0).getScore() + ""); + refreshBgByStatus(); + } else { + pkResult = PK_RESULT_VICTORY; + teamInfo = findTeamByTeamId(result); + refreshView(pkResult, teamInfo); + + } + + } else { + //非观众 + teamInfo = findTeamByTeamId(teamId); + + if (result == RoomPkData.PK_RESULT_DRAW) { + pkResult = PK_RESULT_TIE; + tvTeamStatus.setText("·势均力敌·"); + tvScore.setText(teamInfo.getScore() + ""); + llGuardianName.setVisibility(View.GONE); + llGuardianValue.setVisibility(View.GONE); + tvTeamLose.setVisibility(View.GONE); + refreshView(pkResult, teamInfo); + + } else { + pkResult = teamId == result ? PK_RESULT_VICTORY : PK_RESULT_FAIL; + refreshView(pkResult, teamInfo); + } + } + } + + + private void showTeamMembers(PKTeamInfo teamInfo) { + List pkResultMembers = new ArrayList<>(); + for (PKTeamMember pkTeamMember : teamInfo.getTeamMembers()) { + PkResultMember resultMember = new PkResultMember(); + resultMember.avatar = pkTeamMember.getAvatar(); + resultMember.nick = pkTeamMember.getNick(); + resultMember.isMVP = pkTeamMember.getUid().equals(teamInfo.getMvp()); + pkResultMembers.add(resultMember); + } + adapter.setNewData(pkResultMembers); + } + + private void showColorByTeam(PKTeamInfo pkTeamInfo) { + if (pkTeamInfo.getTeam() == PKTeamInfo.TEAM_RED) { + tvScore.setTextColor(getContext().getResources().getColor(R.color.color_FD4D72)); + tvGuardianName.setTextColor(getContext().getResources().getColor(R.color.color_FD4D72)); + tvGuardianValue.setTextColor(getContext().getResources().getColor(R.color.color_FD4D72)); + tvTeamStatus.setTextColor(getContext().getResources().getColor(R.color.color_FD4D72)); + tvSeeOtherTeam.setTextColor(getContext().getResources().getColor(R.color.color_59B9FB)); + } else if (pkTeamInfo.getTeam() == PKTeamInfo.TEAM_BLUE) { + tvScore.setTextColor(getContext().getResources().getColor(R.color.color_59B9FB)); + tvGuardianName.setTextColor(getContext().getResources().getColor(R.color.color_59B9FB)); + tvGuardianValue.setTextColor(getContext().getResources().getColor(R.color.color_59B9FB)); + tvTeamStatus.setTextColor(getContext().getResources().getColor(R.color.color_59B9FB)); + tvSeeOtherTeam.setTextColor(getContext().getResources().getColor(R.color.color_FD4D72)); + } else { + //未知 + } + } + + private void refreshBgByStatus() { + if (pkResult == PK_RESULT_VICTORY) { + ivResultTop.setImageResource(R.mipmap.pk_result_victory_top); + ivResultBottom.setImageResource(R.mipmap.pk_result_victory_bottom); + } else if (pkResult == PK_RESULT_FAIL) { + ivResultTop.setImageResource(R.mipmap.pk_result_fail_top); + ivResultBottom.setImageResource(R.mipmap.pk_result_fail_bottom); + } else if (pkResult == PK_RESULT_TIE) { + ivResultTop.setImageResource(R.mipmap.pk_result_tie_top); + ivResultBottom.setImageResource(R.mipmap.pk_result_tie_bottom); + } + } + + private int findTeamIdByAccount(String account) { + for (PKTeamInfo pkTeamInfo : roomPkData.getTeams()) { + for (PKTeamMember pkTeamMember : pkTeamInfo.getTeamMembers()) { + if (pkTeamMember.getUid().equals(account)) { + return pkTeamInfo.getTeam(); + } + } + } + return 0; + } + + /** + * 反转队伍,状态 + */ + private void reverseTeamAndStatus() { + if (teamInfo.getTeam() == TEAM_RED) { + teamInfo = findTeamByTeamId(TEAM_BLUE); + } else if (teamInfo.getTeam() == TEAM_BLUE) { + teamInfo = findTeamByTeamId(TEAM_RED); + } + + if (pkResult == PK_RESULT_VICTORY) { + pkResult = PK_RESULT_FAIL; + } else if (pkResult == PK_RESULT_FAIL) { + pkResult = PK_RESULT_VICTORY; + } + } + + /** + * 显示本队的结果 + */ + private void showMyResult() { + if (isShowOpponent) { + isShowOpponent = false; + reverseTeamAndStatus(); + } + refreshView(pkResult, teamInfo); + } + + /** + * 显示对手队结果 + */ + private void showOpponentResult() { + isShowOpponent = true; + reverseTeamAndStatus(); + refreshView(pkResult, teamInfo); + } + + private void refreshView(int pkResult, PKTeamInfo teamInfo) { + refreshBgByStatus(); + showTeamMembers(teamInfo); + showColorByTeam(teamInfo); + + tvScore.setText(teamInfo.getScore() + ""); + + if (teamInfo.getProtector() != null && teamInfo.getProtector().getUid() != 0) { + tvGuardianName.setText(teamInfo.getProtector().getNick()); + tvGuardianValue.setText(teamInfo.getProtecScore() + ""); + } else { + tvGuardianName.setText("无"); + tvGuardianValue.setText("0"); + } + + int myTeamId = findTeamIdByAccount(String.valueOf(AuthModel.get().getCurrentUid())); + if (teamInfo.getTeam() == PKTeamInfo.TEAM_RED) { + + tvTeamStatus.setText("·红队战绩·"); + if (myTeamId == PKTeamInfo.TEAM_NONE) { + tvSeeOtherTeam.setText("查看蓝队战绩>"); + } else if (myTeamId == teamInfo.getTeam()) { + if (pkResult == PK_RESULT_VICTORY) { + tvTeamStatus.setText("·您胜利了·"); + } else if (pkResult == PK_RESULT_FAIL) { + tvTeamLose.setVisibility(View.VISIBLE); + } + tvSeeOtherTeam.setText("查看对方战绩>"); + } else { + tvSeeOtherTeam.setText("查看我的战绩>"); + } + } else if (teamInfo.getTeam() == PKTeamInfo.TEAM_BLUE) { + tvTeamStatus.setText("·蓝队战绩·"); + if (myTeamId == PKTeamInfo.TEAM_NONE) { + tvSeeOtherTeam.setText("查看红队战绩>"); + } else if (myTeamId == teamInfo.getTeam()) { + if (pkResult == PK_RESULT_VICTORY) { + tvTeamStatus.setText("·您胜利了·"); + } else if (pkResult == PK_RESULT_FAIL) { + tvTeamLose.setVisibility(View.VISIBLE); + } + tvSeeOtherTeam.setText("查看对方战绩>"); + } else { + tvSeeOtherTeam.setText("查看我的战绩>"); + } + } else { + tvTeamStatus.setText("·未知队战绩·"); + tvSeeOtherTeam.setVisibility(View.GONE); + } + + } + + @Data + class PkResultMember { + String avatar; + String nick; + boolean isMVP; + } + + class PkResultMemberAdapter extends BaseQuickAdapter { + + public PkResultMemberAdapter(@Nullable List data) { + super(R.layout.item_pk_result_member_rv, data); + } + + @Override + protected void convert(BaseViewHolder helper, PkResultMember item) { + CircleImageView avatar = helper.getView(R.id.civ_avatar); + GlideApp.with(avatar) + .load(item.avatar) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(avatar); + + helper.setVisible(R.id.iv_mvp_mark, item.isMVP); + } + } + + + private PKTeamInfo findTeamByTeamId(int teamId) { + if (roomPkData == null) { + return null; + } + for (PKTeamInfo pkTeamInfo : roomPkData.getTeams()) { + if (teamId == pkTeamInfo.getTeam()) { + return pkTeamInfo; + } + } + return null; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKScoreBoardDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKScoreBoardDialog.java new file mode 100644 index 000000000..1e4acca40 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKScoreBoardDialog.java @@ -0,0 +1,367 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.support.v7.widget.GridLayout; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; +import com.yizhuan.erban.ui.widget.dialog.CommonTipDialog; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.room.pk.bean.PKMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamMember; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.pk.event.PKDataUpdateEvent; +import com.yizhuan.xchat_android_core.room.pk.event.PKTimeFinishEvent; +import com.yizhuan.xchat_android_core.room.pk.event.PKTimeTickEvent; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2019/1/3 + */ +public class PKScoreBoardDialog extends BaseDialog { + + + private TextView tvPkVoteMode; + private TextView tvClose; + private ProgressBar pbScore; + private TextView tvRedTeamScore; + private TextView tvBlueTeamScore; + private TextView tvPkTimer; + private GridLayout glRedTeam; + private LinearLayout llRedTeamParticipant1; + private CircleImageView ivRedAvatar1; + private TextView tvRedName1; + private LinearLayout llRedTeamParticipant2; + private CircleImageView ivRedAvatar2; + private TextView tvRedName2; + private LinearLayout llRedTeamParticipant3; + private CircleImageView ivRedAvatar3; + private TextView tvRedName3; + private LinearLayout llRedTeamParticipant4; + private CircleImageView ivRedAvatar4; + private TextView tvRedName4; + private GridLayout glBlueTeam; + private LinearLayout llBlueTeamParticipant1; + private CircleImageView ivBlueAvatar1; + private TextView tvBlueName1; + private LinearLayout llBlueTeamParticipant2; + private CircleImageView ivBlueAvatar2; + private TextView tvBlueName2; + private LinearLayout llBlueTeamParticipant3; + private CircleImageView ivBlueAvatar3; + private TextView tvBlueName3; + private LinearLayout llBlueTeamParticipant4; + private CircleImageView ivBlueAvatar4; + private TextView tvBlueName4; + private TextView tvRestart; + + private List redTeamMembers = new ArrayList<>(); + private List redTeamAvatars = new ArrayList<>(); + private List redTeamNicks = new ArrayList<>(); + + private List blueTeamMembers = new ArrayList<>(); + private List blueTeamAvatars = new ArrayList<>(); + private List blueTeamNicks = new ArrayList<>(); + + private RoomPkData roomPkData; + + private CompositeDisposable compositeDisposable; + + public PKScoreBoardDialog(Context context) { + super(context, R.style.easy_dialog_style); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_pk_score_board); + + tvPkVoteMode = (TextView) findViewById(R.id.tv_pk_vote_mode); + tvClose = (TextView) findViewById(R.id.tv_close); + pbScore = (ProgressBar) findViewById(R.id.pb_score); + tvRedTeamScore = (TextView) findViewById(R.id.tv_red_team_score); + tvBlueTeamScore = (TextView) findViewById(R.id.tv_blue_team_score); + tvPkTimer = (TextView) findViewById(R.id.tv_pk_timer); + glRedTeam = (GridLayout) findViewById(R.id.gl_red_team); + llRedTeamParticipant1 = (LinearLayout) findViewById(R.id.ll_red_team_participant_1); + ivRedAvatar1 = (CircleImageView) findViewById(R.id.iv_red_avatar_1); + tvRedName1 = (TextView) findViewById(R.id.tv_red_name_1); + llRedTeamParticipant2 = (LinearLayout) findViewById(R.id.ll_red_team_participant_2); + ivRedAvatar2 = (CircleImageView) findViewById(R.id.iv_red_avatar_2); + tvRedName2 = (TextView) findViewById(R.id.tv_red_name_2); + llRedTeamParticipant3 = (LinearLayout) findViewById(R.id.ll_red_team_participant_3); + ivRedAvatar3 = (CircleImageView) findViewById(R.id.iv_red_avatar_3); + tvRedName3 = (TextView) findViewById(R.id.tv_red_name_3); + llRedTeamParticipant4 = (LinearLayout) findViewById(R.id.ll_red_team_participant_4); + ivRedAvatar4 = (CircleImageView) findViewById(R.id.iv_red_avatar_4); + tvRedName4 = (TextView) findViewById(R.id.tv_red_name_4); + glBlueTeam = (GridLayout) findViewById(R.id.gl_blue_team); + llBlueTeamParticipant1 = (LinearLayout) findViewById(R.id.ll_blue_team_participant_1); + ivBlueAvatar1 = (CircleImageView) findViewById(R.id.iv_blue_avatar_1); + tvBlueName1 = (TextView) findViewById(R.id.tv_blue_name_1); + llBlueTeamParticipant2 = (LinearLayout) findViewById(R.id.ll_blue_team_participant_2); + ivBlueAvatar2 = (CircleImageView) findViewById(R.id.iv_blue_avatar_2); + tvBlueName2 = (TextView) findViewById(R.id.tv_blue_name_2); + llBlueTeamParticipant3 = (LinearLayout) findViewById(R.id.ll_blue_team_participant_3); + ivBlueAvatar3 = (CircleImageView) findViewById(R.id.iv_blue_avatar_3); + tvBlueName3 = (TextView) findViewById(R.id.tv_blue_name_3); + llBlueTeamParticipant4 = (LinearLayout) findViewById(R.id.ll_blue_team_participant_4); + ivBlueAvatar4 = (CircleImageView) findViewById(R.id.iv_blue_avatar_4); + tvBlueName4 = (TextView) findViewById(R.id.tv_blue_name_4); + tvRestart = (TextView) findViewById(R.id.tv_restart); + + tvClose.setOnClickListener(v -> dismiss()); + + redTeamMembers.add(llRedTeamParticipant1); + redTeamMembers.add(llRedTeamParticipant2); + redTeamMembers.add(llRedTeamParticipant3); + redTeamMembers.add(llRedTeamParticipant4); + redTeamAvatars.add(ivRedAvatar1); + redTeamAvatars.add(ivRedAvatar2); + redTeamAvatars.add(ivRedAvatar3); + redTeamAvatars.add(ivRedAvatar4); + redTeamNicks.add(tvRedName1); + redTeamNicks.add(tvRedName2); + redTeamNicks.add(tvRedName3); + redTeamNicks.add(tvRedName4); + + blueTeamMembers.add(llBlueTeamParticipant1); + blueTeamMembers.add(llBlueTeamParticipant2); + blueTeamMembers.add(llBlueTeamParticipant3); + blueTeamMembers.add(llBlueTeamParticipant4); + blueTeamAvatars.add(ivBlueAvatar1); + blueTeamAvatars.add(ivBlueAvatar2); + blueTeamAvatars.add(ivBlueAvatar3); + blueTeamAvatars.add(ivBlueAvatar4); + blueTeamNicks.add(tvBlueName1); + blueTeamNicks.add(tvBlueName2); + blueTeamNicks.add(tvBlueName3); + blueTeamNicks.add(tvBlueName4); + + init(); + + } + + private void init() { + roomPkData = PkModel.get().getCurPkInfo(); + if (roomPkData == null) { + return; + } + if (roomPkData.getVoteMode() == RoomPkData.VOTE_MODE_GIFT) { + tvPkVoteMode.setText(String.format(getContext().getResources().getString(R.string.pk_score_board_type), + getContext().getResources().getString(R.string.vote_type_gift_value))); + } else if (roomPkData.getVoteMode() == RoomPkData.VOTE_MODE_PERSON) { + tvPkVoteMode.setText(String.format(getContext().getResources().getString(R.string.pk_score_board_type), + getContext().getResources().getString(R.string.vote_type_gift_member))); + } + + PKTeamInfo redTeam = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_RED); + for (int i = 0; i < redTeamMembers.size(); i++) { + if (i < redTeam.getTeamMembers().size()) { + redTeamMembers.get(i).setVisibility(View.VISIBLE); + PKTeamMember pkTeamMember = redTeam.getTeamMembers().get(i); + PKMemberInfo pkMemberInfo = findPKMemberInfo(pkTeamMember.getUid()); + if (pkMemberInfo == null || pkMemberInfo.getUserInfo() == null) { + continue; + } + redTeamNicks.get(i).setText(pkMemberInfo.getUserInfo().getNick()); + GlideApp.with(redTeamAvatars.get(i)) + .load(pkMemberInfo.getUserInfo().getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(redTeamAvatars.get(i)); + + } else { + redTeamMembers.get(i).setVisibility(View.GONE); + } + } + + PKTeamInfo blueTeam = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_BLUE); + for (int i = 0; i < blueTeamMembers.size(); i++) { + if (i < blueTeam.getTeamMembers().size()) { + blueTeamMembers.get(i).setVisibility(View.VISIBLE); + PKTeamMember pkTeamMember = blueTeam.getTeamMembers().get(i); + PKMemberInfo pkMemberInfo = findPKMemberInfo(pkTeamMember.getUid()); + if (pkMemberInfo == null || pkMemberInfo.getUserInfo() == null) { + continue; + } + blueTeamNicks.get(i).setText(pkMemberInfo.getUserInfo().getNick()); + GlideApp.with(blueTeamAvatars.get(i)) + .load(pkMemberInfo.getUserInfo().getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(blueTeamAvatars.get(i)); + + } else { + blueTeamMembers.get(i).setVisibility(View.GONE); + } + } + + if (AvRoomDataManager.get().isManager() && !SuperAdminUtil.isSuperAdmin()) { + tvRestart.setVisibility(View.VISIBLE); + tvRestart.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (PkModel.get().getCurPkInfo() == null) { + toast("PK已经不在"); + dismiss(); + return; + } + if (PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_AFTER_PK) { + toast("PK已经结束"); + dismiss(); + return; + } + CommonTipDialog tipDialog = new CommonTipDialog(getContext()); + tipDialog.setTipMsg("重新开始将会提前结束本次PK\n" + + "确认重新开始吗?"); + tipDialog.setOnActionListener( + new CommonTipDialog.OnActionListener() { + @Override + public void onOk() { + PkModel.get().toPKAgain().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + compositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + dismiss(); + StatisticManager.Instance().onEvent( + getContext(), + StatisticsProtocol.Event.ROOM_RESTART_PK, + "重新开始", + null); + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + } + ); + tipDialog.show(); + } + }); + } else { + tvRestart.setVisibility(View.GONE); + tvRestart.setOnClickListener(null); + } + updateTime(); + onPKDataUpdateEvent(null); + } + + private PKMemberInfo findPKMemberInfo(String account) { + for (PKMemberInfo pkMemberInfo : PkModel.get().getPkMemberInfoList()) { + if (String.valueOf(pkMemberInfo.getUserInfo().getUid()).equals(account)) { + return pkMemberInfo; + } + } + return null; + } + + + private void updateTime() { + roomPkData = PkModel.get().getCurPkInfo(); + if (roomPkData == null) { + return; + } + long pkTimeUntilEnd = roomPkData.getCurPkTimeUntilEnd(); + tvPkTimer.setText(String.format("%1$02d:%2$02d", pkTimeUntilEnd / 60, pkTimeUntilEnd % 60)); + } + + + @Override + protected void onStart() { + super.onStart(); + EventBus.getDefault().register(this); + compositeDisposable = new CompositeDisposable(); + compositeDisposable.add(IMNetEaseManager.get().getChatRoomEventObservable() + .subscribe(this::onReceiveRoomEvent)); + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.PK_INFO_UPDATE: + roomPkData = PkModel.get().getCurPkInfo(); + if (roomPkData != null && roomPkData.getPkStatus() == RoomPkData.PK_STATUS_BEFORE_PK) { + dismiss(); + } + break; + } + } + + @Override + protected void onStop() { + super.onStop(); + EventBus.getDefault().unregister(this); + compositeDisposable.dispose(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKDataUpdateEvent(PKDataUpdateEvent event) { + if (PkModel.get().getCurPkInfo() == null + || PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_AFTER_PK) { + dismiss(); + return; + } + + PKTeamInfo redTeam = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_RED); + PKTeamInfo blueTeam = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_BLUE); + if (redTeam == null || blueTeam == null) { + return; + } + long totalScore = redTeam.getScore() + blueTeam.getScore(); + if (totalScore > 0) { + tvRedTeamScore.setText(FormatUtils.formatToShortHalfUp(redTeam.getScore())); + tvBlueTeamScore.setText(FormatUtils.formatToShortHalfUp(blueTeam.getScore())); + int percent = (int) ((float) redTeam.getScore() / (float) totalScore * 100.0f); + pbScore.setProgress(percent); + } else { + pbScore.setProgress(50); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKTimeTickEvent(PKTimeTickEvent event) { + updateTime(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKTimeFinishEvent(PKTimeFinishEvent event) { + tvPkTimer.setText("00:00"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKSelectPeopleDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKSelectPeopleDialog.java new file mode 100644 index 000000000..0b02d658b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKSelectPeopleDialog.java @@ -0,0 +1,237 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.SparseArray; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.pk.bean.PKMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2019/1/2 + */ +public class PKSelectPeopleDialog extends BaseDialog implements View.OnClickListener { + + + private RecyclerView rvList; + private TextView tvOk; + MicAdapter micAdapter; + List micEntityList = new ArrayList<>(); + private int teamId = -1; + + private List pkMemberInfoList = new ArrayList<>(); + + public PKSelectPeopleDialog(Context context, int teamId, List pkMemberInfoList) { + super(context, R.style.easy_dialog_style); + this.teamId = teamId; + this.pkMemberInfoList = pkMemberInfoList; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_pk_select_people); + + rvList = (RecyclerView) findViewById(R.id.rv_list); + rvList.setLayoutManager(new GridLayoutManager(getContext(), 4)); + rvList.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + outRect.top = Utils.dip2px(getContext(), 8); + outRect.bottom = Utils.dip2px(getContext(), 8); + } + }); + for (int i = 0; i < 9; i++) { + micEntityList.add(new MicEntity()); + } + micAdapter = new MicAdapter(getContext(), micEntityList); + micAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + if (position == 0) { + return 4; + } + return 1; + } + }); + rvList.setAdapter(micAdapter); + tvOk = (TextView) findViewById(R.id.tv_ok); + tvOk.setOnClickListener(this); + + initData(); + } + + private void initData() { + SparseArray micQueue = AvRoomDataManager.get().mMicQueueMemberMap; + int[] keys = new int[micQueue.size()]; + for (int i = 0; i < micQueue.size(); i++) { + keys[i] = micQueue.keyAt(i); + } + Arrays.sort(keys); + for (int i = 0; i < keys.length; i++) { + RoomQueueInfo roomQueueInfo = micQueue.get(keys[i]); + ChatRoomMember chatRoomMember = roomQueueInfo.mChatRoomMember; + if (chatRoomMember != null) { + micEntityList.get(i).avatar = chatRoomMember.getAvatar(); + micEntityList.get(i).nick = chatRoomMember.getNick(); + micEntityList.get(i).uid = chatRoomMember.getAccount(); + micEntityList.get(i).gender = roomQueueInfo.gender; + micEntityList.get(i).isSelect = false; + micEntityList.get(i).unSelectable = false; + //已经加入队伍的显示已经选择 + if (isAddInTeam(teamId, chatRoomMember.getAccount())) { + micEntityList.get(i).isSelect = true; + } + //已经加其他入队伍的不显示选择 + if (isAddInTeam(-1, chatRoomMember.getAccount()) + && !isAddInTeam(teamId, chatRoomMember.getAccount())) { + micEntityList.get(i).unSelectable = true; + } + + } + } + micAdapter.notifyDataSetChanged(); + } + + /** + * @param teamId + * @param account + * @return + */ + private boolean isAddInTeam(int teamId, String account) { + for (PKMemberInfo createPKMember : pkMemberInfoList) { + if (teamId == -1) { + if (String.valueOf(createPKMember.getUserInfo().getUid()).equals(account)) { + return true; + } + } else { + if (createPKMember.getTeamId() == teamId + && String.valueOf(createPKMember.getUserInfo().getUid()).equals(account)) { + return true; + } + } + } + return false; + } + + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvOk.getId()) { + dismiss(); + if (onSelectPeopleListener != null) { + onSelectPeopleListener.onSelectPeople(micAdapter.getData()); + } + } + } + + + class MicAdapter extends BaseQuickAdapter { + + private Context context; + + public MicAdapter(Context context, @Nullable List data) { + super(R.layout.item_pk_select_people_rv, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, MicEntity item) { + + CircleImageView civAvatar = (CircleImageView) helper.getView(R.id.civ_avatar); + TextView tvSelectMark = (TextView) helper.getView(R.id.tv_select_mark); + TextView tvName = (TextView) helper.getView(R.id.tv_name); + + if (TextUtils.isEmpty(item.uid)) { + civAvatar.setImageResource(R.mipmap.bg_pk_select_people_seat); + tvName.setText(helper.getAdapterPosition() + "号麦位"); + tvSelectMark.setVisibility(View.GONE); + helper.itemView.setOnClickListener(null); + } else { + GlideApp.with(context) + .load(item.avatar) + .dontAnimate() + .placeholder(R.drawable.default_avatar) + .into(civAvatar); + tvName.setText(item.nick); + if (!item.unSelectable) { + tvSelectMark.setVisibility(View.VISIBLE); + tvSelectMark.setSelected(item.isSelect); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!item.isSelect && !isSelectUnderLimit()) { + toast("队伍人数已经达到上限"); + return; + } + micEntityList.get(helper.getAdapterPosition()).isSelect + = !micEntityList.get(helper.getAdapterPosition()).isSelect; + notifyItemChanged(helper.getAdapterPosition()); + } + }); + } else { + tvSelectMark.setVisibility(View.GONE); + tvSelectMark.setSelected(false); + helper.itemView.setOnClickListener(null); + } + } + + } + } + + private boolean isSelectUnderLimit() { + int selectSize = 0; + for (MicEntity micEntity : micEntityList) { + if (micEntity.isSelect) { + selectSize++; + } + } + return selectSize < PkModel.TEAM_MAX_SIZE; + } + + private OnSelectPeopleListener onSelectPeopleListener; + + public interface OnSelectPeopleListener { + void onSelectPeople(List userInfoList); + } + + public void setOnSelectPeopleListener(OnSelectPeopleListener onSelectPeopleListener) { + this.onSelectPeopleListener = onSelectPeopleListener; + } + + public class MicEntity { + public boolean unSelectable = false; + public boolean isSelect = false; + public String uid; + public String avatar; + public String nick; + public int gender; + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKTimePickerDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKTimePickerDialog.java new file mode 100644 index 000000000..ffd999826 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/PKTimePickerDialog.java @@ -0,0 +1,170 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import android.widget.Toast; + +import com.jzxiang.pickerview.adapters.AbstractWheelTextAdapter; +import com.jzxiang.pickerview.adapters.NumericWheelAdapter; +import com.jzxiang.pickerview.config.PickerConfig; +import com.jzxiang.pickerview.utils.PickerContants; +import com.jzxiang.pickerview.wheel.WheelView; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.dialog.BaseDialog; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/12/29 + */ +public class PKTimePickerDialog extends BaseDialog implements View.OnClickListener { + Context context; + + private TextView tvCancel; + private TextView tvOk; + private WheelView wvMinute; + private WheelView wvSecond; + + private NumericWheelAdapter minuteAdapter; + private SecondAdapter secondAdapter; + + private int selectMinute = 0; + private int selectSecond = 30; + + public PKTimePickerDialog(Context context) { + super(context, R.style.bottom_dialog); + this.context = context; + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams lps = window.getAttributes(); + lps.width = WindowManager.LayoutParams.MATCH_PARENT; + lps.height = WindowManager.LayoutParams.WRAP_CONTENT; + lps.gravity = Gravity.BOTTOM; + window.setAttributes(lps); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(false); + setContentView(R.layout.dialog_pk_pick_time); + + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvOk = (TextView) findViewById(R.id.tv_ok); + wvMinute = (WheelView) findViewById(R.id.wv_minute); + wvSecond = (WheelView) findViewById(R.id.wv_second); + + tvCancel.setOnClickListener(this); + tvOk.setOnClickListener(this); + + PickerConfig pickerConfig = new PickerConfig(); + pickerConfig.mWheelTVNormalColor = getContext().getResources().getColor(R.color.color_999999); + pickerConfig.mWheelTVSelectorColor = getContext().getResources().getColor(R.color.black); + pickerConfig.mWheelTVSize = 16; + pickerConfig.cyclic = true; + pickerConfig.mThemeColor = getContext().getResources().getColor(R.color.color_FFFFFF); + + minuteAdapter = new NumericWheelAdapter(getContext(), 0, 30, PickerContants.FORMAT, "分钟"); + minuteAdapter.setConfig(pickerConfig); + wvMinute.setConfig(pickerConfig); + wvMinute.setViewAdapter(minuteAdapter); + wvMinute.setCurrentItem(selectMinute, false); + wvMinute.setCyclic(pickerConfig.cyclic); + wvMinute.addChangingListener((wheel, oldValue, newValue) -> { + selectMinute = newValue; + if (selectMinute == 0) { + secondAdapter.setSecondSelectData(Collections.singletonList(30)); + wvSecond.setCurrentItem(0, false); + selectSecond = 30; + } else if (selectMinute == 30) { + secondAdapter.setSecondSelectData(Collections.singletonList(0)); + wvSecond.setCurrentItem(0, false); + selectSecond = 0; + } else { + secondAdapter.setSecondSelectData(Arrays.asList(0, 30)); + wvSecond.setCurrentItem(0, false); + selectSecond = 0; + } + }); + + PickerConfig secConfig = new PickerConfig(); + secConfig.mWheelTVNormalColor = getContext().getResources().getColor(R.color.color_999999); + secConfig.mWheelTVSelectorColor = getContext().getResources().getColor(R.color.black); + secConfig.mWheelTVSize = 16; + secConfig.cyclic = false; + secConfig.mThemeColor = getContext().getResources().getColor(R.color.color_FFFFFF); + + secondAdapter = new SecondAdapter(getContext()); + secondAdapter.setSecondSelectData(Collections.singletonList(30)); + secondAdapter.setConfig(secConfig); + wvSecond.setConfig(secConfig); + wvSecond.setViewAdapter(secondAdapter); + wvSecond.setCurrentItem(0, false); + wvSecond.setCyclic(false); + wvSecond.addChangingListener((wheel, oldValue, newValue) -> { + selectSecond = secondAdapter.date.get(newValue); + }); + } + + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvCancel.getId()) { + dismiss(); + } else if (id == tvOk.getId()) { + dismiss(); + Logger.i("当前选择时间 " + selectMinute + "分钟" + selectSecond + "秒", Toast.LENGTH_SHORT); + if (null != onSelectTime) { + onSelectTime.selectTime((long) (selectMinute * 60 + selectSecond)); + } + } + } + + private OnSelectTime onSelectTime; + + public interface OnSelectTime { + void selectTime(long timeSecond); + } + + public void setOnSelectTime(OnSelectTime onSelectTime) { + this.onSelectTime = onSelectTime; + } + + private class SecondAdapter extends AbstractWheelTextAdapter { + + List date = new ArrayList<>(); + + protected SecondAdapter(Context context) { + super(context); + } + + @Override + protected CharSequence getItemText(int index) { + return String.format("%02d", date.get(index)) + "秒"; + } + + @Override + public int getItemsCount() { + return date.size(); + } + + public void setSecondSelectData(List date) { + this.date = date; + notifyDataChangedEvent(); + notifyDataInvalidatedEvent(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomImposeDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomImposeDialog.java new file mode 100644 index 000000000..30ced4d12 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomImposeDialog.java @@ -0,0 +1,183 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.CpRoomInviteActivity; +import com.yizhuan.erban.avroom.widget.EditRoomTitleDialog; +import com.yizhuan.erban.databinding.DialogRoomImposeBinding; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; + +import io.reactivex.functions.Consumer; + +public class RoomImposeDialog extends BottomSheetDialog implements View.OnClickListener { + private Context context; + private DialogRoomImposeBinding binding; + + public RoomImposeDialog(Context context) { + super(context, R.style.ErbanBottomSheetDialogDimFalse); + this.context = context; + } + + @SuppressWarnings("ConstantConditions") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_room_impose); + binding = DataBindingUtil.bind(findViewById(R.id.dialog_container)); + binding.setClick(this); + + FrameLayout bottomSheet = findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + BottomSheetBehavior.from(bottomSheet).setPeekHeight( + UIUtil.dip2px(context, 270) + + (Utils.hasSoftKeys(context) ? Utils.getNavigationBarHeight(context) : 0)); + } + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + getWindow().setWindowAnimations(R.style.ErbanCommonWindowAnimationStyle); + + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + if ("lock".equals(roomInfo.getLimitType()) || !TextUtils.isEmpty(roomInfo.roomPwd)) { + binding.tvPwd.setTextColor(context.getResources().getColor(R.color.appColor)); + } else if ("isFriend".equals(roomInfo.getLimitType())) { + binding.tvFriend.setTextColor(context.getResources().getColor(R.color.appColor)); + } else if ("isInvite".equals(roomInfo.getLimitType())) { + binding.tvInvite.setTextColor(context.getResources().getColor(R.color.appColor)); + } + } + + @Override + public void onClick(View v) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + switch (v.getId()) { + case R.id.tv_invite: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_roomlimit_invitation_click, "仅邀请进入"); + + context.startActivity(new Intent(context, CpRoomInviteActivity.class)); + dismiss(); + // updateRoomInfo("", roomInfo,RoomInfo.IS_INVITE); + break; + case R.id.tv_friend: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_roomlimit_friends_click, "仅好友进入"); + + updateRoomInfo("", roomInfo, RoomInfo.IS_FRIEND); + break; + case R.id.tv_pwd: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_roomlimit_password_click, "仅密码进入"); + + String oldContent = ""; + try { + oldContent = DESUtils.DESAndBase64Decrypt(roomInfo.roomPwd); + } catch (Exception e) { + e.printStackTrace(); + } + EditRoomTitleDialog pwdDialog = new EditRoomTitleDialog(context, + EditRoomTitleDialog.TYPE_EDIT_PASSWORD, oldContent); + pwdDialog.setOnEditTitleListner(new EditRoomTitleDialog.OnEditTitleListner() { + @Override + public void onEditPwdListner(String newPwd) { + String encryptPwd = DESUtils.DESAndBase64(newPwd); + + if (encryptPwd.equals(roomInfo.getRoomPwd())) { + return; + } + updateRoomInfo(encryptPwd, roomInfo, RoomInfo.LOCK); + } + }); + pwdDialog.show(); + break; + case R.id.tv_cancel_limit: + updateRoomInfo("", roomInfo, ""); + break; + case R.id.btn_cancel: + dismiss(); + break; + } + } + + private void updateRoomInfo(String encryptPwd, RoomInfo roomInfo, String limitType) { + //更新房间接口调用成功后,会发事件RoomEvent.ROOM_INFO_UPDATE + RoomSettingModel model = new RoomSettingModel(); + // if (AvRoomDataManager.get().isRoomOwner()){ + model.updateRoomInfo(roomInfo.title, + roomInfo.getRoomDesc(), + roomInfo.getIntroduction(), + encryptPwd, + roomInfo.getRoomTag(), + roomInfo.tagId, + AuthModel.get().getCurrentUid(), + AuthModel.get().getTicket(), + roomInfo.isHasAnimationEffect(), + roomInfo.getAudioQuality(), + limitType, + roomInfo.isPureMode()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(RoomInfo roomInfo, String error) { + super.accept(roomInfo, error); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + if (!limitType.equals(RoomInfo.IS_INVITE)) { + SingleToastUtil.showToast("设置成功"); + } + } + + } + }); +// }else { +// model.updateByAdmin(roomInfo.getUid(),roomInfo.title, +// roomInfo.getRoomDesc(), +// encryptPwd, +// roomInfo.getRoomTag(), +// roomInfo.tagId, +// AuthModel.get().getCurrentUid(), +// AuthModel.get().getTicket(), +// roomInfo.isHasAnimationEffect(), +// roomInfo.getAudioQuality(), +// limitType) +// .subscribe(new Consumer() { +// @Override +// public void accept(RoomInfo roomInfo) throws Exception { +// if (!limitType.equals(RoomInfo.IS_INVITE)){ +// SingleToastUtil.showToast("设置成功"); +// } +// } +// }); +// } + + dismiss(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java new file mode 100644 index 000000000..11ef8cc79 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java @@ -0,0 +1,467 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetDialog; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.module_hall.HallDataManager; +import com.yizhuan.erban.module_hall.hall.adapter.OptionAdapter; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.erban.ui.widget.recyclerview.layoutmanager.FullyGridLayoutManager; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + + +/** + * 房间操作dialog + * Created by lvzebiao on 2018/11/15. + */ + +public class RoomOperationDialog extends BottomSheetDialog { + + @BindView(R.id.rv_opt_list) + RecyclerView rvOPtList; + + private Context context; + private Unbinder unbinder; + private OptAdapter optAdapter; + public RoomOperationDialog(@NonNull Context context) { + super(context, R.style.ErbanBottomSheetDialogDimFalse); + this.context = context; + } + + @SuppressWarnings("ConstantConditions") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_room_operation); + unbinder = ButterKnife.bind(this); + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + + init(); + } + + private void init() { + + rvOPtList.addItemDecoration(new ColorDecoration( + Color.TRANSPARENT, + Utils.dip2px(getContext(), 10), + Utils.dip2px(getContext(), 20), + true)); + rvOPtList.setLayoutManager(new FullyGridLayoutManager(getContext(), 5)); + optAdapter = new OptAdapter(context, null); + addPKAction(optAdapter); + addKTVAction(optAdapter); + addGameAction(optAdapter); + addRoomLimit(optAdapter); + addGiftEffectAction(optAdapter); + addOpenOrClosePublicScreenAction(optAdapter); + addGiftValueAction(optAdapter); + addRoomSettingAction(optAdapter); + addRoomModuleHallAction(optAdapter); +// addRoomManagerAction(optAdapter); + addSuperAdminAction(optAdapter); + rvOPtList.setAdapter(optAdapter); + + } + + private void addGameAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + if (ImGameMode.gameSwitch && !AvRoomDataManager.get().isCpRoom() + && !MarketVerifyModel.get().isMarketChecking()) { + optAdapter.addData(new OptAction(R.drawable.room_ic_opera_game, + "游戏", + () -> { + if (onActionListener != null) { + onActionListener.onGameAction(); + } + })); + } + } + + + /** + * PK 模式 + * + * @param optAdapter + */ + private void addPKAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + if (AvRoomDataManager.get().isManager() && !AvRoomDataManager.get().isCpRoom()) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + String str = AvRoomDataManager.get().isOpenPKMode() ? + getContext().getResources().getString(R.string.room_was_in_PK) : + getContext().getResources().getString(R.string.room_PK_mode); + int icon = AvRoomDataManager.get().isOpenPKMode() ? + R.drawable.ic_room_opt_op_pk : + R.drawable.ic_room_opt_in_pk; + optAdapter.addData(new OptAction(icon, + str, + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onPKAction(); + } + } + })); + } + + } + + /** + * 添加KTV 操作 + * + * @param optAdapter + */ + private void addKTVAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + //添加 + if (AvRoomDataManager.get().hasKTVPriv()) { + if (AvRoomDataManager.get().isOpenKTV()) { + optAdapter.addData(new OptAction(R.drawable.ic_room_opt_ktv_select_song, + getContext().getResources().getString(R.string.KTV_ing), + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onRoomKTV(); + } + } + })); + + } else { + //如果不是ktv房间,只有管理有ktv按钮 + if (AvRoomDataManager.get().isManager()) { + optAdapter.addData(new OptAction(R.drawable.ic_room_opt_ktv, + getContext().getResources().getString(R.string.KTV), + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onRoomKTV(); + } + } + })); + } + } + } + } + + /** + * 添加房间限制 + * + * @param optAdapter + */ + private void addRoomLimit(OptAdapter optAdapter) { + //添加 + if (AvRoomDataManager.get().isRoomOwner() && AvRoomDataManager.get().isCpRoom()) { + optAdapter.addData(new OptAction(R.drawable.icon_room_limit, + "进房限制", + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onRoomLimit(); + } + } + })); + + } + } + /** + * 礼物特效 + * + * @param optAdapter + */ + private void addGiftEffectAction(OptAdapter optAdapter) { + boolean effect = AvRoomDataManager.get().mIsNeedGiftEffect; + String text = effect ? + context.getResources().getString(R.string.close_my_effect) : + context.getResources().getString(R.string.open_my_effect); + + int icon = effect ? + R.drawable.icon_close_my_effect : + R.drawable.icon_open_my_effect; + optAdapter.addData(new OptAction(icon, + text, + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onSwitchGiftEffect(); + } + } + })); + } + + /** + * 公屏开关 + * + * @param optAdapter + */ + private void addOpenOrClosePublicScreenAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + //超管能开关公屏 + } else { + if (!AvRoomDataManager.get().isManager()) { + return; + } + } + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + boolean isCloseScreen = roomInfo.isCloseScreen(); + String text = isCloseScreen ? + context.getResources().getString(R.string.open_public_screen) : + context.getResources().getString(R.string.close_public_screen); + + int icon = isCloseScreen ? + R.drawable.icon_open_public_screen : + R.drawable.icon_close_public_screen; + + optAdapter.addData(new OptAction(icon, + text, + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onSwitchPublicScreen(); + } + } + })); + + } + + /** + * 礼物值 + */ + private void addGiftValueAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + if (AvRoomDataManager.get().isCpRoom()) { + return; + } + if (!AvRoomDataManager.get().isManager()) { + return; + } + if (AvRoomDataManager.get().isOpenKTV()) { + return; + } + boolean openGiftValue = AvRoomDataManager.get().isShowGiftValue(); + optAdapter.addData(new OptAction( + openGiftValue ? R.drawable.icon_close_gift_value : R.drawable.icon_open_gift_value, + getContext().getResources().getString( + openGiftValue ? R.string.close_gift_value_text : R.string.open_gift_value_text), + () -> { + if (onActionListener != null) { + onActionListener.onGiftValue(); + } + })); + } + + /** + * 房间设置 + * + * @param optAdapter + */ + private void addRoomSettingAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + if (AvRoomDataManager.get().isManager()) { + optAdapter.addData(new OptAction(R.drawable.icon_room_setting, + getContext().getResources().getString(R.string.room_setting), () -> { + if (onActionListener != null) { + onActionListener.onSetting(); + } + })); + } + } + + /** + * 房间管理员 + * + * @param optAdapter + */ + private void addRoomManagerAction(OptAdapter optAdapter) { + if (!AvRoomDataManager.get().isRoomOwner() || AvRoomDataManager.get().isCpRoom()) { + return; + } + optAdapter.addData(new OptAction(R.drawable.icon_room_admin, + getContext().getResources().getString(R.string.team_admin), + new OptAction.OnAction() { + @Override + public void onAction() { + if (onActionListener != null) { + onActionListener.onRoomAdmin(); + } + } + })); + } + + /** + * 厅管理 + */ + private void addRoomModuleHallAction(OptAdapter optAdapter) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null || HallDataManager.get().getOwnerUid() != AvRoomDataManager.get().mCurrentRoomInfo.getUid()) + return; + + optAdapter.addData(new OptAction(R.drawable.icon_room_module_hall, + getContext().getResources().getString(R.string.label_room_hall_manage), + () -> { + if (onActionListener != null) { + onActionListener.onRoomHall(); + } + } + )); + } + + /** + * 超管管理 + */ + private void addSuperAdminAction(OptAdapter optAdapter) { + if (!SuperAdminUtil.isSuperAdmin()) { + return; + } + optAdapter.addData(new OptAction(R.drawable.icon_room_super_admin, + getContext().getResources().getString(R.string.sa_label_room_super_a_manager), + true, + () -> { + if (onActionListener != null) { + onActionListener.onSuperAdmin(); + } + } + )); + } + + @Override + protected void onStop() { + super.onStop(); + unbinder.unbind(); + this.onActionListener = null; + } + + private OnActionListener onActionListener; + + public interface OnActionListener { + void onSwitchGiftEffect(); + + void onSwitchPublicScreen(); + + void onSetting(); + + void onRoomLimit(); + + void onRoomAdmin(); + + void onRoomKTV(); + + void onPKAction(); + + void onGameAction(); + + void onRoomHall(); + + void onGiftValue(); + + void onSuperAdmin(); + } + + public void setOnActionListener(OnActionListener onActionListener) { + this.onActionListener = onActionListener; + } + + + static class OptAction { + private int icon; + private String name; + private OnAction onAction; + private boolean isAppColor; + + interface OnAction { + void onAction(); + } + + public OptAction(int icon, String name, OnAction onAction) { + this(icon, name, false, onAction); + } + + public OptAction(int icon, String name, boolean isAppColor, OnAction onAction) { + this.icon = icon; + this.name = name; + this.isAppColor = isAppColor; + this.onAction = onAction; + } + + } + + private class OptAdapter extends BaseQuickAdapter { + + private Context context; + + OptAdapter(Context context, @Nullable List data) { + super(R.layout.item_room_opt_dialog, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, OptAction item) { + helper.setText(R.id.tv_name, item.name) + .setImageResource(R.id.iv_icon, item.icon) + .setTextColor(R.id.tv_name, context.getResources().getColor( + item.isAppColor ? R.color.appColor : R.color.white_transparent_50)); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + item.onAction.onAction(); + dismiss(); + } + }); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationVm.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationVm.java new file mode 100644 index 000000000..491d191df --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationVm.java @@ -0,0 +1,60 @@ +package com.yizhuan.erban.avroom.dialog; + +import android.arch.lifecycle.MutableLiveData; +import android.content.Context; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; + +/** + * Created by lvzebiao on 2018/11/15. + */ + +public class RoomOperationVm { + + public final MutableLiveData isRoomOwnerOrAdmin = new MutableLiveData<>(); + + public final MutableLiveData isRoomOwner = new MutableLiveData<>(); + /** + * 礼物特效 + */ + public final MutableLiveData openOrCloseEffect = new MutableLiveData<>(); + /** + * 开关公屏 + */ + public final MutableLiveData openOrClosePublicScreen = new MutableLiveData<>(); + + public ObservableBoolean showLimitType = new ObservableBoolean(false); + public ObservableField roomInfo = new ObservableField<>(); + private Context context; + + public RoomOperationVm(Context context) { + this.context = context; + long currentUid = AuthModel.get().getCurrentUid(); + boolean isRoomOwner = AvRoomDataManager.get().isRoomOwner(currentUid); + boolean isRoomAdmin = AvRoomDataManager.get().isRoomAdmin(currentUid); + this.isRoomOwner.setValue(isRoomOwner); + isRoomOwnerOrAdmin.setValue(isRoomOwner || isRoomAdmin); + boolean effect = AvRoomDataManager.get().mIsNeedGiftEffect; + String text = effect ? + context.getResources().getString(R.string.close_my_effect) : + context.getResources().getString(R.string.open_my_effect); + openOrCloseEffect.setValue(text); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + this.roomInfo.set(roomInfo); + showLimitType.set(roomInfo.getType() == RoomInfo.ROOMTYPE_CP && isRoomOwner); + boolean isCloseScreen = roomInfo.isCloseScreen(); + text = isCloseScreen ? + context.getResources().getString(R.string.open_public_screen) : + context.getResources().getString(R.string.close_public_screen); + openOrClosePublicScreen.setValue(text); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/AbsRoomFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/AbsRoomFragment.java new file mode 100644 index 000000000..b19234427 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/AbsRoomFragment.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.avroom.fragment; + +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; + +import java.util.List; + +/** + * @author chenran + * @date 2017/8/8 + */ + +public abstract class AbsRoomFragment extends BaseFragment { + + + public abstract void onShowActivity(List dialogInfo); + + + public void onRoomOnlineNumberSuccess(int onlineNumber) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/DialogWebFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/DialogWebFragment.java new file mode 100644 index 000000000..84708b5bd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/DialogWebFragment.java @@ -0,0 +1,391 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; +import android.net.http.SslError; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.webkit.SslErrorHandler; +import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ImageView; +import android.widget.ProgressBar; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.JSInterface; +import com.yizhuan.erban.ui.webview.event.CloseDialogWebViewEvent; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.WebViewUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +public class DialogWebFragment extends DialogFragment { + + + private WebView webView; + + private ImageView ivClose; + + private Context context; + + private int mPosition; + private String url; + private String targetUrl; + + private WebChromeClient wvcc; + private ValueCallback mUploadMessage; + private ValueCallback mUploadMessage5; + public static final int FILECHOOSER_RESULTCODE = 5173; + public static final int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 5174; + + private boolean isDestroyView = false; + + public static DialogWebFragment newInstance(String url) { + + Bundle args = new Bundle(); + args.putString("url", url); + DialogWebFragment fragment = new DialogWebFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.context = context; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onStart() { + super.onStart(); + try { + Window win = getDialog().getWindow(); + if (win == null) { + return; + } + win.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparent))); + WindowManager.LayoutParams layoutParams = getDialog().getWindow().getAttributes(); + DisplayMetrics dm = new DisplayMetrics(); + Display d = win.getWindowManager().getDefaultDisplay(); + d.getRealMetrics(dm); + if (getActivity() == null) { + return; + } + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + layoutParams.width = dm.widthPixels; + layoutParams.dimAmount = 0.0f; //背景透明 + win.setAttributes(layoutParams); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Dialog dialog = super.onCreateDialog(savedInstanceState); + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + //禁止bottomSheetDialogFragment的拖动效果 +// dialog.setOnShowListener(dialog1 -> { +// try { +// BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog1; +// Field behaviorField = bottomSheetDialog.getClass().getDeclaredField("mBehavior"); +// behaviorField.setAccessible(true); +// final BottomSheetBehavior behavior = (BottomSheetBehavior) behaviorField.get(bottomSheetDialog); +// behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { +// +// @Override +// public void onStateChanged(@NonNull View bottomSheet, int newState) { +// if (newState == BottomSheetBehavior.STATE_DRAGGING) { +// behavior.setState(BottomSheetBehavior.STATE_EXPANDED); +// } +// } +// +// @Override +// public void onSlide(@NonNull View bottomSheet, float slideOffset) { +// } +// }); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// }); + //不监听返回键 + dialog.setOnKeyListener((dialog12, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 + && event.getAction() == KeyEvent.ACTION_DOWN) { + //onBackPressed(); + return true; + } + return false; + }); + + return dialog; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_dialog_web, container, false); + View llContainer = view.findViewById(R.id.ll_container); + ViewGroup.LayoutParams params = llContainer.getLayoutParams(); + params.height = (UIUtil.getScreenWidth(context) - UIUtil.dip2px(context, 40)) * 4 / 3; + llContainer.setLayoutParams(params); + webView = view.findViewById(R.id.webview); + ivClose = view.findViewById(R.id.iv_close); + EventBus.getDefault().register(this); + return view; + } + + @Override + public void onDestroyView() { + isDestroyView = true; + EventBus.getDefault().unregister(this); + LogUtil.print("dialog-onDestroyView"); + super.onDestroyView(); + } + + public void show(FragmentManager manager) { + show(manager, DialogWebFragment.class.getSimpleName()); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(); + } + + private void initView() { + if (getArguments() != null) { + url = getArguments().getString("url"); + } + + ivClose.setOnClickListener(v -> dismiss()); + + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setUseWideViewPort(true); + // 设置 WebView 可以在 HTTPS 通道上加载 HTTP 资源,Android 4.4 后的暗坑 + // 因为 Android 4.4 后默认不允许在 HTTPS 通道上加载 HTTP 资源 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + } + webView.getSettings().setTextZoom(100); + JSInterface jsInterface = new JSInterface(webView, context); + jsInterface.setPosition(mPosition); + webView.addJavascriptInterface(jsInterface, "androidJsObj"); + webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); + webView.setWebViewClient(new WebViewClient() { + + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Logger.e("shouldOverrideUrlLoading--------" + url); + LogUtil.e("shouldOverrideUrlLoading" + url); + targetUrl = url; + //modules/noble/paySuccess.html + //modules/noble/order.html?nobleIndex=1 // 获取上下文, H5PayDemoActivity为当前页面 + // ------ 对alipays:相关的scheme处理 ------- + if (url.startsWith("alipays:") || url.startsWith("alipay")) { + try { + context.startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url))); + } catch (Exception e) { + new AlertDialog.Builder(context) + .setMessage("未检测到支付宝客户端,请安装后重试。") + .setPositiveButton("立即安装", (dialog, which) -> { + Uri alipayUrl = Uri.parse("https://d.alipay.com"); + context.startActivity(new Intent("android.intent.action.VIEW", alipayUrl)); + }).setNegativeButton("取消", null).show(); + } + return true; + } + if (url.contains("tel:")) { + //删除直接拨打电话的功能 + return true; + } + // ------- 处理结束 ------- + + if (!(url.startsWith("http") || url.startsWith("https"))) { + return true; + } + + view.loadUrl(url); + return true; + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { +// super.onReceivedSslError(view, handler, error); //一定要去掉 + // handler.cancel();// Android默认的处理方式 + handler.proceed();// 接受所有网站的证书 + // handleMessage(Message msg);// 进行其他处理 + } + + @Override + public void onPageFinished(WebView view, String url) { + Logger.e("onPageFinished--------" + url); + //界面被销毁,则不需要执行view动作了 + super.onPageFinished(view, url); + } + }); + //获取webviewtitle作为titlebar的title + wvcc = new WebChromeClient() { + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + } + + // For Android >= 4.1 + public void openFileChooser(ValueCallback uploadMsg, + String acceptType, String capture) { + mUploadMessage = uploadMsg; + Intent i = new Intent(Intent.ACTION_GET_CONTENT); + i.addCategory(Intent.CATEGORY_OPENABLE); + i.setType("*/*"); + startActivityForResult(Intent.createChooser(i, "File Browser"), + FILECHOOSER_RESULTCODE); + } + + // For Lollipop 5.0+ Devices + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public boolean onShowFileChooser(WebView mWebView, + ValueCallback filePathCallback, + FileChooserParams fileChooserParams) { + if (mUploadMessage5 != null) { + mUploadMessage5.onReceiveValue(null); + mUploadMessage5 = null; + } + mUploadMessage5 = filePathCallback; + Intent intent = fileChooserParams.createIntent(); + try { + startActivityForResult(intent, + FILECHOOSER_RESULTCODE_FOR_ANDROID_5); + } catch (ActivityNotFoundException e) { + mUploadMessage5 = null; + return false; + } + return true; + } + + }; + // 设置setWebChromeClient对象 + webView.setWebChromeClient(wvcc); + // 设置Webview的user-agent + webView.getSettings().setUserAgentString(webView.getSettings().getUserAgentString() + " tutuAppAndroid erbanAppAndroid"); + if (!TextUtils.isEmpty(url)) { + webView.loadUrl(url); + } + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if (requestCode == FILECHOOSER_RESULTCODE) { + if (null == mUploadMessage) { + return; + } + Uri result = intent == null || resultCode != Activity.RESULT_OK ? null + : intent.getData(); + mUploadMessage.onReceiveValue(result); + mUploadMessage = null; + } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) { + if (null == mUploadMessage5) { + return; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mUploadMessage5.onReceiveValue(WebChromeClient.FileChooserParams + .parseResult(resultCode, intent)); + } + mUploadMessage5 = null; + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCloseDialogWebViewEvent(CloseDialogWebViewEvent event) { + dismiss(); + } + + public void onBackPressed() { + if (webView.canGoBack()) { + if (!TextUtils.isEmpty(targetUrl) && targetUrl.contains("modules/nobles/paySuccess.html")) { + dismiss(); + } else + webView.goBack(); + } else { + dismiss(); + } + } + + @Override + public void dismiss() { + try { + super.dismiss(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * 清除h5的一些定时器 + */ + private void clearWebActCache() { + try { + String call = "javascript:clearFun()"; + if (webView != null) { + webView.loadUrl(call); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void onDetach() { + super.onDetach(); + WebViewUtils.releaseWeb(webView); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java new file mode 100644 index 000000000..5707b5b16 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java @@ -0,0 +1,991 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.content.res.AssetFileDescriptor; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.AppCompatImageView; +import android.text.Html; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewStub; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.activity.RoomOnlineUserActivity; +import com.yizhuan.erban.avroom.presenter.HomePartyPresenter; +import com.yizhuan.erban.treasure_box.widget.GoldBoxHelper; +import com.yizhuan.erban.avroom.widget.GiftV2View; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.FragmentChatroomGameMainBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftMultiReceiverInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiveInfo; +import com.yizhuan.xchat_android_core.gift.bean.MultiGiftReceiveInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomInfoAttachment; +import com.yizhuan.xchat_android_core.magic.bean.MagicReceivedInfo; +import com.yizhuan.xchat_android_core.magic.bean.MultiMagicReceivedInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.SimplePartyRoomInfo; +import com.yizhuan.xchat_android_core.room.game.GameEvent; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.queuing_mic.event.HasAnimationEffect; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import cn.sharesdk.framework.Platform; +import io.reactivex.Observable; +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; +import nl.dionsegijn.konfetti.models.Shape; +import nl.dionsegijn.konfetti.models.Size; + +/** + * 轰趴房 + * Created by 2016/9/22. + * + * @author Administrator + */ +public class HomePartyFragment extends AbsRoomFragment implements View.OnClickListener, ShareDialog.OnShareDialogItemClick { + public static final int SELECT_DEFAULT = -1; + public static final int SELECT_ONLINE_LIST = 0; + public static final int SELECT_CONTRIBUTE_LIST = 1; + + private HomePartyRoomFragment roomFragment; + private HomePartyUserListFragment listFragment; + + private TextView roomTitle; + private TextView roomId; + private AppCompatImageView mIvGoodNumber; + + private ImageView roomBack; + private ImageView roomMore; + private ImageView ivRoomShare; + + private long mTargetRoomUid; + private boolean isRoomMin; + + public int selectPage; + public int selectContent = -1; + private GiftV2View giftView; + private ViewStub mVsGift2View; + + private SVGAImageView mSvgaCar; + private SVGAParser mSVGAParser; + private boolean isSvgaPlaying; + private List mCarEffectList = new ArrayList<>(); + + private UserInfo mUserInfo; + private FragmentChatroomGameMainBinding gameMainBinding; + + private ShareDialog shareDialog; + + + public static HomePartyFragment newInstance(long roomUid, boolean isRoomMin) { + HomePartyFragment homePartyFragment = new HomePartyFragment(); + Bundle bundle = new Bundle(); + bundle.putLong(Constants.ROOM_UID, roomUid); + //是否是最小化进来 + bundle.putBoolean(Constants.IS_ROOM_MIN, isRoomMin); + homePartyFragment.setArguments(bundle); + return homePartyFragment; + } + + @Override + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + // clear views + roomTitle.setText(""); + setRoomId(0, 0); + updateOnlineNumberView(0); + if (roomFragment != null) + roomFragment.onNewIntent(intent); + if (listFragment != null) + listFragment.onNewIntent(intent); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + private void setRoomId(long id, int onlineNumber) { + String htmlText = "ID:" + id; + roomId.setText(Html.fromHtml(htmlText)); + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + mTargetRoomUid = bundle.getLong(Constants.ROOM_UID, 0); + isRoomMin = bundle.getBoolean(Constants.IS_ROOM_MIN, false); + } + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_chatroom_game_main; + } + + @Override + public void onFindViews() { + gameMainBinding = DataBindingUtil.bind(mView); + gameMainBinding.ivKtvTreasureBox.setVisibility(View.GONE); + roomTitle = mView.findViewById(R.id.room_title); + setupRoomTitleMarquee(); + roomMore = mView.findViewById(R.id.room_more); + ivRoomShare = mView.findViewById(R.id.iv_room_share); + if (SuperAdminUtil.isSuperAdmin()) { + ivRoomShare.setVisibility(View.INVISIBLE); + } else { + ivRoomShare.setVisibility(View.VISIBLE); + } + roomId = mView.findViewById(R.id.room_id); + roomBack = mView.findViewById(R.id.room_back); +// giftView = mView.findViewById(R.id.gift_view); + mSvgaCar = mView.findViewById(R.id.room_car_svga); + mVsGift2View = mView.findViewById(R.id.vs_gift_view); + mIvGoodNumber = mView.findViewById(R.id.iv_good_number); + + mSVGAParser = new SVGAParser(mContext); + + mSvgaCar.setVisibility(View.GONE); + mSvgaCar.setCallback(new SVGACallback() { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + isSvgaPlaying = false; + if (ListUtils.isListEmpty(mCarEffectList)) { + mSvgaCar.setVisibility(View.GONE); + return; + } + mCarEffectList.remove(0); + if (!ListUtils.isListEmpty(mCarEffectList)) { + playCarSvagEnterRoom(mCarEffectList.get(0)); + } + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + }); + } + + /** + * 添加跑马灯 + * 以及反射一些参数影响跑马灯 + */ + private void setupRoomTitleMarquee() { + try { + ViewConfiguration configuration = ViewConfiguration.get(getContext()); + Class claz = configuration.getClass(); + Field field = claz.getDeclaredField("mFadingMarqueeEnabled"); + field.setAccessible(true); + field.set(configuration, true); + + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + roomTitle.setSelected(true); + } + + @SuppressLint("CheckResult") + private void playCarSvga(String account, String effect, boolean isSendMsg) { + if (isSendMsg) { + UserModel.get().getUserInfoFromServer(Long.valueOf(account)) + .subscribe(userInfo -> { + //播放座驾动效 + if (userInfo != null + && userInfo.getCarInfo() != null + && userInfo.getCarInfo().isUsing() + && userInfo.getCarInfo().getStatus() == CarInfo.STATUS_USER_CAN_USE) { + if (AvRoomDataManager.get().mIsNeedGiftEffect) { + mCarEffectList.add(userInfo.getCarInfo().getEffect()); + } + // 非贵族人员,进来后要播放座驾动画 + if (userInfo.getNobleInfo() == null) { + if (!mSvgaCar.isAnimating() && !isSvgaPlaying) { + // 播放座驾动画 + playCarSvagEnterRoom(userInfo.getCarInfo().getEffect()); + } + // 公屏进入房间的提示语 + IMNetEaseManager.get() + .sendCarPlayRoomMsgBySdk(userInfo.getCarInfo(), userInfo.getUid(), userInfo.getNick()) + .subscribe(); + } + // 贵族人员,要先判断是否隐身 + if (userInfo.getNobleInfo() != null && !userInfo.getNobleInfo().isNobleEnterHide()) { + if (!mSvgaCar.isAnimating() && !isSvgaPlaying) { + // 播放座驾动画 + playCarSvagEnterRoom(userInfo.getCarInfo().getEffect()); + } + // 公屏进入房间的提示语 + IMNetEaseManager.get() + .sendCarPlayRoomMsgBySdk(userInfo.getCarInfo(), userInfo.getUid(), userInfo.getNick()) + .subscribe(); + } + } + }); + } else { + if (TextUtils.isEmpty(effect)) return; + if (AvRoomDataManager.get().mIsNeedGiftEffect) { + mCarEffectList.add(effect); + } + if (!mSvgaCar.isAnimating() && !isSvgaPlaying) { + playCarSvagEnterRoom(effect); + } + + } + } + + /** + * 真实播放svga + * + * @param effect + */ + private void playCarSvagEnterRoom(String effect) { + if (TextUtils.isEmpty(effect)) return; + if (!AvRoomDataManager.get().mIsNeedGiftEffect) return; + isSvgaPlaying = true; + try { + mSVGAParser.parse(new URL(effect), + new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + mSvgaCar.setVisibility(View.VISIBLE); + mSvgaCar.setLoops(1); + mSvgaCar.setClearsAfterStop(true); + mSvgaCar.setImageDrawable(new SVGADrawable(svgaVideoEntity)); + mSvgaCar.startAnimation(); + } + + @Override + public void onError() { + isSvgaPlaying = false; + mSvgaCar.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + isSvgaPlaying = false; + } + } + + @Override + public void onSetListener() { + roomMore.setOnClickListener(this); + roomId.setOnClickListener(this); + roomBack.setOnClickListener(this); + ivRoomShare.setOnClickListener(this); + gameMainBinding.roomNums.setOnClickListener(this); + } + + @Override + public void initiate() { + roomFragment = HomePartyRoomFragment.newInstance(isRoomMin); + roomFragment.setParent(this); + getChildFragmentManager().beginTransaction().replace(R.id.container, roomFragment).commitAllowingStateLoss(); + + if (!AvRoomDataManager.get().haveSelfChange && AvRoomDataManager.get().mCurrentRoomInfo != null) { + AvRoomDataManager.get().mIsNeedGiftEffect = AvRoomDataManager.get().mCurrentRoomInfo.isHasAnimationEffect(); + } + //砸金蛋横幅通知这个订阅不能在onPause里面取消,单独写个... + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .filter(roomEvent -> roomEvent.getEvent() == RoomEvent.BOX_NOTIFY) + .subscribe(roomEvent -> addBoxNotify(roomEvent.getChatRoomMessage())); + //registerKtvBoxListener(); + + subscribeGameEvent(); + } + + @SuppressLint("CheckResult") + private void subscribeGameEvent() { + RxBus.get().toFlowable(GameEvent.class) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(gameEvent -> { + if (gameEvent.getType() == GameEvent.GAME_END) { + if (!AvRoomDataManager.get().gameModel) return; + gameMainBinding.ivGameResult.setVisibility(View.VISIBLE); + GameResultInfo.ResultBean resultInfo = gameEvent.getResultInfo(); + if (GameResultInfo.DRAW.equals(resultInfo.getResultType())) { + gameMainBinding.ivGameResult.setImageResource(R.drawable.room_cp_game_draw); + } else { + if (resultInfo.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid()) { + showGameWin(); + } else if (resultInfo.getFailers().get(0).getUid() == AuthModel.get().getCurrentUid()) { + gameMainBinding.ivGameResult.postDelayed(() -> playFromRawFile(getActivity(), R.raw.lose), 500); + gameMainBinding.ivGameResult.setImageResource(R.drawable.room_cp_game_defeated); + } else { + gameMainBinding.ivGameResult.setImageResource(R.drawable.room_cp_game_victory); + } + } + } else { + gameMainBinding.ivGameResult.setVisibility(View.GONE); + } + }); + } + + private void showGameWin() { + gameMainBinding.ivGameResult.postDelayed(() -> playFromRawFile(getActivity(), R.raw.win), 500); + + gameMainBinding.ivGameResult.setImageResource(R.drawable.room_cp_game_victory); + gameMainBinding.konfettiView.build() + .addColors(Color.parseColor("#fe3864"), + Color.parseColor("#64ffa6"), + Color.parseColor("#ffdb00"), + Color.parseColor("#73eaff"), + Color.parseColor("#d350ff")) + .setDirection(0.0, 359.0) + .setSpeed(1f, 5f) + .setFadeOutEnabled(true) + .setTimeToLive(2000L) + .addShapes(Shape.RECT) + .addSizes(new Size(12, 5), new Size(16, 6f)) + .setPosition(-50f, gameMainBinding.konfettiView.getWidth() + 50f, -50f, -50f) + .burst(60); + } + + public void clearScreen() { + if (roomFragment != null) { + roomFragment.clearScreen(); + } + } + + public void addMessage(ChatRoomMessage msg) { + if (roomFragment != null) { + roomFragment.addMessage(msg); + } + } + + @SuppressLint("CheckResult") + @Override + public void onResume() { + super.onResume(); + + updateView(); + + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .subscribe(roomEvent -> { + if (roomEvent == null) return; + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.ENTER_ROOM: + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + updateOnlineNumberView(AvRoomDataManager.get().mCurrentRoomInfo.onlineNum); + } + addTipMsg(); + case RoomEvent.ROOM_INFO_UPDATE: + if (!isResumed()) return; + updateView(); + if (event == RoomEvent.ENTER_ROOM) { + if (!SuperAdminUtil.isSuperAdmin()) { + playCarSvga(String.valueOf(AuthModel.get().getCurrentUid()), null, true); + } + } + break; + case RoomEvent.CAR_MEMBER_IN: + if (!isResumed()) return; + if (roomEvent.mRoomCarMsgAttachment != null) { + playCarSvga(null, roomEvent.mRoomCarMsgAttachment.effect, false); + } + break; + case RoomEvent.RECEIVE_GIFT: + onReceiveGiftMsg(roomEvent.getGiftReceiveInfo()); + break; + case RoomEvent.RECEIVE_MULTI_GIFT: + onReceiveMultiGiftMsg(roomEvent.getMultiGiftReceiveInfo()); + break; + case RoomEvent.RECEIVE_GIFT_TO_MULTI: + onReceiveGiftToMultiMsg(roomEvent.getGiftMultiReceiverInfo()); + break; + case RoomEvent.RECEIVED_SINGLE_MAGIC: + onReceiveMagicMsg(roomEvent.getMagicReceivedInfo()); + break; + case RoomEvent.RECEIVED_ALL_MIC_MAGIC: + onReceiveMultiMagicMsg(roomEvent.getMultiMagicReceivedInfo()); + break; + default: + break; + } + }); + } + + private void onReceiveGiftToMultiMsg(GiftMultiReceiverInfo giftMultiReceiverInfo) { + if (giftMultiReceiverInfo == null || !isResumed()) return; + if (giftView == null) { + giftView = (GiftV2View) mVsGift2View.inflate(); + } + giftView.onReceiveGiftToMultiMsg(giftMultiReceiverInfo); + } + + /** + * 进入房间时的提示信息 + */ + private void addTipMsg() { + if (AvRoomDataManager.get().mCurrentRoomInfo != null && AvRoomDataManager.get().mCurrentRoomInfo.isCloseScreen()) { + MsgAttachment attachment = new RoomInfoAttachment(CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO, + CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_CLOSE_SCREEN); + ChatRoomMessage closeMsg = ChatRoomMessageBuilder.createChatRoomCustomMessage( + String.valueOf(AvRoomDataManager.get().getRoomId()), attachment); + closeMsg.setContent("管理员已关闭聊天公屏"); + IMNetEaseManager.get().addCloseScreenMessages(closeMsg); + } else if (AvRoomDataManager.get().mCurrentRoomInfo != null && !AvRoomDataManager.get().mCurrentRoomInfo.isHasAnimationEffect()) { + ChatRoomMessage tipMessage = ChatRoomMessageBuilder.createTipMessage(""); + tipMessage.setContent("礼物特效"); + IMNetEaseManager.get().addCloseScreenMessages(tipMessage); + } + } + + private void setIdOnlineData() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + + UserModel.get().getUserInfo(roomInfo.getUid()).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(UserInfo userInfo) { + mUserInfo = userInfo; + setRoomId(mUserInfo.getErbanNo(), roomInfo.onlineNum); + mIvGoodNumber.setVisibility(mUserInfo.isHasPrettyErbanNo() ? View.VISIBLE : View.GONE); + } + + @Override + public void onError(Throwable e) { + setRoomId(0, roomInfo.onlineNum); + mIvGoodNumber.setVisibility(View.GONE); + } + }); + + gameMainBinding.setRoomInfo(roomInfo); +// gameMainBinding.setHasAnimationEffect(AvRoomDataManager.get().mIsNeedGiftEffect); + } + + public void updateView() { + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoomInfo != null) { + gameMainBinding.setRoomInfo(currentRoomInfo); + if (!currentRoomInfo.isOpenGame) { + gameMainBinding.ivGameResult.setVisibility(View.GONE); + } + updateHasAnimationEffect(); + + roomTitle.setText(RegexUtil.getPrintableString(currentRoomInfo.getTitle())); + if (!StringUtil.isEmpty(currentRoomInfo.getRoomPwd())) { + roomTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, + getResources().getDrawable(R.drawable.icon_room_lock), null); + } else { + roomTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + } + + setIdOnlineData(); + } + } + + public void updateHasAnimationEffect() { + if (!AvRoomDataManager.get().haveSelfChange && AvRoomDataManager.get().mCurrentRoomInfo != null) { + AvRoomDataManager.get().mIsNeedGiftEffect = AvRoomDataManager.get().mCurrentRoomInfo.isHasAnimationEffect(); + } + gameMainBinding.setHasAnimationEffect(AvRoomDataManager.get().mIsNeedGiftEffect); + } + + /** + * 更新特效开关提示 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void updateHasAnimation(HasAnimationEffect event) { + updateHasAnimationEffect(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.room_more: + showMoreItems(); + break; + case R.id.room_nums: + case R.id.room_id: +// selectContent = SELECT_ONLINE_LIST; +// showListFragment(); + RoomOnlineUserActivity.start(getActivity()); + break; + + case R.id.room_back: + ((AVRoomActivity) getActivity()).onBackPressed(); + break; + case R.id.iv_room_share: + shareRoom(); + break; + default: + } + } + + public void shareRoom() { + if (shareDialog != null && shareDialog.isShowing()) { + shareDialog.dismiss(); + } + shareDialog = new ShareDialog(getActivity()); + shareDialog.setOnShareDialogItemClick(this); + shareDialog.show(); + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_SHARE_CLICK, "分享房间"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_SHARE_CLICK, "分享房间"); + + } + + @SuppressLint("CheckResult") + private void showMoreItems() { + List buttonItems = new ArrayList<>(); + ButtonItem buttonItem0 = new ButtonItem("随机进入嗨聊房", () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.room_hiparty, "房间内随机进入嗨聊房"); + AvRoomModel.get() + .getPartyRoomList(AuthModel.get().getCurrentUid()) + .subscribe((partyRoomResult, throuble) -> { + if (throuble != null) { + SingleToastUtil.showToastShort(throuble.getMessage()); + } else if (partyRoomResult.getData() != null && partyRoomResult.isSuccess()) { + if (partyRoomResult.getData().size() > 0) { + + // 普通房切嗨聊房清屏逻辑; + // cp房清屏逻辑在AVRoomActivity "切换房间后" 弹框监听, 防止用户取消切换房间,但公屏被清空的情况 + if (!AvRoomDataManager.get().isCpRoom()) { + clearScreen(); + ChatRoomMessage firstMsg = IMNetEaseManager.get().getFirstMessageContent(); + addMessage(firstMsg); + } + + AvRoomDataManager.get().setRoomUidList(partyRoomResult.getData()); + AVRoomActivity.start(getActivity(), true); + } else { + SingleToastUtil.showToastShort("暂无嗨聊房"); + } + } else if (partyRoomResult.getData() != null && !partyRoomResult.isSuccess()) { + SingleToastUtil.showToastShort(partyRoomResult.getError()); + } else { + SingleToastUtil.showToastShort("未知错误"); + } + }); +// HomeModel.get().getGuildRoomId() +// .subscribe(s -> AVRoomActivity.start(getActivity(), JavaUtil.str2long(s))); + + }); + + ButtonItem buttonItem1 = new ButtonItem("退出房间", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + if (AvRoomDataManager.get().isOpenKTV() && AvRoomDataManager.get().isOwnerOnMic()) { + getDialogManager().showOkCancelDialog("KTV模式下退出房间会移除您已点的所有歌曲,确定进行此操作?", false, + () -> ((AVRoomActivity) getActivity()).toBack()); + return; + } + if ((AvRoomDataManager.get().isQueuingMicro() || AvRoomDataManager.get().isOpenPKMode()) + && AvRoomDataManager.get().myIsInQueue) { + getDialogManager().showOkCancelDialog("退出房间将会取消你的报名,确定进行此操作?", false, + (DialogManager.LambdaOkDialogListener) () -> + ((AVRoomActivity) getActivity()).toBack()); + return; + } + if (AvRoomDataManager.get().haveStartDragon) { + getDialogManager().showOkCancelDialog("你正在交友匹配中,此操作代表你放弃本局匹配展示,确定进行此操作?", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + ((AVRoomActivity) getActivity()).giveUpDragonBar().subscribe(s -> { + new HomePartyPresenter().cancelDragon(); + ((AVRoomActivity) getActivity()).toBack(); + }); + } + }); + } else { + ((AVRoomActivity) getActivity()).toBack(); + } + } + }); + ButtonItem buttonItem2 = new ButtonItem("最小化房间", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + ((AVRoomActivity) getActivity()).onBackPressed(); + } + }); + ButtonItem buttonItem3 = new ButtonItem("举报房间", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + UIHelper.showReportPage(mContext, roomInfo.getUid(), XChatConstants.REPORT_TYPE_ROOM); + } + }); + buttonItems.add(buttonItem0); + buttonItems.add(buttonItem1); + buttonItems.add(buttonItem2); + buttonItems.add(buttonItem3); + DialogManager dialogManager = ((BaseMvpActivity) getActivity()).getDialogManager(); + if (dialogManager != null) { + dialogManager.showCommonPopupDialog(buttonItems, "取消"); + } + } + + @Override + public void onInAppSharingItemClick() { + shareDialog.dismiss(); + SelectFriendActivity.startForSharingRoom(getActivity()); + } + + @Override + public void onSharePlatformClick(Platform platform) { + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoomInfo != null) { + ShareModel.get().shareRoom( + platform, + currentRoomInfo.getUid(), + currentRoomInfo.getTitle() + ) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + getDialogManager().dismissDialog(); + } + }) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + } + + + private class MyOnPageChangeListener implements ViewPager.OnPageChangeListener { + private int selectPosition = -1; + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + selectPosition = position; + selectPage = position; + if (position == 1 && listFragment != null) { + if (selectContent == SELECT_CONTRIBUTE_LIST) { + listFragment.showPage(HomePartyUserListFragment.SHOW_PAGE_CONTRIBUTE_LIST); + } else if (selectContent == SELECT_ONLINE_LIST) { + listFragment.showPage(HomePartyUserListFragment.SHOW_PAGE_ONLINE_LIST); + } + } else { + + } + selectContent = SELECT_DEFAULT; + } + + @Override + public void onPageScrollStateChanged(int state) { + if (state == ViewPager.SCROLL_STATE_IDLE && selectPosition >= 0) { + if (listFragment != null) { + listFragment.setViewPagerPosition(selectPosition); + } + } else if (state == ViewPager.SCROLL_STATE_DRAGGING) { + selectPosition = -1; + } + } + } + + @Override + public void onShowActivity(List dialogInfos) { + if (roomFragment != null && roomFragment.isAdded()) { + roomFragment.showActivity(dialogInfos); + } + } + + + @Override + public void onDestroy() { + if (mSvgaCar.isAnimating()) { + mSvgaCar.clearAnimation(); + } + if (giftView != null) { + giftView.release(); + } + + EventBus.getDefault().unregister(this); + + super.onDestroy(); + if (boxDisposable != null) boxDisposable.dispose(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + roomFragment.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void onRoomOnlineNumberSuccess(int onlineNumber) { + super.onRoomOnlineNumberSuccess(onlineNumber); + updateOnlineNumberView(onlineNumber); + // setIdOnlineData(); + } + + private void onReceiveMultiGiftMsg(MultiGiftReceiveInfo multiGiftReceiveInfo) { + if (multiGiftReceiveInfo == null || !isResumed()) return; + if (giftView == null) { + giftView = (GiftV2View) mVsGift2View.inflate(); + } + giftView.onReceiveMultiGiftMsg(multiGiftReceiveInfo); + } + + private void onReceiveGiftMsg(GiftReceiveInfo giftReceiveInfo) { + if (giftReceiveInfo == null || !isResumed()) return; + if (giftView == null) { + giftView = (GiftV2View) mVsGift2View.inflate(); + } + giftView.onReceiveGiftMsg(giftReceiveInfo); + } + + private void onReceiveMagicMsg(MagicReceivedInfo magicReceivedInfo) { + if (magicReceivedInfo == null || !isResumed()) return; + if (giftView == null) { + giftView = (GiftV2View) mVsGift2View.inflate(); + } + giftView.onReceiveMagicMsg(magicReceivedInfo); + } + + + private void onReceiveMultiMagicMsg(MultiMagicReceivedInfo multiMagicReceivedInfo) { + if (multiMagicReceivedInfo == null || !isResumed()) return; + if (giftView == null) { + giftView = (GiftV2View) mVsGift2View.inflate(); + } + giftView.onReceiveMultiMagicMsg(multiMagicReceivedInfo); + } + + private Animation animation; + private List messages; + private Disposable boxDisposable; + private boolean isCreate; + + private void addBoxNotify(ChatRoomMessage chatRoomMessage) { + if (messages == null) messages = new ArrayList<>(); + messages.add(chatRoomMessage); + if (boxDisposable == null || messages.size() == 1) { + isCreate = true; + boxDisposable = Observable.interval(0, 6, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(aLong -> { + if (messages.size() > 0 && !isCreate) + messages.remove(0);//如果不是新创建的Observable发送的数据,需要移除第一个 + isCreate = false; + }) + .takeWhile(aLong -> messages.size() > 0 && messages.get(0) != null) + .subscribe(aLong -> showBoxNotify(messages.get(0))); + } + } + + private void showBoxNotify(ChatRoomMessage chatRoomMessage) { + // if (AvRoomDataManager.get().mCurrentRoomInfo == null) return; + SuperTextView textView = (SuperTextView) LayoutInflater.from(mContext).inflate(R.layout.layout_box_notify, null); + RoomBoxPrizeAttachment attachment = (RoomBoxPrizeAttachment) chatRoomMessage.getAttachment(); + // 内容 + MessageView.SpannableBuilder text = new MessageView.SpannableBuilder(textView) + .append("厉害了! ", new ForegroundColorSpan(0x80ffffff)) + .append(attachment.getNick() + " ", new ForegroundColorSpan(0xffffd557)) + .append(attachment.getBoxTypeStr() + " ", new ForegroundColorSpan(0x80ffffff)) + .append(attachment.getPrizeName(), new ForegroundColorSpan(Color.WHITE)); + textView.setText(text.build()); + if (animation == null) + animation = AnimationUtils.loadAnimation(mContext, R.anim.anim_box_notify); + gameMainBinding.flBoxNotify.removeAllViews(); + gameMainBinding.flBoxNotify.setVisibility(View.VISIBLE); + gameMainBinding.flBoxNotify.addView(textView); + gameMainBinding.flBoxNotify.startAnimation(animation); + animation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + gameMainBinding.flBoxNotify.removeAllViews(); + gameMainBinding.flBoxNotify.setVisibility(View.GONE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + } + + public void showKtvBox() { + GoldBoxHelper.isHideBox().subscribe( + hide -> { + if (hide != null && !hide) { + gameMainBinding.ivKtvTreasureBox.setVisibility(View.VISIBLE); + gameMainBinding.ivKtvTreasureBox.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (roomFragment != null) { + roomFragment.onClickBox(); + } + } + }); + } else { + gameMainBinding.ivKtvTreasureBox.setVisibility(View.GONE); + } + }, throwable -> + gameMainBinding.ivKtvTreasureBox.setVisibility(View.GONE)); + + } + + public void hideKtvBox() { + gameMainBinding.ivKtvTreasureBox.setVisibility(View.GONE); + } + + /** + *  * 提示音 + *

+ *  * @param mContext + *

+ *   + */ + + private void playFromRawFile(Context mContext, int res) { + try { + MediaPlayer player = new MediaPlayer(); + AssetFileDescriptor file = mContext.getResources().openRawResourceFd(res); + try { + player.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); + file.close(); + if (!player.isPlaying()) { + player.prepare(); + player.start(); + } + } catch (IOException e) { + player = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public void dismissGiftDialog() { + if (roomFragment != null) { + roomFragment.dismissGiftDialog(); + } + } + + private void updateOnlineNumberView(int onlineNumber) { + if (!SuperAdminUtil.isSuperAdmin()) { + if (onlineNumber < 1) { + onlineNumber = 1; + } + } + gameMainBinding.roomNums.setText(onlineNumber + "人在线>"); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java new file mode 100644 index 000000000..33586fbd7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java @@ -0,0 +1,3158 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.arch.lifecycle.ViewModelProviders; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewPager; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewStub; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.netease.nim.uikit.common.antispam.AntiSpamEvent; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.StatusCode; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomStatusChangeData; +import com.orhanobut.logger.Logger; +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.tongdaxing.erban.sadmin.RoomSAdminManagerActivity; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.BottomViewListenerWrapper; +import com.yizhuan.erban.avroom.ButtonItemFactory; +import com.yizhuan.erban.avroom.SoftKeyBoardListener; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.activity.CreatePKActivity; +import com.yizhuan.erban.avroom.activity.RoomInviteActivity; +import com.yizhuan.erban.avroom.activity.RoomManagerListActivity; +import com.yizhuan.erban.avroom.activity.RoomSettingActivity; +import com.yizhuan.erban.avroom.activity.RoomTitleEditActivity; +import com.yizhuan.erban.avroom.adapter.BaseMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.CpMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.KtvMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.MicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.OnMicroItemClickListener; +import com.yizhuan.erban.avroom.dialog.MicQueueDialog; +import com.yizhuan.erban.avroom.dialog.NewUserTaskDialog; +import com.yizhuan.erban.avroom.dialog.PKMicQueueDialog; +import com.yizhuan.erban.avroom.dialog.PKResultDialog; +import com.yizhuan.erban.avroom.dialog.PKScoreBoardDialog; +import com.yizhuan.erban.avroom.dialog.RoomImposeDialog; +import com.yizhuan.erban.avroom.dialog.RoomOperationDialog; +import com.yizhuan.erban.avroom.game.GameSelectDialog; +import com.yizhuan.erban.avroom.game.PlayGameActivity; +import com.yizhuan.erban.avroom.giftvalue.GiftValueDialogUiHelper; +import com.yizhuan.erban.avroom.helper.RoomViewModel; +import com.yizhuan.erban.avroom.ktv.KtvHelper; +import com.yizhuan.erban.avroom.ktv.KtvMusicManager; +import com.yizhuan.erban.avroom.ktv.KtvSelectSongActivity; +import com.yizhuan.erban.avroom.ktv.KtvSongListActivity; +import com.yizhuan.erban.avroom.presenter.HomePartyPresenter; +import com.yizhuan.erban.miniworld.widget.MiniWorldEditChooseClassifyDialog; +import com.yizhuan.erban.treasure_box.activity.TreasureBoxHonourActivity; +import com.yizhuan.erban.treasure_box.fragment.ChooseTreasureBoxDialogFragment; +import com.yizhuan.erban.treasure_box.widget.GoldBoxHelper; +import com.yizhuan.erban.treasure_box.activity.TreasureBoxActivity; +import com.yizhuan.erban.avroom.view.IHomePartyView; +import com.yizhuan.erban.avroom.widget.BottomView; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.avroom.widget.MicroView; +import com.yizhuan.erban.avroom.widget.PKBoardView; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.FragmentAvRoomGameBinding; +import com.yizhuan.erban.event.OpenRoomIntroEvent; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.home.adapter.RoomActAdapter; +import com.yizhuan.erban.miniworld.activity.MiniWorldGuestPageActivity; +import com.yizhuan.erban.module_hall.hall.activity.ModuleHallActivity; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleDialog; +import com.yizhuan.erban.ui.widget.dynamicface.DynamicFaceDialog; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.AvRoomNobleWelcomeView; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.tutu.music.widget.MusicPlayerView; +import com.yizhuan.tutu.room_chat.activity.RoomMsgActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.bean.attachmsg.RoomQueueMsgAttachment; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftMultiReceiverInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.JoinMiniWorldAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomFollowOwnerAttachment; +import com.yizhuan.xchat_android_core.im.game.ImGameInfo; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringCountingEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringCountingFinishEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringStartCountingEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringStopCountingEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.model.MentoringRelationshipModel; +import com.yizhuan.xchat_android_core.miniworld.bean.MiniWorldInWorldInfo; +import com.yizhuan.xchat_android_core.music.model.PlayerModel; +import com.yizhuan.xchat_android_core.radish.task.TaskModel; +import com.yizhuan.xchat_android_core.radish.task.bean.CheckNewUserTaskInfo; +import com.yizhuan.xchat_android_core.radish.task.bean.PrizeType; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; +import com.yizhuan.xchat_android_core.room.activitytimer.ActivityTimerEvent; +import com.yizhuan.xchat_android_core.room.activitytimer.TimerBean; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.event.RoomClearScreenEvent; +import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_core.room.game.AiPlayEndEvent; +import com.yizhuan.xchat_android_core.room.game.ChangeGameEvent; +import com.yizhuan.xchat_android_core.room.game.ChangeUserEvent; +import com.yizhuan.xchat_android_core.room.game.GameEvent; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.giftvalue.GiftValueModel; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.room.ktv.event.MusicCountEvent; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.MicQueueModel; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRespQueuingMicListInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.pk.event.PKStateEvent; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.RespQueuingMicListInfo; +import com.yizhuan.xchat_android_core.room.queuing_mic.event.HasAnimationEffect; +import com.yizhuan.xchat_android_core.room.queuing_mic.event.QueuingMicEmptyEvent; +import com.yizhuan.xchat_android_core.room.queuing_mic.event.QueuingMicNotEmptyEvent; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.SaConstant; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.BaseInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.ErrorConsumer; +import com.yizhuan.xchat_android_core.utils.net.ServerException; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.net.rxnet.utils.RxNetWorkUtils; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.TimeUtils; +import com.yizhuan.xchat_android_library.utils.UIUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Consumer; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_OPEN; + +/** + * 轰趴房间 + * + * @author chenran + * @date 2017/7/26 + */ +@CreatePresenter(HomePartyPresenter.class) +public class HomePartyRoomFragment extends BaseMvpFragment implements View.OnClickListener, + GiftDialog.OnGiftDialogBtnClickListener, IHomePartyView, OnMicroItemClickListener, PKBoardView.OnActionListener { + /** + * 显示关注房主的时间 + */ + public static final int SHOW_FOLLOW_TIME = 3 * 60 * 1000; + public static final int SHOW_JOIN_MINI_WORLD_TIME = 2 * 60 * 1000; + private static final int MINI_WORLD_REQUEST_CODE = 101; + private long myUid; + private UserInfo roomOwnner; + private MessageView messageView; + private BottomView bottomView; + private RelativeLayout inputLayout; + private EditText inputEdit; + private ImageView inputSend; + + private MusicPlayerView musicPlayerView; + private ViewStub mVsMusicPlayer; + private MicroView microView; + + private SuperTextView stvKtvSong; + private PKBoardView pkBoardView; + + private AvRoomNobleWelcomeView mNobleWelcomeView; + private ViewStub mVsNobleWelcome; + + private List mActionDialogInfoList; + + private Disposable mDisposable; + private int audioQulity; + + private FragmentAvRoomGameBinding gameBinding; + //添加变量 + private boolean isKtvMode = false; + private boolean isGameMode = false; + private Disposable ktvDisposable; + private boolean isCloseScreen; + private boolean isRoomPureMode; + /** + * 是否开启礼物值显示 + */ + private boolean showGiftValue; + + HomePartyFragment parentFragment; + /** + * 排麦弹框 + */ + private MicQueueDialog micQueueDialog; + + private PKMicQueueDialog pkMicQueueDialog; + + private ViewStub countDownTimerViewStub; + private View countDownTimerLayout; + private ImageView countDownTimerLayoutBackground; + private ImageView mentoringCountDownTimerIcon; + private TextView mentoringCountDownTimer; + + private boolean isRoomMin; + private int mJoinMiniWorldOperationPosition = -1; + + public static HomePartyRoomFragment newInstance(boolean isRoomMin) { + HomePartyRoomFragment roomFragment = new HomePartyRoomFragment(); + Bundle bundle = new Bundle(); + //是否是最小化进来 + bundle.putBoolean(Constants.IS_ROOM_MIN, isRoomMin); + roomFragment.setArguments(bundle); + return roomFragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + this.isRoomMin = bundle.getBoolean(Constants.IS_ROOM_MIN, false); + } + } + + public void setParent(HomePartyFragment homePartyFragment) { + this.parentFragment = homePartyFragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_av_room_game; + } + + @Override + public void onFindViews() { + gameBinding = DataBindingUtil.bind(mView); + gameBinding.setLifecycleOwner(this); + gameBinding.setClick(this); + gameBinding.setKtvModel(false); + messageView = mView.findViewById(R.id.message_view); + bottomView = mView.findViewById(R.id.bottom_view); + inputLayout = mView.findViewById(R.id.input_layout); + inputEdit = mView.findViewById(R.id.input_edit); + inputSend = mView.findViewById(R.id.input_send); + mVsMusicPlayer = mView.findViewById(R.id.vs_music_player); + gameBinding.playTogether.setVisibility(View.GONE); + gameBinding.ivToMiniWorld.setVisibility(View.GONE); + microView = mView.findViewById(R.id.micro_view); + stvKtvSong = (SuperTextView) mView.findViewById(R.id.stv_ktv_song); + + pkBoardView = (PKBoardView) mView.findViewById(R.id.layout_pk_board); + pkBoardView.setOnActionListener(this); + mVsNobleWelcome = mView.findViewById(R.id.vs_avroom_noble_welcome); + + messageView.setDialogManager(getDialogManager()); + messageView.setClickConsumer(new Consumer() { + @Override + public void accept(String account) throws Exception { + //getMvpPresenter().avatarClick(-2, account); + showUserCardDialog(account); + } + }); + messageView.setOnClickListener((chatRoomMessage, imGameInfo) -> getGameUrl(chatRoomMessage, imGameInfo)); + messageView.setOnClick(new MessageView.OnClick() { + @Override + public void onFollowClick(int position) { + getMvpPresenter().followOwner(position, roomOwnner.getUid()); + } + + @Override + public void onJoinMiniWorldClick(int position) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + toast("发生了一些异常,请重新打开"); + return; + } + if (roomInfo.getWorldId() == 0) { + toast("当前房间没有小世界哦!!"); + return; + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_VIEW_WORLD_PAGE, + "进入小世界客态页:语音派对"); + MiniWorldGuestPageActivity.startFromRoom(HomePartyRoomFragment.this, String.valueOf(roomInfo.getWorldId()), MINI_WORLD_REQUEST_CODE); + } + + @Override + public void onShowRoomIntroduction() { + showRoomIntroduction(false); + } + }); + countDownTimerViewStub = mView.findViewById(R.id.vs_avroom_mentoring_count_down_timer); + countDownTimerViewStub.setOnInflateListener(new ViewStub.OnInflateListener() { + @Override + public void onInflate(ViewStub viewStub, View view) { + countDownTimerLayout = view; + } + }); + + } + + @Override + public void onSetListener() { + bottomView.setBottomViewListener(new GameRoomBottomViewWrapper()); + bottomView.setMagicBtnEnable(true); + inputSend.setOnClickListener(this); + microView.findViewById(R.id.desc_layout).setOnClickListener(v -> onRoomSettingsClick()); + microView.findViewById(R.id.ll_ktv_top).setOnClickListener(v -> onRoomSettingsClick()); + + inputLayout.setOnTouchListener((v, event) -> { + inputEdit.clearFocus(); + inputLayout.setVisibility(View.GONE); + KeyBoardUtils.hideKeyBoard(getActivity(), inputEdit); + return false; + }); + softKeyboardListener(); + } + + + @SuppressLint("CheckResult") + @Override + public void initiate() { + //如果不需要开麦,并且还没有权限的情况下,重置状态为需要去打开麦克风 + if (!AvRoomDataManager.get().mIsNeedOpenMic && !isHavingMicPermissions()) { + AvRoomDataManager.get().mIsNeedOpenMic = true; + } + + myUid = AuthModel.get().getCurrentUid(); + //audioQulity = AvRoomDataManager.get().mCurrentRoomInfo.getAudioQuality(); + gameBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + isCloseScreen = AvRoomDataManager.get().isCloseScreen(); + isRoomPureMode = AvRoomDataManager.get().isOpenPureMode(); + showGiftValue = AvRoomDataManager.get().isShowGiftValue(); + openOrCloseGiftValue(true); + hideKtvRelaView(); + updateView(); + updateMicBtn(); + updateQueuingMicBtn(); + updatePkScoreBoard(); + microView.setOnMicroItemClickListener(this); + + + mDisposable = IMNetEaseManager.get().getChatRoomEventObservable() + .subscribe(this::onReceiveRoomEvent); + + if (AvRoomDataManager.get().mCurrentRoomInfo != null + && IMNetEaseManager.get().mCacheRoomQueueInfo != null + && !AvRoomDataManager.get().isFirstEnterRoomOrChangeOtherRoom(AvRoomDataManager.get().mCurrentRoomInfo.getUid())) { + getMvpPresenter().chatRoomReConnect(IMNetEaseManager.get().mCacheRoomQueueInfo); + } + + RxBus.get().toFlowable(MusicCountEvent.class) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(musicCountEvent -> gameBinding.stvKtvSong.setText("已点" + musicCountEvent.getCount())); + + RxBus.get().toFlowable(GameEvent.class) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(gameEvent -> handGameEvent(gameEvent)); + + RxBus.get().toFlowable(AiPlayEndEvent.class) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .observeOn(AndroidSchedulers.mainThread()) + .delay(2, TimeUnit.SECONDS) + .subscribe(aiPlayEndEvent -> { + getMvpPresenter().kickAi(aiPlayEndEvent); + }); + + // 接收公屏消息点击 可点击房间编辑页查看 事件 + RxBus.get().toFlowable(OpenRoomIntroEvent.class) + .compose(bindToLifecycle()) + .subscribe(showUserInfoDialog -> showRoomIntroduction(false)); + //换个对手重新发起游戏 + RxBus.get().toFlowable(ChangeUserEvent.class) + .compose(bindToLifecycle()) + .subscribe(changeUserEvent -> ImGameMode.get().sendRoomSponsorGameMsg(changeUserEvent.gameInfo)); + //换个游戏 + RxBus.get().toFlowable(ChangeGameEvent.class) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(changeUserEvent -> { + if (!AvRoomDataManager.get().isCpRoom()) { + showGameSelectDialog(); + } + }); + + //最小化恢复时,更新礼物值 + if (isRoomMin) { + GiftValueMrg.get().updateRoomGiftValue(false); + } + // 刷新礼物列表,获取房间专属礼物列表 + GiftModel.get().refreshGiftList(String.valueOf(AvRoomDataManager.get().getRoomUid())).subscribe(); +// if (!AvRoomDataManager.get().isCpRoom() && TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_FIRST_ROOM)) { + if (!AvRoomDataManager.get().isCpRoom()) { + microView.recyclerView.postDelayed(() -> { + if (!ActivityUtil.isValidContext(mContext)) { + return; + } + int count = microView.recyclerView.getChildCount(); + if (count > 0) { + View kingView = microView.recyclerView.getChildAt(count - 1); + if (kingView == null) { + return; + } + View micro_layout = kingView.findViewById(R.id.micro_layout); + if (micro_layout == null) { + return; + } +// TuTuGuideHelper helper = new TuTuGuideHelper(mContext); +// helper.createHiGuide(() -> helper.createRoomGuide(micro_layout, bottomView.getSendGiftView()), +// new TuTuGuideView.IGuideShowFinishListener() { +// @Override +// public void onSkip() { +// checkNewUserTask();// 跳过指引,判断是否有新人有礼 +// } +// +// @Override +// public void onGuideFinish() { +// checkNewUserTask();// 引导图显示结束,判断是否有新人有礼 +// } +// }); +// TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_FIRST_ROOM); +// checkNewUserTask();// 引导图显示结束,判断是否有新人有礼[20190719 直接去掉新人有礼dialog] + } + }, 500); + } + checkFollowOwner(); + checkMiniWorld(); + otherInitView(); + } + + private void checkNewUserTask() { + new TaskModel().checkNewUserTask(AuthModel.get().getCurrentUid()) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(CheckNewUserTaskInfo checkNewUserTaskInfo, String error) { + super.accept(checkNewUserTaskInfo, error); + if (error == null) { + if (checkNewUserTaskInfo.isHasNewUser()) {// 可以领取新人礼物 + if (getFragmentManager() != null) { + NewUserTaskDialog newUserTaskDialog = NewUserTaskDialog.newInstance(() -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_POPUP_NEW_USER_REWARD, "语音房-新人有礼弹窗-领取奖励"); + // 领取奖励 + receiveNewUserTaskAward(checkNewUserTaskInfo.getConfigId()); + }); + newUserTaskDialog.show(getFragmentManager(), "new_user_task_dialog"); + } + } + } + } + }); + } + + private void receiveNewUserTaskAward(long configId) { +// getDialogManager().showProgressDialog(mContext, "正在领取奖励..."); + new TaskModel().receivePrice(configId, PrizeType.RADISH) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); +// getDialogManager().dismissDialog(); + if (error == null) { + SingleToastUtil.showToast("送个萝卜礼物试试吧~"); + // 领取成功,刷新Dialog布局并且三秒后dismiss + if (getFragmentManager() != null) { + Fragment newUserTaskDialog = getFragmentManager().findFragmentByTag("new_user_task_dialog"); + if (newUserTaskDialog instanceof NewUserTaskDialog) { + ((NewUserTaskDialog) newUserTaskDialog).refreshDialogWithReceiveAwardFinish(); + } + } + } else { + SingleToastUtil.showToast(error); + } + } + }); + } + + private void handGameEvent(GameEvent gameEvent) { + switch (gameEvent.getType()) { + case GameEvent.OPEN_GAME_MODEL: + openGameModel(); + break; + case GameEvent.CLOSE_GAME_MODEL: + closeGameModel(); + break; + } + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + if (roomEvent == null) return; + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.ROOM_CHAT_RECONNECTION: + // 重新调服务器的userroom/inV2,保持座位上有贵族 + getMvpPresenter().userRoomIn(); + //从新获取队列信息 + getMvpPresenter().chatRoomReConnect(roomEvent.roomQueueInfo); + //如果用户在麦上的话,会重新上麦一次,如果不在麦上,则自行更新 + if (RxNetWorkUtils.isAvailable(mContext) && !AvRoomDataManager.get().isOwnerOnMic()) { + GiftValueMrg.get().handleReconnect(false); + } + break; + case RoomEvent.ROOM_EXIT: + // 退出房间,把标志置为 false + AvRoomDataManager.get().setFromMentoring(false); + // 退出房间的时候,要停止倒计时 + EventBus.getDefault().post(new MentoringStopCountingEvent()); + break; + case RoomEvent.DOWN_CROWDED_MIC: + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + cleanDragonBar(); + if (isKtvMode) { + KtvMusicManager.INSTANCE.deleteUserAllChooseMusic().subscribe(); + } + toast(R.string.crowded_down); + } + break; + case RoomEvent.ROOM_MANAGER_ADD: + gameBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + updateView(); + updatePkScoreBoard(); + //如果自己被设置为管理员,移除自己的排麦队列 + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + cancelMyQueue(); + if (AvRoomDataManager.get().isQueuingMicro() + && !AvRoomDataManager.get().myIsInQueue + && isMicQueueDialogShowing()) { + micQueueDialog.refreshData(); + } + + if (AvRoomDataManager.get().isOpenPKMode() + && !AvRoomDataManager.get().myIsInQueue + && isPKMicQueueDialogShowing()) { + pkMicQueueDialog.refreshData(); + } + } + break; + case RoomEvent.ROOM_MANAGER_REMOVE: + gameBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + updateView(); + updatePkScoreBoard(); + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount()) + && isMicQueueDialogShowing()) { + micQueueDialog.refreshData(); + } + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount()) + && isPKMicQueueDialogShowing()) { + pkMicQueueDialog.refreshData(); + } + break; + case RoomEvent.ROOM_INFO_UPDATE: + // changeAudioQuality(); + Logger.i("房间更新事件"); + gameBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + updateScreen(); + updateView(); + updateRemoteMuteBtn(); + updateQueuingMicBtn(); + updatePkScoreBoard(); + openOrCloseGiftValue(false); + getMvpPresenter().updateLeaveMode(); + break; + case RoomEvent.ENTER_ROOM: + Logger.i("进入房间事件"); + cpRoomAutoUpMic(); + getMvpPresenter().leaveModeCheck(); + + UserModel.get().getUserInfoFromServer(myUid).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + //如果贵族是超管,则不显示贵族进房提示 + if (userInfo != null && userInfo.isSuperAdmin()) { + return; + } + if (userInfo != null && userInfo.getNobleInfo() != null && !userInfo.getNobleInfo().isNobleEnterHide()) + IMNetEaseManager.get().sendNobleInRoomMsgBySdk(userInfo.getNobleInfo(), + userInfo.getNick(), userInfo.getUid()) + .subscribe(chatRoomMessage -> { + if (mNobleWelcomeView == null) { + mNobleWelcomeView = (AvRoomNobleWelcomeView) mVsNobleWelcome.inflate(); + } + mNobleWelcomeView.setData(userInfo.getNobleInfo(), userInfo.getNick()); + }); + } + }); + gameBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + updateView(); + updateRemoteMuteBtn(); + updateQueuingMicBtn(); + updatePkScoreBoard(); + if (AvRoomDataManager.get().isFromMentoring() && Objects.equals(AvRoomDataManager.get().getMasterUid(), + AvRoomDataManager.get().mCurrentRoomInfo.getUid())) { + // 只有从任务三分享房间链接进来的时候才开始倒计时 + EventBus.getDefault().post(new MentoringStartCountingEvent()); + } else { + EventBus.getDefault().post(new MentoringStopCountingEvent()); + } + openOrCloseGiftValue(true); + GiftValueMrg.get().updateRoomGiftValue(false); + break; + case RoomEvent.ADD_BLACK_LIST: + onChatRoomMemberBlackAdd(roomEvent.getAccount()); + break; + case RoomEvent.MIC_QUEUE_STATE_CHANGE: + onQueueMicStateChange(roomEvent.getMicPosition(), roomEvent.getPosState()); + break; + case RoomEvent.KICK_DOWN_MIC_BY_S_ADMIN: + case RoomEvent.KICK_DOWN_MIC: + cleanDragonBar(); + if (isKtvMode) { + KtvMusicManager.INSTANCE.deleteUserAllChooseMusic().subscribe(); + } + if (event == RoomEvent.KICK_DOWN_MIC) { + SingleToastUtil.showToast(mContext.getResources().getString( + R.string.kick_mic)); + } else if (event == RoomEvent.KICK_DOWN_MIC_BY_S_ADMIN) { + SingleToastUtil.showToast(mContext.getResources().getString( + R.string.kick_mic_by_s_admin)); + } + break; + case RoomEvent.DOWN_MIC: + addOrRemoveMatchPool(); + onDownMicro(roomEvent.getMicPosition()); + break; + case RoomEvent.UP_MIC: // 上麦 + getMvpPresenter().closeLeaveMode(roomEvent.getMicPosition(), roomEvent.getAccount()); + addOrRemoveMatchPool(); + onUpMicro(roomEvent.getMicPosition()); + if (pkMicQueueDialog != null && pkMicQueueDialog.isShowing()) { + String account = roomEvent.getAccount(); + pkMicQueueDialog.onUpMicro(account); + } + break; + case RoomEvent.INVITE_UP_MIC: + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + //自己的消息 + onInviteUpMic(roomEvent.getMicPosition()); + } else { + //如果不是自己的消息,将这上麦的这个人,从排麦列表,静态移除 + removeOtherFromMicQueue(roomEvent.getAccount()); + } + break; + case RoomEvent.KICK_OUT_ROOM: + ChatRoomKickOutEvent reason = roomEvent.getReason(); + if (reason != null && reason.getReason() == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + releaseView(); + } + if (isMicQueueDialogShowing()) { + micQueueDialog.dismiss(); + } + if (AvRoomDataManager.get().isQueuingMicro() && AvRoomDataManager.get().myIsInQueue) { + MicQueueModel.get().cancelApplyForQueuing(AvRoomDataManager.get().getRoomUid(), + AuthModel.get().getCurrentUid()).subscribe(); + } + if (AvRoomDataManager.get().isFromMentoring() && !Objects.equals(AuthModel.get().getCurrentUid(), + AvRoomDataManager.get().mCurrentRoomInfo.getUid())) { + // 被踢出房间的时候,要停止倒计时 + EventBus.getDefault().post(new MentoringStopCountingEvent()); + // 并且把标志置为 false + AvRoomDataManager.get().setFromMentoring(false); + } + AvRoomDataManager.get().removeChatRoomMember(String.valueOf(roomEvent.getAccount())); + break; + case RoomEvent.ON_NOBLE_MEMBER_IN: + if (roomEvent.mRoomNobleMsgAttachment != null) { + if (mNobleWelcomeView == null) { + mNobleWelcomeView = (AvRoomNobleWelcomeView) mVsNobleWelcome.inflate(); + } + mNobleWelcomeView.setData(roomEvent.mRoomNobleMsgAttachment.nobleInfo, + roomEvent.mRoomNobleMsgAttachment.nick); + } + break; + case RoomEvent.ON_QUEUE_MEMBER_INFO_UPDATE: + // 用户的贵族字段过期或者开通贵族,可以实时地监听ext字段变化,显示头饰,光晕等 + microView.getAdapter().notifyDataSetChanged(); + break; + case RoomEvent.OTHER_KICK_OUT_ROOM: + case RoomEvent.OTHER_ADD_BLACK: + case RoomEvent.OTHER_KICK_OUT_OR_ADD_BLACK_BY_S_ADMIN: + String targetUid = roomEvent.getAccount(); + if (!TextUtils.isEmpty(targetUid)) { + removeOtherFromMicQueue(targetUid); + AvRoomDataManager.get().removeChatRoomMember(targetUid); + } + break; + + case RoomEvent.PK_INFO_UPDATE: + updatePkScoreBoard(); + + break; + case RoomEvent.PK_INVITE_IN_TEAM: + if (AvRoomDataManager.get().isOwner(roomEvent.getAccount())) { + //自己的消息 + onInviteInTeam(roomEvent.getMicPosition()); + } else { + //如果不是自己的消息,将这上麦的这个人,从排麦列表,静态移除 + removeOtherFromMicQueue(roomEvent.getAccount()); + } + break; + case RoomEvent.PK_START: + //PK 开始弹出大记分板 + if (PkModel.get().getCurPkInfo() != null + && PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_IN_PK) { + PKScoreBoardDialog pkScoreBoardDialog = new PKScoreBoardDialog(getContext()); + pkScoreBoardDialog.show(); + } + break; + + case RoomEvent.LEAVE_MODE: + microView.getAdapter().notifyDataSetChanged(); + break; + + default: + } + } + + /** + * cp房自动上麦 + */ + private void cpRoomAutoUpMic() { + if (AvRoomDataManager.get().isCpRoom()) { + + // 超管进cp房不上麦 + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + + int freePosition = AvRoomDataManager.get().findFreePosition(); + if (freePosition == Integer.MIN_VALUE) { + return; + } + if (AvRoomDataManager.get().isRoomOwner()) { + getMvpPresenter().upMicroPhone(-1, AuthModel.get().getCurrentUid() + "", false); + } else { + int freePositionNoOwner = AvRoomDataManager.get().findFreePositionNoOwner(); + if (freePositionNoOwner == 0) { + getMvpPresenter().upMicroPhone(freePositionNoOwner, AuthModel.get().getCurrentUid() + "", false); + } else if (freePosition == -1) { + getMvpPresenter().upMicroPhone(freePosition, AuthModel.get().getCurrentUid() + "", false); + } + } + } + } + + /** + * 抱上队伍 + * + * @param micPosition + */ + private void onInviteInTeam(int micPosition) { + if (UIUtils.isTopActivity(getBaseActivity())) { + ((BaseMvpActivity) getActivity()).getDialogManager() + .showOkWithTitleDialog(getString(R.string.embrace_on_mic), true); + } + //被人抱上麦 + //自己取消报名 + cancelMyQueue(); + } + + private void updatePkScoreBoard() { + if (AvRoomDataManager.get().isOpenPKMode()) { + + if (pkBoardView.getVisibility() == View.GONE) { + // 通知更新背景 + PKStateEvent pkStateEvent = new PKStateEvent(); + pkStateEvent.setCreate(true); + EventBus.getDefault().post(pkStateEvent); + } + + pkBoardView.setVisibility(View.VISIBLE); + //这里通过接口获取PK 详情 更新pk 记分板 + if (PkModel.get().getCurPkInfo() == null) { + PkModel.get().loadPKDataByRoomId( + AvRoomDataManager.get().getRoomUid() + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(RoomPkData roomPkData) { + pkBoardView.updateView(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } else { + pkBoardView.updateView(); + } + //PK模式不显示这个玩意 + stvKtvSong.setVisibility(View.GONE); + setToMiniWorldVisible(true); + //取消掉正在进行的龙珠 + if (AvRoomDataManager.get().haveStartDragon) { + ((AVRoomActivity) getActivity()).giveUpDragonBar().subscribe(s -> { + gameBinding.playDragon.setVisibility(View.INVISIBLE); + gameBinding.cancelDragon.setVisibility(View.INVISIBLE); + getMvpPresenter().cancelDragon(); + }); + } + + } else { + + if (pkBoardView.getVisibility() == View.VISIBLE) { + // 通知更新bg + PKStateEvent pkStateEvent = new PKStateEvent(); + pkStateEvent.setCreate(false); + EventBus.getDefault().post(pkStateEvent); + } + + pkBoardView.setVisibility(View.GONE); + //KTV模式显示这个玩意 + if (AvRoomDataManager.get().isOpenKTV()) { + stvKtvSong.setVisibility(View.VISIBLE); + setToMiniWorldVisible(false); + } + } + + if (SuperAdminUtil.isSuperAdmin()) { + pkBoardView.setVisibility(View.GONE); + } + + //龙珠相关界面设置 + setDragonView(); + } + + /** + * 开启或关闭公屏 + */ + private void updateScreen() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null || isCloseScreen == AvRoomDataManager.get().mCurrentRoomInfo.isCloseScreen()) + return; + isCloseScreen = AvRoomDataManager.get().mCurrentRoomInfo.isCloseScreen(); + if (isCloseScreen) { + AvRoomDataManager.get().chatRoomDataRelease(false); + gameBinding.messageView.clear(); + } + getMvpPresenter().updateScreen(isCloseScreen); + } + + /** + * 嗨聊房切换清屏方法 + */ + public void clearScreen() { + gameBinding.messageView.clear(); + } + + /** + * 嗨聊房切换重置公屏消息(绿色公告) + */ + public void addMessage(ChatRoomMessage msg) { + gameBinding.messageView.addMessages(msg); + } + + /** + * 开启或关闭礼物值 + */ + private void openOrCloseGiftValue(boolean isEnterRoom) { + if (AvRoomDataManager.get().isOpenKTV() || AvRoomDataManager.get().isCpRoom()) { + GiftValueMrg.get().clearObsever(); + return; + } + if (!isEnterRoom && (AvRoomDataManager.get().mCurrentRoomInfo == null || showGiftValue == AvRoomDataManager.get().isShowGiftValue())) + return; + showGiftValue = AvRoomDataManager.get().isShowGiftValue(); + GiftValueMrg.get().openOrCloseGiftValue(); + } + + @Override + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + // 释放公屏和麦上的所有信息信息和动画 + long roomUid = intent.getLongExtra(Constants.ROOM_UID, 0); + if (roomUid != 0 && roomUid != AvRoomDataManager.get().mCurrentRoomInfo.getUid()) { + releaseView(); + } + } + + @Override + public void onResume() { + super.onResume(); + if (musicPlayerView != null) { + musicPlayerView.updateVoiceValue(); + } + updateMicBtn(); + ChatRoomStatusChangeData chatRoomStatusChangeData = + AvRoomDataManager.get().chatRoomStatusChangeData; + if (chatRoomStatusChangeData != null && + chatRoomStatusChangeData.status == StatusCode.LOGINED) { + // 重新调服务器的userroom/inV2,保持座位上有贵族 + getMvpPresenter().userRoomIn(); + } + +// // 自动发公屏聊天消息 +// Observable.interval(150, TimeUnit.MILLISECONDS) +// .subscribeOn(Schedulers.computation()) +// .observeOn(AndroidSchedulers.mainThread()) +// .compose(bindToLifecycle()) +// .subscribe(aLong -> { +// getMvpPresenter().sendTextMsg(aLong + "app-test"); +// }); + updateMentoringCountDownTimer(); + } + + //改变声网品质 + private void changeAudioQuality() { + if (audioQulity == AvRoomDataManager.get().mCurrentRoomInfo.getAudioQuality()) return; + RtcEngineManager.get().resetChannel(); + PlayerModel.get().stop(); + long uid = AuthModel.get().getCurrentUid(); + audioQulity = AvRoomDataManager.get().mCurrentRoomInfo.getAudioQuality(); + if (AvRoomDataManager.get().mCurrentRoomInfo.getAudioQuality() == 1) { + RtcEngineManager.get().reJoinChannel(AvRoomDataManager.get().mCurrentRoomInfo.getRoomId(), uid); + } else if (AvRoomDataManager.get().mCurrentRoomInfo.getAudioQuality() == 2) { + RtcEngineManager.get().reJoinHighQualityChannel(AvRoomDataManager.get().mCurrentRoomInfo.getRoomId(), uid, true); + } + } + + private void cleanDragonBar() { + LogUtil.e("cleanDragonBar"); + if (AvRoomDataManager.get().haveStartDragon) { + AvRoomDataManager.get().haveStartDragon = false; + ((AVRoomActivity) getActivity()).giveUpDragonBar().subscribe(s -> { + gameBinding.playDragon.setVisibility(View.INVISIBLE); + gameBinding.cancelDragon.setVisibility(View.INVISIBLE); + }); + } + } + + /** + * 左上角的活动,比较特殊,并且能触发暴走倒计时 + */ + private List specialActivities = new ArrayList<>(); + /** + * 显示活动图标 + */ + public void showActivity(List dialogInfo) { + List normalActivities = new ArrayList<>(); + if (dialogInfo == null) { + dialogInfo = new ArrayList<>(); + } + for (ActionDialogInfo info : dialogInfo) { + if (info.getEntrancePosition() == 2) { + specialActivities.add(info); + } else { + normalActivities.add(info); + } + } + if (AvRoomDataManager.get().isCpRoom()) { + initRoomAct(gameBinding.activityImgLeftCp, specialActivities, 11f); + } else { + initRoomAct(gameBinding.activityImgLeft, specialActivities, 11f); + } + + initRoomAct(gameBinding.activityImg, normalActivities, 11f); + setActTimerVisibility(View.GONE); + + AvRoomModel.get().getRoomActTimer(AvRoomDataManager.get().getRoomUid()) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(); + +// gameBinding.activityImg.setVisibility(View.INVISIBLE); +// mActionDialogInfoList = dialogInfo; +// if (!ListUtils.isListEmpty(dialogInfo) && !MarketVerifyModel.get().isMarketChecking()) { +// if (!isKtvMode && !isGameMode) { +// gameBinding.activityImg.setVisibility(View.VISIBLE); +// } +// +// // 只有一个图标,隐藏底部指示器 +// boolean show = dialogInfo.size() > 1; +// gameBinding.activityImg.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { +// @Override +// public Drawable makeFocusDrawable() { +// GradientDrawable dotFocus = new GradientDrawable(); +// dotFocus.setColor(Color.WHITE); +// dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); +// dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); +// return show ? dotFocus : null; +// } +// +// @Override +// public Drawable makeNormalDrawable() { +// GradientDrawable dotNormal = new GradientDrawable(); +// dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); +// dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); +// dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); +// return show ? dotNormal : null; +// } +// }); +// +// RoomActAdapter bannerAdapter = new RoomActAdapter(mContext, dialogInfo); +// gameBinding.activityImg.setAdapter(bannerAdapter); +// gameBinding.activityImg.setPlayDelay(3000); +// //设置透明度 +// gameBinding.activityImg.setAnimationDurtion(500); +// bannerAdapter.notifyDataSetChanged(); +// +// bannerAdapter.setRoomActClickListener(new RoomActAdapter.RoomActClickListener() { +// @Override +// public void onWebClick(String url) { +// DialogWebFragment.newInstance(url).show(getFragmentManager()); +// } +// }); +// +// // 模拟指示器在viewpager底部效果 +// ViewPager viewPager = gameBinding.activityImg.getViewPager(); +// viewPager.setOffscreenPageLimit(dialogInfo.size()); +// RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) viewPager.getLayoutParams(); +// layoutParams.setMargins(0, 0, 0, 30); +// viewPager.setLayoutParams(layoutParams); +// } else { +// gameBinding.activityImg.setVisibility(View.INVISIBLE); +// } + } + + private void setActTimerVisibility(int visibility) { + gameBinding.activityTimer.setVisibility(visibility); + gameBinding.activityTimerCp.setVisibility(visibility); + } + + public void initRoomAct(RollPagerView rollPagerView, List dialogInfo, float bottomDp) { + rollPagerView.setVisibility(View.INVISIBLE); + if (!ListUtils.isListEmpty(dialogInfo) && !MarketVerifyModel.get().isMarketChecking()) { + if (!isKtvMode && !isGameMode) { + rollPagerView.setVisibility(View.VISIBLE); + } + // 只有一个图标,隐藏底部指示器 + boolean show = dialogInfo.size() > 1; + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return show ? dotFocus : null; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return show ? dotNormal : null; + } + }); + + RoomActAdapter bannerAdapter = new RoomActAdapter(mContext, dialogInfo); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + bannerAdapter.notifyDataSetChanged(); + + bannerAdapter.setRoomActClickListener(new RoomActAdapter.RoomActClickListener() { + @Override + public void onWebClick(String url) { + DialogWebFragment.newInstance(url).show(getFragmentManager()); + } + }); + + // 模拟指示器在viewpager底部效果 + ViewPager viewPager = rollPagerView.getViewPager(); + viewPager.setOffscreenPageLimit(dialogInfo.size()); + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) viewPager.getLayoutParams(); + layoutParams.setMargins(0, 0, 0, UIUtil.dip2px(mContext, bottomDp)); + viewPager.setLayoutParams(layoutParams); + } + } + + private void releaseView() { + messageView.release(); + microView.release(); + if (musicPlayerView != null) { + musicPlayerView.release(); + } + GiftValueMrg.get().clearObsever(); + } + + private void updateView() { + + // 是否可以显示一起玩的骰子活动 + gameBinding.playTogether.setVisibility( + (!MarketVerifyModel.get().isMarketChecking() && + AvRoomDataManager.get().isAllowedToPlayTogether() && + (AvRoomDataManager.get().isRoomAdmin() || AvRoomDataManager.get().isRoomOwner())) && + (!AvRoomDataManager.get().isOpenKTV()) && !AvRoomDataManager.get().isCpRoom() ? + View.VISIBLE : + View.GONE); + + setToMiniWorldVisible(true); + + // 更新底栏 + showBottomViewForDifRole(); + if (AvRoomDataManager.get().isOpenKTV()) { + openKtvModel(); + } else { + closeKtvModel(); + } + if (AvRoomDataManager.get().isOpenGame()) { + openGameModel(); + } else { + closeGameModel(); + } + + if (microView.getAdapter() != null) { + String microType = microView.getAdapter().microType(); + + if (AvRoomDataManager.get().isCpRoom()) { + if (!microType.equals(BaseMicroViewAdapter.MICRO_TYPE_CP)) { + microView.bindAdapter(new CpMicroViewAdapter(mContext)); + } + + } else if (AvRoomDataManager.get().isOpenKTV()){ + if (!microType.equals(BaseMicroViewAdapter.MICRO_TYPE_KTV)) { + microView.bindAdapter(new KtvMicroViewAdapter(mContext)); + } + + } else { + if (!microType.equals(BaseMicroViewAdapter.MICRO_TYPE_NORMAL)) { + microView.bindAdapter(new MicroViewAdapter(mContext)); + } + } + microView.getAdapter().notifyDataSetChanged(); + microView.updateRoomInfo(); + } + if (!isGameMode && !isKtvMode) { + changeModelShowView(); + } else { + changeModeHideView(); + } + + updateActViewVisibility(); + + gameBinding.gameView.setCloseClick(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamechose_close_click, "游戏面板关闭"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_close_click, "游戏等待面板-房主关闭按钮"); + openOrCloseGame(); + }); + + } + + /** + * 设置活动入口是否可见 + */ + private void updateActViewVisibility() { + List list = new ArrayList<>(); + list.add(gameBinding.activityImg); + list.add(gameBinding.clActivityImgLeft); + list.add(gameBinding.clActivityImgLeftCp); + for (View index : list) { + index.setVisibility(isKtvMode || isGameMode ? View.INVISIBLE : View.VISIBLE); + } + } + + private void updateMentoringCountDownTimer() { + // 师徒关系里徒弟进入房间显示的倒计时 + if (AvRoomDataManager.get().isFromMentoring() && + AvRoomDataManager.get().mCurrentRoomInfo != null) { + if (countDownTimerLayout == null) { + countDownTimerLayout = countDownTimerViewStub.inflate(); + } + mentoringCountDownTimer = countDownTimerLayout.findViewById(R.id.tv_time); + mentoringCountDownTimer.setTextSize(16); + mentoringCountDownTimerIcon = countDownTimerLayout.findViewById(R.id.iv_clock); + countDownTimerLayoutBackground = countDownTimerLayout.findViewById(R.id.iv_countdown_timer_bg); + countDownTimerLayoutBackground.setImageResource(R.drawable.mentoring_count_down_timer_bg); + // 是否为师父的房间 + if (Objects.equals(AvRoomDataManager.get().getMasterUid(), + AvRoomDataManager.get().mCurrentRoomInfo.getUid())) { + countDownTimerViewStub.setVisibility(View.VISIBLE); + if (MentoringRelationshipModel.get().getMillisUntilFinished() == 0) { + mentoringCountDownTimer.setText(TimeUtils.ms2MS(0, false)); + getMvpPresenter().reportToServerMissionThree(); + } + } + } else { + if (countDownTimerViewStub != null) { + countDownTimerViewStub.setVisibility(View.GONE); + } + if (countDownTimerLayout != null) { + countDownTimerLayout.setVisibility(View.GONE); + } + } + } + + /** + * 根据角色显示不同的状态 + */ + private void showBottomViewForDifRole() { + boolean isOnMic = AvRoomDataManager.get().isOnMic(myUid); + // 更新播放器界面 + RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (mCurrentRoomInfo == null) return; + UserModel.get().getUserInfo(mCurrentRoomInfo.getUid()).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + if (mCompositeDisposable != null) { + mCompositeDisposable.add(d); + } + } + + @Override + public void onSuccess(UserInfo userInfo) { + roomOwnner = userInfo; + if (roomOwnner != null && isOnMic && !isKtvMode) { + if (musicPlayerView == null) { + musicPlayerView = (MusicPlayerView) mVsMusicPlayer.inflate(); + } + musicPlayerView.setVisibility(View.VISIBLE); + musicPlayerView.setImageBg(roomOwnner.getAvatar()); + } + if (musicPlayerView != null) { + musicPlayerView.setVisibility((isOnMic && !isKtvMode && !AvRoomDataManager.get().gameModel) ? View.VISIBLE : View.GONE); + } + + } + + @Override + public void onError(Throwable e) { + + } + }); + + setDragonView(); + if (isOnMic) { + bottomView.showHomePartyUpMicBottom(); + } else { + bottomView.showHomePartyDownMicBottom(); + } + bottomView.showInputOrIcon(isOnMic); + bottomView.showGameBottom(); + // 更新听筒消息 + bottomView.setRemoteMuteOpen(!RtcEngineManager.get().isRemoteMute); + } + + private void checkMiniWorld() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + //过滤没有房间信息和没有小世界的房间 + if (roomInfo == null || roomInfo.getWorldId() == 0) { + return; + } + getMvpPresenter().checkMiniWorld(roomInfo.getWorldId()); + + } + + /** + * 检查是否关注房主,然后弹出 + */ + private void checkFollowOwner() { + if (roomOwnner == null) { + return; + } + //如果当前账号是房主也过滤 + if (AuthModel.get().getCurrentUid() == roomOwnner.getUid()) { + return; + } + getMvpPresenter().checkFollow(roomOwnner.getUid()); + } + + private void updateMicBtn() { + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoomInfo != null) { + if (RtcEngineManager.get().isAudienceRole) { + bottomView.setMicBtnEnable(false); + bottomView.setMicBtnOpen(false); + } else { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByAccount(String.valueOf(myUid)); + if (roomQueueInfo != null && roomQueueInfo.mChatRoomMember != null + && Objects.equals(String.valueOf(myUid), + roomQueueInfo.mChatRoomMember.getAccount()) + && roomQueueInfo.mRoomMicInfo != null + && roomQueueInfo.mRoomMicInfo.isMicMute()) { + //先判断坑位是否被闭麦了 + bottomView.setMicBtnEnable(false); + bottomView.setMicBtnOpen(false); + } else { + bottomView.setMicBtnEnable(true); +// if (RtcEngineManager.get().isMute) { +// bottomView.setMicBtnEnable(true); +// bottomView.setMicBtnOpen(false); +// } else { +// bottomView.setMicBtnEnable(true); +// bottomView.setMicBtnOpen(true); +// } + if (RtcEngineManager.get().isMute) { + bottomView.setMicBtnOpen(false); + } else { + //获取当前是否有麦克风权限 + boolean isPermission = isHavingMicPermissions(); + if (!isPermission) { + RtcEngineManager.get().setMute(true); + } + bottomView.setMicBtnOpen(isPermission); + + } + } + } + } else { + bottomView.setMicBtnEnable(false); + bottomView.setMicBtnOpen(false); + } + } + + private void updateQueuingMicBtn() { + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + bottomView.setQueuingMicButton(AvRoomDataManager.get().isQueuingMicro() + || AvRoomDataManager.get().isOpenPKMode()); + + if (!AvRoomDataManager.get().isQueuingMicro()) { + if (isMicQueueDialogShowing()) { + micQueueDialog.dismiss(); + } + } + + if (!AvRoomDataManager.get().isOpenPKMode()) { + if (isPKMicQueueDialogShowing()) { + pkMicQueueDialog.dismiss(); + } + } + } + } + + private void updateRemoteMuteBtn() { + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + bottomView.setRemoteMuteOpen(!RtcEngineManager.get().isRemoteMute); + } + } + + public void onMicStateChanged() { + updateMicBtn(); + } + + public void updatePkBoard() { + if (AvRoomDataManager.get().isOpenPKMode()) { + + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + releaseView(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + if (mDisposable != null) { + mDisposable.dispose(); + mDisposable = null; + } + EventBus.getDefault().unregister(this); + + super.onDestroy(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void displayMentoringCountDownTimer(MentoringCountingEvent event) { + long mills = event.getMillisUntilFinished(); + if (mentoringCountDownTimer != null) { + mentoringCountDownTimer.setText(TimeUtils.ms2MS(mills, false)); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void displayMentoringCountDownTimerFinished(MentoringCountingFinishEvent event) { + if (mentoringCountDownTimer != null) { + mentoringCountDownTimer.setText(TimeUtils.ms2MS(0, false)); + } + getMvpPresenter().reportToServerMissionThree(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void hideMentoringCountDownTimer(MentoringStopCountingEvent event) { + if (countDownTimerViewStub != null) { + countDownTimerViewStub.setVisibility(View.GONE); + } + if (countDownTimerLayout != null) { + countDownTimerLayout.setVisibility(View.GONE); + } + } + + /** + * 排麦模式从有人到无人 + * + * @param event + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void displayEmptyQueuingMic(QueuingMicEmptyEvent event) { + bottomView.setQueuingMicButtonBackground(true); + } + + /** + * 排麦模式从无人到有人 + * + * @param event + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void displayNotEmptyQueuingMic(QueuingMicNotEmptyEvent event) { + bottomView.setQueuingMicButtonBackground(false); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onAntiSpamEvent(AntiSpamEvent event) { +// Toast.makeText(getContext(), "发送失败,轻寻提醒您文明用语~", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("发送失败,轻寻提醒您文明用语~"); + } + + /** + * 清除公屏信息 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void onClearScreenEvent(RoomClearScreenEvent event) { + clearScreen(); + ChatRoomMessage firstMsg = IMNetEaseManager.get().getFirstMessageContent(); + addMessage(firstMsg); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.input_send: + sendMsg(); + break; + + case R.id.play_together: + if (!DynamicFaceModel.get().isShowingFace()) { + FaceInfo faceInfo = DynamicFaceModel.get().getPlayTogetherFace(); + if (faceInfo != null) { + DynamicFaceModel.get().sendAllFace(faceInfo); + } else { + toast("加载失败,请重试!"); + } + } + break; + + case R.id.iv_to_mini_world: + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null && roomInfo.getWorldId() > 0) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MINI_WORLD_ROOM_BACK_TO_WORLD, "语音房-回到小世界"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_VIEW_WORLD_PAGE, + "进入小世界客态页:语音派对"); + MiniWorldGuestPageActivity.start(mContext, String.valueOf(roomInfo.getWorldId())); + ((AVRoomActivity) getActivity()).onBackPressed(); + } + break; +// case R.id.activity_img: +// if (!ListUtils.isListEmpty(mActionDialogInfoList)) { +// ActionDialogInfo dialogInfo = mActionDialogInfoList.get(0); +// CommonWebViewActivity.start(getContext(), dialogInfo.getSkipUrl()); +// } +// break; + case R.id.iv_ktv_contribute_list: + case R.id.contribute_list: + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_RANKING_LIST_CLICK, "房间榜"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_RANKING_LIST_CLICK, "房间榜"); +// RoomRankListActivity.start(getActivity()); + + if (getChildFragmentManager().findFragmentByTag("dialog_fragment_room_rank") != null) { + return; + } + if (roomOwnner != null) { + RoomRankDialogFragment roomRankDialogFragment = RoomRankDialogFragment.newInstance(roomOwnner.getUid()); + roomRankDialogFragment.show(getChildFragmentManager(), "dialog_fragment_room_rank"); + } + + break; + case R.id.iv_treasure_box: + case R.id.iv_treasure_box_cp: + onClickBox(); + break; + case R.id.iv_dragon_start_button: + if (AvRoomDataManager.get().haveStartDragon) { + return; + } + playDragon(); + break; + case R.id.play_dragon: + playDragon(); + break; + case R.id.cancel_dragon: + ((AVRoomActivity) getActivity()).giveUpDragonBar().subscribe(s -> { + gameBinding.playDragon.setVisibility(View.INVISIBLE); + gameBinding.cancelDragon.setVisibility(View.INVISIBLE); + getMvpPresenter().cancelDragon(); + }); + break; + case R.id.stv_ktv_song: + KtvSongListActivity.start(mContext, false); + break; + + case R.id.tv_room_introduction: + showRoomIntroduction(AvRoomDataManager.get().isRoomOwner() || AvRoomDataManager.get().isRoomAdmin()); + break; + default: + } + } + + private void sendMsg() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (roomInfo.isCloseScreen()) { + toast("房间公屏已关闭"); + return; + } + getMvpPresenter().sendTextMsg(inputEdit.getText().toString()); + messageView.setNeedAutoScroll(true); // 发送后自动滚动公屏列表 + inputEdit.setText(""); + } + + public void onClickBox() { + if (getFragmentManager() != null) { + ChooseTreasureBoxDialogFragment chooseTreasureBoxDialogFragment = new ChooseTreasureBoxDialogFragment(); + chooseTreasureBoxDialogFragment.setOnTreasureBoxChooseListener(type -> { + if (type == 0) {// 普通蛋(默认) + TreasureBoxActivity.start(getActivity()); + } else if (type == 1) {// 至尊蛋 + TreasureBoxHonourActivity.start(getActivity()); + } + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_SMASH_EGG_CLICK, "砸蛋入口"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_SMASH_EGG_CLICK, "砸蛋入口"); + }); + chooseTreasureBoxDialogFragment.show(getFragmentManager(), "chooseTreasureBoxDialogFragment"); + } else { + TreasureBoxActivity.start(getActivity()); + } + } + + private void playDragon() { + List faceInfos = DynamicFaceModel.get().getFaceInfos(); + if (faceInfos == null) { + toast("交友匹配正在准备"); + return; + } + FaceInfo info = null; + for (FaceInfo faceInfo : faceInfos) { + if (faceInfo.getId() == Constants.DRAGON_BAR_ID) { + info = faceInfo; + } + } + if (info == null) return; + if (AvRoomDataManager.get().haveStartDragon) { + getMvpPresenter().clearDragonBar().subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + gameBinding.playDragon.setVisibility(View.INVISIBLE); + gameBinding.cancelDragon.setVisibility(View.INVISIBLE); + }); + } else { + getMvpPresenter().getDragonBar(info).subscribe(s -> { + gameBinding.playDragon.setVisibility(View.VISIBLE); + gameBinding.cancelDragon.setVisibility(View.VISIBLE); + }); + } + } + + private SoftKeyBoardListener.OnSoftKeyBoardChangeListener + mOnSoftKeyBoardChangeListener = new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() { + @Override + public void keyBoardShow(int height) { + /*软键盘显示:执行隐藏title动画,并修改listview高度和装载礼物容器的高度*/ + } + + @Override + public void keyBoardHide(int height) { + /*软键盘隐藏:隐藏聊天输入框并显示聊天按钮,执行显示title动画,并修改listview高度和装载礼物容器的高度*/ + inputLayout.setVisibility(View.GONE); + } + }; + + /** + * 软键盘显示与隐藏的监听 + */ + private void softKeyboardListener() { + SoftKeyBoardListener.setListener(getActivity(), mOnSoftKeyBoardChangeListener); + } + + @SuppressLint("CheckResult") + @Override + public void onSendGiftBtnClick(GiftInfo giftInfo, List micMemberInfos, + int number, String msg, boolean isKnap, + boolean isWholdMic, GiftDialog.SenGiftCallback callback) { + List targetUids = new ArrayList<>(); + for (int i = 0; i < micMemberInfos.size(); i++) { + targetUids.add(micMemberInfos.get(i).getUid()); + } + boolean canUseNobleGiftOrNot = GiftModel.get().canUseNobleGiftOrNot(giftInfo); + if (canUseNobleGiftOrNot) { + GiftModel.get() + .sendRoomGift(giftInfo.getGiftId(), targetUids, number, msg, isKnap, isWholdMic) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(ServiceResult giftMultiReceiverInfoServiceResult, Throwable throwable) throws Exception { + if (throwable != null) { + callback.onFail(); + return; + } + callback.onSuccess(); + } + }); + } else { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + int currentLevel = userInfo == null ? 0 : userInfo.getNobleInfo() == null ? 0 : userInfo.getNobleInfo().getLevel(); + new OpenNobleDialog(mContext, currentLevel, giftInfo.getLevel(), "送该礼物").show(); + callback.onFail(); + } + + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gift_open_click, "礼物面板按钮"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gift_send_click, "礼物赠送按钮"); + } + } + + @Override + public void onSendMagicBtnClick(MagicInfo magicInfo, long targetUid, GiftDialog.SenGiftCallback callback) { + + } + + + void onUpMicro(int micPosition) { + showBottomViewForDifRole(); + updateMicBtn(); + microView.getAdapter().notifyDataSetChanged(); + gameBinding.gameView.updateUpMic(); + } + + void onInviteUpMic(final int micPosition) { + AvRoomDataManager.get().mIsNeedOpenMic = true; + getMvpPresenter().upMicroPhone(micPosition, String.valueOf(AuthModel.get().getCurrentUid()), true); + if (UIUtils.isTopActivity(getBaseActivity())) { + ((BaseMvpActivity) getActivity()).getDialogManager() + .showOkWithTitleDialog(getString(R.string.embrace_on_mic), true); + } + //被人抱上麦 + //自己取消报名 + cancelMyQueue(); + + } + + void onDownMicro(int micPosition) { + showBottomViewForDifRole(); + updateMicBtn(); + gameBinding.microView.removeDragonBar(micPosition); + microView.getAdapter().notifyDataSetChanged(); + gameBinding.gameView.downMic(); + } + + + void onQueueMicStateChange(int micPosition, int micPosState) { + microView.getAdapter().notifyDataSetChanged(); + onMicStateChanged(); + } + + private void addOrRemoveMatchPool() { + if (GameModel.get().needRemovePool()) { + GameModel.get().removePool(GameModel.get().getGameId()).subscribe(); + } + if (AvRoomDataManager.get().isCpRoom() && AvRoomDataManager.get().isRoomOwner()) { + if (AvRoomDataManager.get().findFreePosition() > 0) { + AvRoomModel.get().removeIsomerism().subscribe(); + } else if (TextUtils.isEmpty(AvRoomDataManager.get().mCurrentRoomInfo.getLimitType()) + && TextUtils.isEmpty(AvRoomDataManager.get().mCurrentRoomInfo.getRoomPwd())) { + AvRoomModel.get().addIsomerism().subscribe(); + } + } + } + + @Override + public void resultLoadNormalMembers(List chatRoomMemberList) { + + } + + + @Override + public void showMicAvatarClickDialog(List buttonItemList, String uid) { + GiftDialog.GIFT_DIALOG_FROM = "房间"; + UserInfoDialog dialog = new UserInfoDialog(mContext, JavaUtil.str2long(uid), buttonItemList, true); + dialog.show(); + //getDialogManager().showCommonPopupDialog(buttonItemList, getString(R.string.cancel)); + } + + @Override + public void showMicAvatarUserInfoDialog(String uId) { + if (TextUtils.isEmpty(uId)) { + return; + } + new UserInfoDialog(getContext(), Long.valueOf(uId)).show(); + } + + @Override + public void kickDownMicroPhoneSuccess() { + updateMicBtn(); + toast(R.string.kick_mic); + } + + @Override + public void showOwnerClickDialog(final RoomMicInfo roomMicInfo, final int micPosition, final long currentUid) { + List buttonItems = new ArrayList<>(4); + final ButtonItem buttonItem1 = new ButtonItem(getString(R.string.embrace_up_mic), new ButtonItem.OnClickListener() { + @Override + public void onClick() { + RoomInviteActivity.openActivity(getActivity(), micPosition); + } + }); + ButtonItem buttonItem2 = new ButtonItem(roomMicInfo.isMicMute() ? getString(R.string.no_forbid_mic) : getString(R.string.forbid_mic), new ButtonItem.OnClickListener() { + @Override + public void onClick() { + if (roomMicInfo.isMicMute()) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + getMvpPresenter().openMicroPhone(micPosition); + } else { + getMvpPresenter().roomOperate(SuperAdminModel.CLOSE_MIC); + getMvpPresenter().closeMicroPhone(micPosition); + } + } + }); + boolean isQueue = AvRoomDataManager.get().isQueuingMicro(); + boolean isBossMic = micPosition == -1; + String unlockStr = getString(isQueue && (!isBossMic) ? R.string.unlock_mic_queue : R.string.unlock_mic); + String lockStr = getString(isQueue && (!isBossMic) ? R.string.lock_mic_queue : R.string.lock_mic); + ButtonItem buttonItem3 = new ButtonItem(roomMicInfo.isMicLock() ? unlockStr : + lockStr, new ButtonItem.OnClickListener() { + @Override + public void onClick() { + if (roomMicInfo.isMicLock()) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + getMvpPresenter().unLockMicroPhone(micPosition); + } else { + if (GameModel.get().needRemovePool()) { + GameModel.get().removePool(GameModel.get().getGameId()).subscribe(); + } + getMvpPresenter().roomOperate(SuperAdminModel.LOCK_MIC); + getMvpPresenter().lockMicroPhone(micPosition); + } + } + }); + ButtonItem buttonItem4 = new ButtonItem("上麦", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + toUpMicroPhone(micPosition, currentUid + "", false); + + + } + }); + //别问为什么,ui调整了顺序 + //禁用超管的上麦和抱TA上麦 + if (!SuperAdminUtil.isSuperAdmin()) { + buttonItems.add(buttonItem4); + buttonItems.add(buttonItem1); + } + + if (!AvRoomDataManager.get().isOpenPKMode()) { + //超管只有锁麦操作 + if (SuperAdminUtil.isSuperAdmin()) { + if (!roomMicInfo.isMicLock() && !isQueue) { + buttonItems.add(buttonItem3); + } + } else { + buttonItems.add(buttonItem3); + } + } + //超管只有闭麦操作 + if (SuperAdminUtil.isSuperAdmin()) { + if (!roomMicInfo.isMicMute()) { + buttonItems.add(buttonItem2); + } + } else { + buttonItems.add(buttonItem2); + } + + getDialogManager().showCommonPopupDialog(buttonItems, getString(R.string.cancel)); + } + + + @Override + public void chatRoomReConnectView() { + if (microView != null && microView.getAdapter() != null) + microView.getAdapter().notifyDataSetChanged(); + } + + @Override + public void onAvatarBtnClick(int position) { + //getMvpPresenter().avatarClick(position, null); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null && roomInfo.isLeaveMode() && position == -1) { + showUserCardDialog(String.valueOf(roomInfo.getUid())); + + } else { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByMicPosition(position); + if (roomQueueInfo == null || roomQueueInfo.mChatRoomMember == null) { + return; + } + String account = roomQueueInfo.mChatRoomMember.getAccount(); + if (TextUtils.isEmpty(account)) { + return; + } + showUserCardDialog(account); + + } + } + + @Override + public void onUpMicBtnClick(int position, ChatRoomMember chatRoomMember) { + getMvpPresenter().microPhonePositionClick(position, chatRoomMember); + } + + @Override + public void onLockBtnClick(int position) { + getMvpPresenter().unLockMicroPhone(position); + } + + @Override + public void onRoomSettingsClick() { + showRoomIntroduction(AvRoomDataManager.get().isRoomOwner() || AvRoomDataManager.get().isRoomAdmin()); + } + + private void showRoomIntroduction(boolean isModify) { + RoomInfo info = AvRoomDataManager.get().mCurrentRoomInfo; + if (info == null) return; + if (SuperAdminUtil.isSuperAdmin()) { + isModify = false; + } + if (isModify) { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_SET_TOPIC_CLICK, "设置房间话题"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_SET_TOPIC_CLICK, "设置房间话题"); + RoomTitleEditActivity.startForResult(getActivity(), info.getRoomDesc(), info.getIntroduction()); + } else { + DialogFragment dialogFragment = RoomTitleDialogFragment.getInstance(info.getRoomDesc(), info.getIntroduction()); + dialogFragment.show(getActivity().getSupportFragmentManager(), "roomTitle"); + } + } + + private DynamicFaceDialog dynamicFaceDialog = null; + private GiftDialog giftDialog = null; + + @Override + public void onBeginPK(PKBoardView.OnOperateStatusCallback callback) { + if (!AvRoomDataManager.get().isManager()) { + return; + } + + if (PkModel.get().getCurPkInfo() != null + && PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_AFTER_PK) { + getDialogManager().showOkCancelWithTitleDialog( + "是否再次开始PK?", + () -> { + //开始PK 倒计时 + callback.onStart(); + PkModel.get().toPKAgain() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + callback.onFinish(); + pkBoardView.updateView(); + toast(s); + } + + @Override + public void onError(Throwable e) { + callback.onFinish(); + toast(e.getMessage()); + } + }); + + }); + return; + } + getDialogManager().showOkCancelWithTitleDialog( + "当前正在准备阶段,是否确认准备开始PK?", + () -> { + //开始PK 倒计时 + callback.onStart(); + PkModel.get().beginPK() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + callback.onFinish(); + pkBoardView.updateView(); + toast(s); + } + + @Override + public void onError(Throwable e) { + callback.onFinish(); + toast(e.getMessage()); + } + }); + + }); + + + } + + @Override + public void onEndPK() { + PKResultDialog pkResultDialog = new PKResultDialog(getContext(), PkModel.get().getCurPkInfo()); + pkResultDialog.show(); + } + + @Override + public void onShowPKMicQueueDialog() { + pkMicQueueDialog = new PKMicQueueDialog(mContext); + pkMicQueueDialog.setActionListener(new PKMicQueueDialog.OnActionListener() { + @Override + public void onShareRoom(PKMicQueueDialog micQueueDialog) { + micQueueDialog.dismiss(); + if (parentFragment != null) { + parentFragment.shareRoom(); + } + } + + @Override + public void onApplyMicQueue(PKMicQueueDialog micQueueDialog, int teamId) { + long myUid = AuthModel.get().getCurrentUid(); + if (AvRoomDataManager.get().isOnMic(myUid)) { + toast("已经在麦上不需要报名啦~"); + return; + } + //加入排队 + PkModel.get().joinPKMicQueue( + teamId + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + micQueueDialog.addDisposable(d); + } + + @Override + public void onSuccess(PKRespQueuingMicListInfo info) { + micQueueDialog.updateQueueInfo(info); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + @Override + public void onCancelMicQueue(PKMicQueueDialog micQueueDialog) { + getDialogManager().showOkCancelDialog( + "取消报名后再次报名需要重新排麦哦!\n确认取消报名吗?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + PkModel.get().leavePKMicQueue() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + micQueueDialog.addDisposable(d); + } + + @Override + public void onSuccess(PKRespQueuingMicListInfo info) { + micQueueDialog.updateQueueInfo(info); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + }); + } + }); + pkMicQueueDialog.show(); + } + + + /** + * 底部按钮点击处理 + */ + private class GameRoomBottomViewWrapper extends BottomViewListenerWrapper { + @Override + public void onOpenMicBtnClick() { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByAccount( + String.valueOf(AuthModel.get().getCurrentUid())); + if (roomQueueInfo == null || roomQueueInfo.mRoomMicInfo == null) return; + //先判断麦上是否是开麦的 + if (!roomQueueInfo.mRoomMicInfo.isMicMute() && !RtcEngineManager.get().isAudienceRole) { + + if (!isHavingMicPermissions()) { + RxPermissions rxPermissions = new RxPermissions(HomePartyRoomFragment.this); + rxPermissions.request(Manifest.permission.RECORD_AUDIO).subscribe(new Consumer() { + @Override + public void accept(Boolean aBoolean) throws Exception { + if (aBoolean) { + AvRoomDataManager.get().mIsNeedOpenMic = false; + RtcEngineManager.get().setMute(!RtcEngineManager.get().isMute); + RtcEngineManager.get().setRole(Constants.CLIENT_ROLE_BROADCASTER); +// AvRoomDataManager.get().mIsNeedOpenMic = RtcEngineManager.get().isMute; + updateMicBtn(); + } else { + toast("开启权限后才能开麦"); + } + } + }); + return; + } + AvRoomDataManager avRoomDataManager = AvRoomDataManager.get(); + boolean tmp = avRoomDataManager.mIsNeedOpenMic; + RtcEngineManager.get().setMute(!RtcEngineManager.get().isMute); + AvRoomDataManager.get().mIsNeedOpenMic = RtcEngineManager.get().isMute; + boolean tmp1 = avRoomDataManager.mIsNeedOpenMic; + updateMicBtn(); + + if (!tmp) { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_CLOSE_MIC_CLICK, "关闭麦克风"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_CLOSE_MIC_CLICK, "关闭麦克风"); + } + } + //判断是否在麦上,如果在麦上设置为主播角色 + else if (AvRoomDataManager.get().isOnMic(myUid)) { + RtcEngineManager.get().setRole(Constants.CLIENT_ROLE_BROADCASTER); + } + } + + } + + @Override + public void onSendFaceBtnClick() { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_EMOTICON_CLICK, "表情面板按钮"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_EMOTICON_CLICK, "表情面板按钮"); + + if (AvRoomDataManager.get().isOnMic(myUid) || AvRoomDataManager.get().isRoomOwner()) { + if (dynamicFaceDialog == null) { + dynamicFaceDialog = new DynamicFaceDialog(getContext()); + dynamicFaceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + dynamicFaceDialog = null; + } + }); + dynamicFaceDialog.setFaceFilter(new DynamicFaceDialog.FaceFilter() { + @Override + public List onFilter(List faceInfoList) { + //审核中版本过滤表情,显示 + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator faceInfoIterator = faceInfoList.iterator(); + while (faceInfoIterator.hasNext()) { + FaceInfo faceInfo = faceInfoIterator.next(); + if (faceInfo.getId() == 24 + || faceInfo.getId() == 17 + || faceInfo.getId() == 40) { + faceInfoIterator.remove(); + } + } + return faceInfoList; + } else { + return faceInfoList; + } + + } + }); + } + if (!dynamicFaceDialog.isShowing()) { + dynamicFaceDialog.show(); + } + } else { + toast("上麦才能发表情哦!"); + } + } + + @Override + public void onSendMsgBtnClick() { + inputLayout.setVisibility(View.VISIBLE); + inputEdit.setFocusableInTouchMode(true); + inputEdit.requestFocus(); + KeyBoardUtils.showKeyBoard(getContext(), inputEdit); + + // + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.EVENT_ROOM_INPUT_BOX_CLICK, "底部文字输入框点击", null); + + } + + @Override + public void onSendGiftBtnClick() { + if (giftDialog == null) { + GiftDialog.GIFT_DIALOG_FROM = "房间"; + giftDialog = new GiftDialog(getContext(), 0, true); + giftDialog.setGiftDialogBtnClickListener(HomePartyRoomFragment.this); + giftDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + giftDialog = null; + } + }); + } + if (!giftDialog.isShowing() && !getActivity().isFinishing()) { + giftDialog.show(); + } + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_GIFT_CLICK, "礼物面板按钮"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_GIFT_CLICK, "礼物面板按钮"); + } + + @Override + public void onRemoteMuteBtnClick() { + boolean isRemoteMute = !RtcEngineManager.get().isRemoteMute; + if (isRemoteMute) { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_CLOSE_SOUND_CLICK, "关闭声音"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_CLOSE_SOUND_CLICK, "关闭声音"); + } + RtcEngineManager.get().setRemoteMute(isRemoteMute); + updateRemoteMuteBtn(); + } + + @Override + public void onMoreBtnClick() { + + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_MORE_CLICK, "更多面板按钮"); + } else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_MORE_CLICK, "更多面板按钮"); + + RoomOperationDialog dialog = new RoomOperationDialog(mContext); + dialog.setOnActionListener(new RoomOperationDialog.OnActionListener() { + @Override + public void onSwitchGiftEffect() { + AvRoomDataManager.get().haveSelfChange = true; + AvRoomDataManager.get().mIsNeedGiftEffect = !AvRoomDataManager.get().mIsNeedGiftEffect; +// Toast.makeText( +// mContext, +// AvRoomDataManager.get().mIsNeedGiftEffect ? "礼物特效已开启" : "礼物特效已关闭", +// Toast.LENGTH_SHORT +// ).show(); + SingleToastUtil.showToastShort(AvRoomDataManager.get().mIsNeedGiftEffect ? "礼物特效已开启" : "礼物特效已关闭"); + + EventBus.getDefault().post(new HasAnimationEffect()); + } + + @Override + public void onSwitchPublicScreen() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + if (roomInfo.isCloseScreen()) { + getMvpPresenter().roomOperate(SuperAdminModel.OPEN_PUBLIC_SCREEN); + }else { + getMvpPresenter().roomOperate(SuperAdminModel.CLOSE_PUBLIC_SCREEN); + } + AvRoomModel.get().closeScreen(roomInfo.getRoomId(), + !roomInfo.isCloseScreen()) + .compose(bindToLifecycle()) + .flatMap(data -> IMNetEaseManager.get().closeOpenScreen( + data.getRoomId(), data)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(); + } + + @Override + public void onSetting() { + RoomSettingActivity.start(mContext); + } + + @Override + public void onRoomLimit() { + new RoomImposeDialog(getActivity()).show(); + } + + @Override + public void onRoomAdmin() { + RoomManagerListActivity.start(mContext); + } + + @Override + public void onRoomKTV() { + if (!isKtvMode) { + + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + + if (roomInfo.isLeaveMode()) { + SingleToastUtil.showToast("开启ktv请先关闭离开模式"); + return; + } + + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_ktv_open_click, "开启KTV"); + } + String giftValueTips = ""; + if (AvRoomDataManager.get().isShowGiftValue()) { + giftValueTips = "\n开启KTV模式默认关闭礼物值"; + } + getDialogManager().showOkCancelWithTitleDialog( + isGameMode ? "当前正在游戏中,切换至KTV后将会关闭游戏模式,确认切换至KTV吗?" : + "是否开启KTV功能?\n开启后所有麦上用户可通过KTV入口点歌" + giftValueTips, + HomePartyRoomFragment.this::openKtvModelByRequest); + } else { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_ktv_choosesong_click, "KTV点唱"); + } + + KtvSelectSongActivity.start(mContext, false); + } + } + + @Override + public void onPKAction() { + CreatePKActivity.start(getContext()); + } + + @Override + public void onRoomHall() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_MY_HALL_CLICK, "厅管理入口"); + ModuleHallActivity.start(mContext); + } + + @Override + public void onGiftValue() { + if (AvRoomDataManager.get().isCpRoom()) { + return; + } + if (AvRoomDataManager.get().isOpenKTV()) { + SingleToastUtil.showToast(mContext.getResources().getString( + R.string.before_open_gift_value_should_close_ktv_model)); + return; + } + //开启礼物值不需要弹框 + if (!AvRoomDataManager.get().isShowGiftValue()) { + handleOpenGiftValue(); + return; + } + if (!GiftValueDialogUiHelper.get().isNeedConfirmDialog( + GiftValueDialogUiHelper.TYPE_CLOSE_SHOW_GIFT_VALUE)) { + handleOpenGiftValue(); + return; + } + GiftValueDialogUiHelper.get().showGiftValueDialog(mContext, getDialogManager(), + GiftValueDialogUiHelper.TYPE_CLOSE_SHOW_GIFT_VALUE, + this::handleOpenGiftValue); + + } + + private void handleOpenGiftValue() { + boolean isOpen = !AvRoomDataManager.get().isShowGiftValue(); + GiftValueModel.get().openGiftValue(isOpen) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_ROOM_GIFTVALUE_SWITCH, + "礼物值开关,区分状态:" + isOpen); +// if (isOpen && getActivity() instanceof AVRoomActivity) { +// ((AVRoomActivity) getActivity()).handleGiftValueStartTips(); +// } + } + } + }); + } + + @Override + public void onGameAction() { + + showGameSelectDialog(); + } + + @Override + public void onSuperAdmin() { + RoomSAdminManagerActivity.start(mContext); + } + }); + dialog.show(); + } + + + /** + * 点击排麦按钮 + */ + @Override + public void onMicQueueClick() { + if (AvRoomDataManager.get().isOpenPKMode()) { + onShowPKMicQueueDialog(); + } else { + micQueueDialog = new MicQueueDialog(mContext); + micQueueDialog.setActionListener(new MicQueueDialog.OnActionListener() { + @Override + public void onShareRoom(MicQueueDialog micQueueDialog) { + parentFragment.shareRoom(); + } + + @Override + public void onApplyMicQueue(final MicQueueDialog micQueueDialog) { + long myUid = AuthModel.get().getCurrentUid(); + if (AvRoomDataManager.get().isOnMic(myUid)) { + toast("已经在麦上不需要报名啦~"); + return; + } + //加入排队 + MicQueueModel.get().applyForQueuing( + AvRoomDataManager.get().getRoomUid(), AuthModel.get().getCurrentUid() + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + micQueueDialog.addDisposable(d); + } + + @Override + public void onSuccess(RespQueuingMicListInfo info) { + micQueueDialog.updateQueueInfo(info); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + + @Override + public void onCancelMicQueue(final MicQueueDialog micQueueDialog) { + //取消排队 + getDialogManager().showOkCancelDialog( + "取消报名后再次报名需要重新排麦哦!\n确认取消报名吗?", + true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + MicQueueModel.get().cancelApplyForQueuing( + AvRoomDataManager.get().getRoomUid(), + AuthModel.get().getCurrentUid()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + micQueueDialog.addDisposable(d); + } + + @Override + public void onSuccess(RespQueuingMicListInfo info) { + micQueueDialog.updateQueueInfo(info); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + }); + } + }); + micQueueDialog.show(); + } + } + + @Override + public void onTransformGameClick() { + super.onTransformGameClick(); + openOrCloseGame(); + } + + @Override + public void onRoomMessageClick() { + RoomMsgActivity.start(mContext); + } + } + + private void showGameSelectDialog() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game, "多人房点击游戏选择面板按钮"); + GameSelectDialog dialog = new GameSelectDialog(getActivity(), false); + dialog.setOnSelectClick(gameInfo -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_choice, "选择游戏" + gameInfo.getGameName()); + + if (ImGameMode.get().getRoomTime() == 0) { + ImGameMode.get().sendRoomSponsorGameMsg(gameInfo); + } else { + SingleToastUtil.showToast(ImGameMode.gameFrequency + "秒内只能发起一次哦"); + } + }); + dialog.show(); + } + + private void openOrCloseGame() { + getDialogManager().showOkCancelDialog(AvRoomDataManager.get().gameModel ? "确定不再玩一会儿??" + : isKtvMode ? "关闭KTV后,所有歌曲将被删除!确认关闭KTV并切换至游戏模式吗?" : "即将开启快玩模式,你准备好了吗?", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + openGameModelServer(!AvRoomDataManager.get().gameModel); + } + }); + } + + @SuppressLint("CheckResult") + private void openKtvModelByRequest() { + KtvModel.get().openKtvMode(AvRoomDataManager.get().mCurrentRoomInfo.getUid()) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(Boolean aBoolean) { + openKtvModel(); + KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_OPEN, new MusicInfo()) + .subscribe(chatRoomMessage -> IMNetEaseManager.get().addMessages(chatRoomMessage)); + } + }); + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.EVENT_ROOM_SWITCH_KTV_CLICK, "切换KTV模式", null); + } + + @SuppressLint("CheckResult") + private void openKtvModel() { + if (isKtvMode) { + return; + } + isKtvMode = true; + gameBinding.microView.openKtvMode(); + showKtvRelaView(); + KtvMusicManager.INSTANCE.reset(); + if (ktvDisposable != null) ktvDisposable.dispose(); + ktvDisposable = RxBus.get().toFlowable(KtvEvent.class) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .filter(ktvEvent -> ktvEvent.getType() == KtvEvent.CLOSE_KTV_MODEL) + .subscribe(ktvEvent -> closeKtvModelByRequest()); + //开启ktv模式,清除礼物值 + GiftValueMrg.get().clearObsever(); + } + + private void closeKtvModel() { + if (!isKtvMode) { + return; + } + isKtvMode = false; + gameBinding.microView.closeKtvMode(); + hideKtvRelaView(); + if (ktvDisposable != null) ktvDisposable.dispose(); + } + + private void showKtvRelaView() { + gameBinding.setKtvModel(true); + gameBinding.llKtvTop.setVisibility(View.VISIBLE); + gameBinding.contributeList.setVisibility(View.GONE); + //PK模式不显示这个玩意 + if (!AvRoomDataManager.get().isOpenPKMode()) { + stvKtvSong.setVisibility(View.VISIBLE); + setToMiniWorldVisible(false); + } + changeModeHideView(); + gameBinding.bottomView.showKtvBottom(true); + if (getActivity() != null) { + ViewModelProviders.of(getActivity()).get(RoomViewModel.class) + .getIsKtvModel().setValue(true); + } + } + + private void changeModeHideView() { + gameBinding.ivTreasureBoxCp.setVisibility(View.GONE); + gameBinding.ivTreasureBox.setVisibility(View.GONE); + + setActViewVisibility(View.INVISIBLE); + + // gameBinding.activityImg.setVisibility(View.GONE); + if (musicPlayerView != null) { + musicPlayerView.setVisibility(View.GONE); + int state = PlayerModel.get().getState(); + if (state == PlayerModel.STATE_PLAY) { + PlayerModel.get().pause(); + } + } + setDragonView(); + //显示ktv的宝箱 + if (getParentFragment() != null && getParentFragment() instanceof HomePartyFragment) { + ((HomePartyFragment) getParentFragment()).showKtvBox(); + } + gameBinding.ivTreasureBox.setVisibility(View.GONE); + } + + private void setActViewVisibility(int visibility) { + List list = new ArrayList<>(); + list.add(gameBinding.activityImg); + list.add(gameBinding.activityImgLeft); + list.add(gameBinding.activityImgLeftCp); + for (View index : list) { + index.setVisibility(visibility); + } + } + + private void hideKtvRelaView() { + gameBinding.setKtvModel(false); + gameBinding.llKtvTop.setVisibility(View.GONE); + gameBinding.contributeList.setVisibility(View.VISIBLE); + stvKtvSong.setVisibility(View.GONE); + setToMiniWorldVisible(true); + + if (getParentFragment() != null && getParentFragment() instanceof HomePartyFragment) { + ((HomePartyFragment) getParentFragment()).hideKtvBox(); + } + if (!isGameMode && !isKtvMode) { + changeModelShowView(); + } + + gameBinding.bottomView.showKtvBottom(false); + } + + @SuppressLint("CheckResult") + private void changeModelShowView() { + //noinspection ResultOfMethodCallIgnored + GoldBoxHelper.isHideBox().subscribe( + hide -> { + if (hide != null && !hide) { + if (AvRoomDataManager.get().isCpRoom()) { + gameBinding.ivTreasureBoxCp.setVisibility(View.VISIBLE); + gameBinding.ivTreasureBox.setVisibility(View.GONE); + } else { + gameBinding.ivTreasureBoxCp.setVisibility(View.GONE); + gameBinding.ivTreasureBox.setVisibility(View.VISIBLE); + } + } else { + gameBinding.ivTreasureBoxCp.setVisibility(View.GONE); + gameBinding.ivTreasureBox.setVisibility(View.GONE); + } + }, + throwable -> { + gameBinding.ivTreasureBoxCp.setVisibility(View.GONE); + gameBinding.ivTreasureBox.setVisibility(View.GONE); + }); + + if (getParentFragment() != null && getParentFragment() instanceof HomePartyFragment) { + ((HomePartyFragment) getParentFragment()).hideKtvBox(); + } + + setActViewVisibility(View.VISIBLE); + if (AvRoomDataManager.get().isOnMic(myUid)) { + if (musicPlayerView == null) { + musicPlayerView = (MusicPlayerView) mVsMusicPlayer.inflate(); + } + musicPlayerView.setVisibility(View.VISIBLE); + } + + setDragonView(); + } + + private void openGameModelServer(boolean status) { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + return; + } + GameModel.get().changeGameModel(AvRoomDataManager.get().mCurrentRoomInfo.getUid(), status) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(String s) { + if (status) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_game_open_click, "游戏面板启动"); + GameModel.get().sendOpenGame(); + openGameModel(); + } else { + GameModel.get().sendCloseGame(); + closeGameModel(); + } + } + }); + } + + private void openGameModel() { + if (isGameMode || AvRoomDataManager.get().mCurrentRoomInfo == null || !AvRoomDataManager.get().isCpRoom()) + return; + AvRoomDataManager.get().gameModel = true; + isGameMode = true; + gameBinding.microView.resetPoint(); + gameBinding.gameView.setVisibility(View.VISIBLE); + gameBinding.gameView.updateView(AvRoomDataManager.get().getGameStatus()); + gameBinding.bottomView.setGameClose(); + gameBinding.gameView.setCloseClick(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_close_click, "游戏等待面板-房主关闭按钮"); + openOrCloseGame(); + }); + changeModeHideView(); + + if (getActivity() != null) { + ViewModelProviders.of(getActivity()).get(RoomViewModel.class) + .getIsGameModel().setValue(true); + } + } + + private void closeGameModel() { + if (!isGameMode) return; + isGameMode = false; + AvRoomDataManager.get().gameModel = false; + gameBinding.microView.resetPoint(); + gameBinding.gameView.setVisibility(View.GONE); + gameBinding.bottomView.setGameOpen(); + changeModelShowView(); + if (getActivity() != null) { + ViewModelProviders.of(getActivity()).get(RoomViewModel.class) + .getIsGameModel().setValue(false); + } + } + + /** + * 设置龙珠的状态 + */ + private void setDragonView() { + boolean isOnMic = AvRoomDataManager.get().isOnMic(myUid); + if (AvRoomDataManager.get().hasDragonGame() && isOnMic + && !MarketVerifyModel.get().isMarketChecking() + && !isKtvMode + && !AvRoomDataManager.get().isOpenPKMode() + && !isKtvMode && !AvRoomDataManager.get().isCpRoom()) { + gameBinding.layoutDragon.setVisibility(View.VISIBLE); + if (AvRoomDataManager.get().haveStartDragon) { + gameBinding.playDragon.setVisibility(View.VISIBLE); + gameBinding.cancelDragon.setVisibility(View.VISIBLE); + } else { + gameBinding.playDragon.setVisibility(View.INVISIBLE); + gameBinding.cancelDragon.setVisibility(View.INVISIBLE); + } + return; + } + gameBinding.layoutDragon.setVisibility(View.GONE); + } + + private void closeKtvModelByRequest() { + getDialogManager().showProgressDialog(mContext); + KtvModel.get().closeKtvMode(AvRoomDataManager.get().mCurrentRoomInfo.getUid()) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + getDialogManager().dismissDialog(); + } + + @Override + public void onSuccess(Boolean aBoolean) { + getDialogManager().dismissDialog(); + closeKtvModel(); + KtvMusicManager.INSTANCE.deleteRoomAllChooseMusic() + .subscribe(); + } + }); + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 200 && resultCode == 100) { + if (data != null && data.getExtras() != null) { + String account = data.getExtras().getString("account"); + String nick = data.getExtras().getString("nick"); + if (TextUtils.isEmpty(account)) return; + if (AvRoomDataManager.get().isLeaveMode() && + Objects.equals(account, String.valueOf(AvRoomDataManager.get().getRoomUid()))) { + showToast(getString(R.string.tips_close_leave_mode_first)); + return; + } + int micPosition = data.getExtras().getInt(Constants.KEY_POSITION, Integer.MIN_VALUE); + if (micPosition == Integer.MIN_VALUE) return; + + //抱人上麦 + getMvpPresenter().inviteMicroPhone(new BaseInfo(account, nick), micPosition); + } + } else if (requestCode == SelectFriendActivity.CODE_REQUEST_TO_SHARE_ROOM && + resultCode == Activity.RESULT_OK) { + String targetUid = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_UID); + String nick = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_NAME); + int sessionType = data.getIntExtra(SelectFriendActivity.EXTRA_SESSION_TYPE, SessionType.P2P); + IMNetEaseManager.get().sendSharingRoomMessage(sessionType, targetUid); + } else if (requestCode == MINI_WORLD_REQUEST_CODE && resultCode == Activity.RESULT_OK) { + if (mJoinMiniWorldOperationPosition == -1) { + return; + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_JOIN_MINI_WORLD_FROM_ROOM, "语音房-加入小世界"); + messageView.changeJoinMiniWorldStatus(mJoinMiniWorldOperationPosition, true); + } + } + + void onChatRoomMemberBlackAdd(String account) { + //拉黑 + if (AvRoomDataManager.get().isOnMic(Long.valueOf(account))) { + int micPosition = AvRoomDataManager.get().getMicPosition(Long.valueOf(account)); + getMvpPresenter().downMicroPhone(micPosition, true); + } + + ListIterator memberListIterator = AvRoomDataManager.get().mRoomManagerList.listIterator(); + for (; memberListIterator.hasNext(); ) { + if (Objects.equals(memberListIterator.next().getAccount(), account)) { + memberListIterator.remove(); + } + } + + + if (AvRoomDataManager.get().isRoomOwner(account)) { + //当前是房主 + AvRoomDataManager.get().mRoomCreateMember = null; + } + } + + @Override + public void onDragonBarChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo) { + getDialogManager().showOkCancelDialog("你正在交友匹配中,此操作代表你放弃本局匹配展示,确定进行此操作?", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + ((AVRoomActivity) getActivity()).giveUpDragonBar().subscribe(s -> { + getMvpPresenter().cancelDragon(); + }); + getMvpPresenter().upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo); + } + }); + } + + /** + * 礼物值模式下换麦 + */ + @Override + public void onGiftValueChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo) { + if (!GiftValueDialogUiHelper.get().isNeedChangeMicDialog()) { + getMvpPresenter().upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo); + return; + } + GiftValueDialogUiHelper.get().showGiftValueDialog(mContext, getDialogManager(), + GiftValueDialogUiHelper.TYPE_CHANGE_MIC, + () -> getMvpPresenter().upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo)); + } + + @Override + public void onKtvChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo) { + getDialogManager().showOkCancelWithTitleDialog("KTV模式下换麦会移除您已点的所有歌曲,确定进行此操作?", "换麦", + () -> + KtvMusicManager.INSTANCE.deleteUserAllChooseMusic() + .subscribe(s -> + getMvpPresenter().upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo))); + } + + @Override + public void showToast(String msg) { + toast(msg); + } + + public void onMentoringCountingFinish() { + // UI 更新 + if (countDownTimerLayoutBackground != null) { + countDownTimerLayoutBackground.setImageResource(R.drawable.mentoring_go_to_send_gift_to_master); + } + if (mentoringCountDownTimerIcon != null) { + mentoringCountDownTimerIcon.setImageResource(R.mipmap.ic_mentoring_gift); + } + if (mentoringCountDownTimer != null) { + mentoringCountDownTimer.setTextSize(13); + mentoringCountDownTimer.setText(R.string.text_go_to_send_gift_to_master); + mentoringCountDownTimer.setOnClickListener(view -> { + // 视作任务完成,缓存数据清除 + AvRoomDataManager.get().setMasterUid(0); + AvRoomDataManager.get().setFromMentoring(false); + if (getActivity() != null) { + NimP2PMessageActivity.start(getActivity(), String.valueOf(AvRoomDataManager.get().mCurrentRoomInfo.getUid())); + getActivity().finish(); + } + }); + } + } + + @Override + public void onSendMsgSuccess() { + inputEdit.setText(""); + } + + /** + * 显示资料卡片 + */ + private void showUserCardDialog(String account) { + List list = ButtonItemFactory.createCommonButtonItems( + mContext, + JavaUtil.str2long(account), + true, + true, + true, + HomePartyRoomFragment.this + ); + GiftDialog.GIFT_DIALOG_FROM = "房间"; + new UserInfoDialog(mContext, JavaUtil.str2long(account), list, true).show(); + } + + /** + * 静态移除这个人出队列 + * + * @param account 需要移除的人 + */ + private void removeOtherFromMicQueue(String account) { + if (TextUtils.isEmpty(account)) { + return; + } + if (AvRoomDataManager.get().isQueuingMicro() && isMicQueueDialogShowing()) { + micQueueDialog.removeQueueMember(account); + } + + if (AvRoomDataManager.get().isOpenPKMode() && isPKMicQueueDialogShowing()) { + pkMicQueueDialog.removeQueueMember(account); + } + } + + /** + * 取消我的报名,如果我已经报名的话 + */ + private void cancelMyQueue() { + if (AvRoomDataManager.get().isQueuingMicro() && AvRoomDataManager.get().myIsInQueue) { + MicQueueModel.get().cancelApplyForQueuing(AvRoomDataManager.get().getRoomUid(), + AuthModel.get().getCurrentUid()) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(info -> { + if (isMicQueueDialogShowing()) { + micQueueDialog.updateQueueInfo(info); + } else { + AvRoomDataManager.get().myIsInQueue = false; + } + }); + } + + if (AvRoomDataManager.get().isOpenPKMode() && AvRoomDataManager.get().myIsInQueue) { + PkModel.get().leavePKMicQueue() + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(info -> { + if (isMicQueueDialogShowing()) { + pkMicQueueDialog.updateQueueInfo(info); + } else { + AvRoomDataManager.get().myIsInQueue = false; + } + }); + } + } + + private boolean isMicQueueDialogShowing() { + return micQueueDialog != null && micQueueDialog.isShowing(); + } + + private boolean isPKMicQueueDialogShowing() { + return pkMicQueueDialog != null && pkMicQueueDialog.isShowing(); + } + + @SuppressLint("CheckResult") + private void getGameUrl(ChatRoomMessage chatRoomMessage, ImGameInfo imGameInfo) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_accept, "点击接受"); + + ImGameMode.get().getGameUrl( + JavaUtil.str2long(chatRoomMessage.getFromAccount()), + imGameInfo.getNick(), + AuthModel.get().getCurrentUid(), + UserModel.get().getCacheLoginUserInfo().getNick(), + imGameInfo.getGameInfo().getGameId(), + imGameInfo.getGameInfo().getGameChannel(), + chatRoomMessage.getUuid() + ).compose(bindToLifecycle()).doOnError(new ErrorConsumer() { + @Override + public void accept(Throwable throwable) throws Exception { + dealInvalidInvite(throwable, imGameInfo, chatRoomMessage); + } + }).subscribe(gameUrlInfo -> ImGameMode.get().sendRoomGameReponseMsg(gameUrlInfo.getGameUrl(), + chatRoomMessage, new CallBack() { + @Override + public void onSuccess(ChatRoomMessage data) { + ImGameMode.get().exitCancelGame(true); + ImGameAttachment attachment = (ImGameAttachment) chatRoomMessage.getAttachment(); + attachment.getImGameInfo().setAcceptUid(AuthModel.get().getCurrentUid()); + messageView.changeGameStatus(chatRoomMessage.getUuid(), ImGameInfo.ACCEPTED); + + PlayGameActivity.start(mContext, gameUrlInfo.getReceiveGameUrl(), chatRoomMessage.getUuid()); + } + + @Override + public void onFail(int code, String error) { + } + })); + } + + private void dealInvalidInvite(Throwable throwable, ImGameInfo imGameInfo, ChatRoomMessage chatRoomMessage) { + if (throwable instanceof ServerException) { + if (((ServerException) throwable).code == 20004) { + new DialogManager(mContext).showOkCancelDialog("游戏已开始,是否进入观战", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + ImGameMode.get() + .getWatchGameUrl(imGameInfo.getGameInfo().getGameId(), + imGameInfo.getGameInfo().getGameChannel(), + chatRoomMessage.getUuid()) + .subscribe(gameUrlInfo -> + PlayGameActivity.start(mContext, gameUrlInfo.getUrl(), 0)); + } + }); + } else if (((ServerException) throwable).code == 20002 || ((ServerException) throwable).code == 20003) { + SingleToastUtil.showToast(throwable.getMessage()); + ImGameAttachment attachment = (ImGameAttachment) chatRoomMessage.getAttachment(); + attachment.getImGameInfo().setAcceptUid(AuthModel.get().getCurrentUid()); + messageView.changeGameStatus(chatRoomMessage.getUuid(), ImGameInfo.ACCEPTED); + } else { + SingleToastUtil.showToast(throwable.getMessage()); + } + } + } + + public void dismissGiftDialog() { + if (giftDialog != null && giftDialog.isShowing()) { + giftDialog.dismiss(); + } + } + + @SuppressLint("CheckResult") + @Override + public void toUpMicroPhone(int micPosition, String currentUid, boolean b) { + checkPermission(android.Manifest.permission.RECORD_AUDIO) + .subscribe(result -> { + if (result) { + getMvpPresenter().upMicroPhone(micPosition, currentUid, b); + } else { + toast("请给予麦克风权限后再试!"); + } + }, throwable -> toast("发生一些异常,请稍后重试!")); + } + + /** + * 是否有麦克风权限 + * + * @return + */ + private boolean isHavingMicPermissions() { + return ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED; + } + + private void setToMiniWorldVisible(boolean visible) { + RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + gameBinding.ivToMiniWorld.setVisibility(mCurrentRoomInfo != null && mCurrentRoomInfo.getWorldId() > 0 && visible ? View.VISIBLE : View.GONE); + } + + @Override + public void noFollow() { + messageView.postDelayed(new Runnable() { + @Override + public void run() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (roomInfo == null || userInfo == null) { + return; + } +// MessageView.SpannableBuilder spannableBuilder = new MessageView.SpannableBuilder(); +// SpannableString spannableString = new SpannableString(getString(R.string.tip_room_follow_owner,userInfo.getNick())); +// spannableString.setSpan(new ForegroundColorSpan(),3,3 + nick.length(),); + RoomFollowOwnerAttachment roomFollowOwnerAttachment = new RoomFollowOwnerAttachment(); + roomFollowOwnerAttachment.setOwnerUid(roomOwnner.getUid()); + roomFollowOwnerAttachment.setUserInfo(userInfo); + messageView.addMessages(ChatRoomMessageBuilder.createChatRoomCustomMessage(String.valueOf(roomInfo.getRoomId()), roomFollowOwnerAttachment)); + + } + }, SHOW_FOLLOW_TIME); + } + + @Override + public void notInWorld(@NotNull MiniWorldInWorldInfo miniWorldInWorldInfo) { + messageView.postDelayed(new Runnable() { + @Override + public void run() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (roomInfo == null || userInfo == null) { + return; + } +// MessageView.SpannableBuilder spannableBuilder = new MessageView.SpannableBuilder(); +// SpannableString spannableString = new SpannableString(getString(R.string.tip_room_follow_owner,userInfo.getNick())); +// spannableString.setSpan(new ForegroundColorSpan(),3,3 + nick.length(),); + JoinMiniWorldAttachment joinMiniWorldAttachment = new JoinMiniWorldAttachment(); + joinMiniWorldAttachment.setMiniWorldInfo(miniWorldInWorldInfo); + mJoinMiniWorldOperationPosition = messageView.addMessages(ChatRoomMessageBuilder.createChatRoomCustomMessage(String.valueOf(roomInfo.getRoomId()), joinMiniWorldAttachment)); + + } + }, SHOW_JOIN_MINI_WORLD_TIME); + } + + @Override + public void onFollowSuccess(int position) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_FOLLOW_OWNER_FROM_ROOM, "语音房-关注房主"); + messageView.changeFollowStatus(position, true); + } + + @Override + public void onFollowFail(String msg) { + toast("关注失败,请稍后重试"); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onActivityTimerEvent(ActivityTimerEvent event) { + setActTimerVisibility(View.GONE); + TimerBean timerBean = event.getData(); + if (timerBean == null) { + return; + } + if (!ListUtils.isListEmpty(specialActivities)) { + if (AvRoomDataManager.get().isCpRoom()) { + gameBinding.activityTimerCp.start(timerBean); + } else { + gameBinding.activityTimer.start(timerBean); + } + } + } + + private void otherInitView() { + setActTimerVisibility(View.GONE); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyUserListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyUserListFragment.java new file mode 100644 index 000000000..bc4554685 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyUserListFragment.java @@ -0,0 +1,186 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.content.Intent; +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.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.xchat_android_core.Constants; + +/** + * 轰趴房用户在线列表+贡献榜 + * + * @author chenran + * @date 2017/9/1 + */ +public class HomePartyUserListFragment extends BaseFragment implements View.OnClickListener { + + public final static int SHOW_PAGE_ONLINE_LIST = 1; + public final static int SHOW_PAGE_CONTRIBUTE_LIST = 2; + public final static int SHOW_PAGE_CHARM_LIST = 3; + + private TextView onlineLayout; + private TextView contributeLayout; + private TextView tvCharmList; + + OnlineUserFragment onlineFragment; + RoomContributeListFragment contributeFragment; + RoomCharmListFragment charmListFragment; + + public int mSelectPage = SHOW_PAGE_ONLINE_LIST; + private long mRoomUid; + + public static HomePartyUserListFragment newInstance(long roomUid) { + HomePartyUserListFragment fragment = new HomePartyUserListFragment(); + Bundle bundle = new Bundle(); + bundle.putLong(Constants.ROOM_UID, roomUid); + fragment.setArguments(bundle); + return fragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + mRoomUid = bundle.getLong(Constants.ROOM_UID, 0); + } + } + + @Override + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + if (intent != null) + mRoomUid = intent.getLongExtra(Constants.ROOM_UID, 0); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mSelectPage = outState.getInt(Constants.KEY_ROOM_IS_SHOW_ONLINE, SHOW_PAGE_ONLINE_LIST); + + } + + @Override + protected void restoreState(@Nullable Bundle savedInstanceState) { + super.restoreState(savedInstanceState); + if (savedInstanceState != null) { + savedInstanceState.putInt(Constants.KEY_ROOM_IS_SHOW_ONLINE, mSelectPage); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onFindViews() { + onlineLayout = mView.findViewById(R.id.tv_online); + contributeLayout = mView.findViewById(R.id.tv_contribute); + tvCharmList = (TextView) mView.findViewById(R.id.tv_charm_list); + + } + + @Override + public void onSetListener() { + onlineLayout.setOnClickListener(this); + contributeLayout.setOnClickListener(this); + tvCharmList.setOnClickListener(this); + } + + @Override + public void initiate() { + showPage(mSelectPage); + } + + public void showPage(int selectPage) { + this.mSelectPage = selectPage; + showBackground(); + FragmentManager manager = getChildFragmentManager(); + FragmentTransaction transaction = manager.beginTransaction(); + onlineFragment = (OnlineUserFragment) manager.findFragmentByTag(OnlineUserFragment.class.getSimpleName()); + contributeFragment = (RoomContributeListFragment) manager.findFragmentByTag(RoomContributeListFragment.class.getSimpleName()); + charmListFragment = (RoomCharmListFragment) manager.findFragmentByTag(RoomCharmListFragment.class.getSimpleName()); + + for (int i = 0; i < manager.getFragments().size(); i++) { + transaction.hide(manager.getFragments().get(i)); + } + if (this.mSelectPage == SHOW_PAGE_ONLINE_LIST){ + if (onlineFragment == null) { + onlineFragment = new OnlineUserFragment(); + transaction.add(R.id.fragment_user_list_container, onlineFragment, OnlineUserFragment.class.getSimpleName()); + } + transaction.show(onlineFragment); + onlineFragment.setShowToUser(true); + }else if (this.mSelectPage == SHOW_PAGE_CONTRIBUTE_LIST){ + if (contributeFragment == null) { + contributeFragment = new RoomContributeListFragment(); + transaction.add(R.id.fragment_user_list_container, contributeFragment, RoomContributeListFragment.class.getSimpleName()); + } + transaction.show(contributeFragment); + }else if (this.mSelectPage == SHOW_PAGE_CHARM_LIST){ + if (charmListFragment == null){ + charmListFragment = RoomCharmListFragment.newInstance(); + transaction.add(R.id.fragment_user_list_container, charmListFragment, RoomCharmListFragment.class.getSimpleName()); + } + transaction.show(charmListFragment); + } + + transaction.commitAllowingStateLoss(); + } + + private void showBackground() { + contributeLayout.setBackground(null); + onlineLayout.setBackground(null); + tvCharmList.setBackground(null); + if (this.mSelectPage == SHOW_PAGE_ONLINE_LIST){ + onlineLayout.setBackgroundResource(R.drawable.bg_game_room_tab_select); + }else if (this.mSelectPage == SHOW_PAGE_CONTRIBUTE_LIST){ + contributeLayout.setBackgroundResource(R.drawable.bg_game_room_tab_select); + }else if (this.mSelectPage == SHOW_PAGE_CHARM_LIST){ + tvCharmList.setBackgroundResource(R.drawable.bg_game_room_tab_select); + } + + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_game_list; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_online: + showPage(SHOW_PAGE_ONLINE_LIST); + break; + case R.id.tv_contribute: + showPage(SHOW_PAGE_CONTRIBUTE_LIST); + break; + case R.id.tv_charm_list: + showPage(SHOW_PAGE_CHARM_LIST); + break; + default: + } + } + + /** + * 设置在线人数OnlineUserFragment 是否可见 + * @param position + */ + public void setViewPagerPosition(int position) { + if (onlineFragment != null){ + if (position == 1 && mSelectPage == SHOW_PAGE_ONLINE_LIST) { + onlineFragment.setShowToUser(true); + }else { + onlineFragment.setShowToUser(false); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogChangePageListener.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogChangePageListener.java new file mode 100644 index 000000000..de6ef8d91 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogChangePageListener.java @@ -0,0 +1,5 @@ +package com.yizhuan.erban.avroom.fragment; + +public interface IRoomRankDialogChangePageListener { + void onChangePage(int pos); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogDismissListener.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogDismissListener.java new file mode 100644 index 000000000..423344361 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankDialogDismissListener.java @@ -0,0 +1,5 @@ +package com.yizhuan.erban.avroom.fragment; + +public interface IRoomRankDialogDismissListener { + void onDismiss(); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankHalfHourView.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankHalfHourView.java new file mode 100644 index 000000000..13dc77d50 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/IRoomRankHalfHourView.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.avroom.fragment; + +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourMeInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourRankInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +public interface IRoomRankHalfHourView extends IMvpBaseView { + void showMeInfo(RoomRankHalfHourMeInfo dataInfo/*, int progress, String onListTip*/); + + void showTop3Info(List dataInfoList); + + void showRankListInfo(List dataList); + + void loadDataFailure(); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/InputPwdDialogFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/InputPwdDialogFragment.java new file mode 100644 index 000000000..69c28282c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/InputPwdDialogFragment.java @@ -0,0 +1,123 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; + +/** + *

密码框输入

+ * + * @author Administrator + * @date 2017/12/1 + */ +public class InputPwdDialogFragment extends DialogFragment implements View.OnClickListener { + private View mRootView; + private TextView mTvTitle; + private EditText mInputText; + private TextView mFailText; + private TextView mConfirmText; + private TextView mCancelText; + + private String mTitle; + private String mOk; + private String mCancel; + private String mResultCode; + + public static InputPwdDialogFragment newInstance(String title, String okLabel, String cancelLabel, String resultCode) { + InputPwdDialogFragment fragment = new InputPwdDialogFragment(); + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("okLabel", okLabel); + bundle.putString("cancelLabel", cancelLabel); + bundle.putString("resultCode", resultCode); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle arguments = getArguments(); + if (arguments != null) { + mTitle = arguments.getString("title"); + mOk = arguments.getString("okLabel"); + mCancel = arguments.getString("cancelLabel"); + mResultCode = arguments.getString("resultCode"); + } + + setCancelable(false); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mRootView = inflater.inflate(R.layout.layout_pic_login_dialog, container); + mTvTitle = (TextView) mRootView.findViewById(R.id.pic_login_title); + mInputText = (EditText) mRootView.findViewById(R.id.pic_login_input); + mFailText = (TextView) mRootView.findViewById(R.id.pic_login_fail_msg); + mConfirmText = (TextView) mRootView.findViewById(R.id.btn_confirm); + mCancelText = (TextView) mRootView.findViewById(R.id.btn_cancel); + return mRootView; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mInputText.requestFocus(); + + mTvTitle.setText(mTitle); + mCancelText.setText(mCancel); + mConfirmText.setText(mOk); + + mConfirmText.setOnClickListener(this); + mCancelText.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_confirm: + if (!TextUtils.isEmpty(mResultCode)) { + if (mResultCode.equals(DESUtils.DESAndBase64(mInputText.getText().toString()))) { + if (mOnDialogBtnClickListener != null) { + mOnDialogBtnClickListener.onBtnConfirm(); + } + } else { + mFailText.setVisibility(View.VISIBLE); + } + } else { + mFailText.setVisibility(View.VISIBLE); + } + break; + case R.id.btn_cancel: + if (mOnDialogBtnClickListener != null) { + mOnDialogBtnClickListener.onBtnCancel(); + } + break; + default: + } + } + + private OnDialogBtnClickListener mOnDialogBtnClickListener; + + public void setOnDialogBtnClickListener(OnDialogBtnClickListener onDialogBtnClickListener) { + mOnDialogBtnClickListener = onDialogBtnClickListener; + } + + public interface OnDialogBtnClickListener { + void onBtnConfirm(); + + void onBtnCancel(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/InviteFriendListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/InviteFriendListFragment.java new file mode 100644 index 000000000..a25f77b5d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/InviteFriendListFragment.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.coorchice.library.utils.LogUtils; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.InviteFriendListAdapter; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.public_chat_hall.adapter.PublicChatHallFriendListAdapter; +import com.yizhuan.erban.public_chat_hall.bean.PublicChatHallFriendInfo; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RelationShipEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 公聊大厅选择艾特人的好友页面 + */ +public class InviteFriendListFragment extends BaseFragment { + + private static final String TAG = "InviteFriendListFragment"; + + private InviteFriendListAdapter adapter = null; + private SwipeRefreshLayout mSwipeRefresh; + private RecyclerView mRecyclerView; + + public static InviteFriendListFragment newInstances() { + return new InviteFriendListFragment(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + mSwipeRefresh = mView.findViewById(R.id.swipe_refresh); + mRecyclerView = mView.findViewById(R.id.recycler_view); + } + + @Override + public void onSetListener() { + } + + @Override + public void initiate() { + mSwipeRefresh.setEnabled(false); + + if (adapter == null) { + adapter = new InviteFriendListAdapter(getActivity()); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + mRecyclerView.setAdapter(adapter); + + loadFriends(); + } else { + mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + mRecyclerView.setAdapter(adapter); + } + + Disposable d = IMNetEaseManager.get().getRelationShipEventObservable().subscribe(this::onGetRelationShipEvent); + mCompositeDisposable.add(d); + } + + private void onGetRelationShipEvent(RelationShipEvent event) { + if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) { + onFriendListUpdate(event.accounts); + } + } + + private void loadFriends() { + onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_fans_list; + } + + private void onFriendListUpdate(List accounts) { + if (ListUtils.isListEmpty(accounts)) { + showNoData(getString(R.string.no_frenids_text)); + return; + } + ArrayList ids = new ArrayList<>(accounts.size()); + for (String account : accounts) { + ids.add(Long.valueOf(account)); + } + UserModel.get().loadUserInfoByUids(accounts).subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List userInfos) { + List publicChatHallFriendInfoList = new ArrayList<>(); + for (UserInfo userInfo : userInfos) { + PublicChatHallFriendInfo friendInfo = new PublicChatHallFriendInfo(); + friendInfo.setUserInfo(userInfo); + publicChatHallFriendInfoList.add(friendInfo); + } + setData(publicChatHallFriendInfoList); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + private void setData(List userInfos) { + if (userInfos != null && !userInfos.isEmpty()) { + hideStatus(); + adapter.setNewData(userInfos); + //adapter.notifyDataSetChanged(); + } else { + showNoData(getString(R.string.no_frenids_text)); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentUserInfoUpdate(UserInfo userInfo) { + mRecyclerView.postDelayed(() -> onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()) + , 250); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/OnlineUserFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/OnlineUserFragment.java new file mode 100644 index 000000000..64711e376 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/OnlineUserFragment.java @@ -0,0 +1,259 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.orhanobut.logger.Logger; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.ButtonItemFactory; +import com.yizhuan.erban.avroom.adapter.OnlineUserAdapter; +import com.yizhuan.erban.avroom.presenter.HomePartyUserListPresenter; +import com.yizhuan.erban.avroom.view.IHomePartyUserListView; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleDialog; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.Iterator; +import java.util.List; + +/** + *

在线用户列表

+ * + * @author Administrator + * @date 2017/12/4 + */ +@CreatePresenter(HomePartyUserListPresenter.class) +public class OnlineUserFragment extends BaseMvpFragment + implements BaseQuickAdapter.OnItemClickListener, IHomePartyUserListView, OnlineUserAdapter.OnRoomOnlineNumberChangeListener { + private RecyclerView mRecyclerView; + private SmartRefreshLayout mRefreshLayout; + + private OnlineUserAdapter mOnlineUserAdapter; + private int mPage = Constants.PAGE_START; + private boolean isShowToUser = false; + + @Override + public void onDestroy() { + if (mOnlineUserAdapter != null) + mOnlineUserAdapter.release(); + super.onDestroy(); + } + + @Override + public void onFindViews() { + mRecyclerView = mView.findViewById(R.id.recycler_view); + mRefreshLayout = mView.findViewById(R.id.refresh_layout); + } + + @Override + public void onSetListener() { + mRefreshLayout.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(mContext)) { + mRefreshLayout.finishLoadmore(); + return; + } + List data = mOnlineUserAdapter.getData(); + if (ListUtils.isListEmpty(data)) { + mRefreshLayout.finishLoadmore(); + return; + } + loadData(data.get(data.size() - 1).chatRoomMember.getEnterTime()); + } + + @Override + public void onRefresh(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(mContext)) { + mRefreshLayout.finishRefresh(); + return; + } + firstLoad(); + } + }); + } + + @Override + public void initiate() { + mRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4)); + mOnlineUserAdapter = new OnlineUserAdapter(mContext, true); + mOnlineUserAdapter.setSpanSizeLookup((gridLayoutManager, i) -> { + List data = mOnlineUserAdapter.getData(); + if (ListUtils.isListEmpty(data)) return OnlineChatMember.SPAN_SIZE_NORMAL; + return data.get(i).getSpanSize(); + }); + mRecyclerView.setAdapter(mOnlineUserAdapter); + mOnlineUserAdapter.setOnItemClickListener(this); + mOnlineUserAdapter.setListener(this); + firstLoad(); + } + + + @Override + public int getRootLayoutId() { + return R.layout.common_refresh_recycler_view; + } + + + public void firstLoad() { + mPage = Constants.PAGE_START; + loadData(0); + } + + private void loadData(long time) { + getMvpPresenter().requestChatMemberByPage(mPage, time, + mOnlineUserAdapter == null ? null : mOnlineUserAdapter.getData()); + } + + + @Override + public void onRequestChatMemberByPageSuccess(List chatRoomMemberList, int page) { + mPage = page; + if (!ListUtils.isListEmpty(chatRoomMemberList)) { + //超管不显示 + Iterator iterator = chatRoomMemberList.iterator(); + while (iterator.hasNext()) { + OnlineChatMember member = iterator.next(); + if (member != null && SuperAdminUtil.isSuperAdmin(member.chatRoomMember)) { + iterator.remove(); + } + } + mOnlineUserAdapter.setNewData(chatRoomMemberList); + if (mPage == Constants.PAGE_START) { + mRefreshLayout.finishRefresh(); + } else { + mRefreshLayout.finishLoadmore(0); + } + mPage++; + } else { + if (mPage == Constants.PAGE_START) { + mRefreshLayout.finishRefresh(); + } else { + mRefreshLayout.finishLoadmore(0); + } + } + } + + @Override + public void onRequestChatMemberByPageFail(String errorStr, int page) { + Logger.i("获取到数据失败,page=" + page); + mPage = page; + if (mPage == Constants.PAGE_START) { + mRefreshLayout.finishRefresh(); + } else { + mRefreshLayout.finishLoadmore(0); + } + } + + @Override + public void onMemberInRefresh() { +// if (!isResumed()) return; +// if (!isShowToUser()) return; +// firstLoad(); + } + + @Override + public void onItemClick(BaseQuickAdapter baseQuickAdapter, View view, int position) { + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom != null) { + List chatRoomMembers = mOnlineUserAdapter.getData(); + if (ListUtils.isListEmpty(chatRoomMembers)) return; + OnlineChatMember onlineChatMember = chatRoomMembers.get(position); + ChatRoomMember chatRoomMember = onlineChatMember.chatRoomMember; + if (chatRoomMember != null || onlineChatMember.uid != 0) { + //贵族隐身进入房间不弹出个人资料卡片 + if (onlineChatMember.nobleUsers != null && onlineChatMember.nobleUsers.isNobleEnterHide()) { + return; + } + Object isEnterHide = NobleUtil.getResource(NobleResourceType.KEY_ENTER_HIDE, onlineChatMember.chatRoomMember); + if ((isEnterHide instanceof Boolean && (Boolean) isEnterHide) + || (isEnterHide instanceof String) && ((String) isEnterHide).equals("1")) { + return; + } + + String account = (chatRoomMember != null ? + chatRoomMember.getAccount() : String.valueOf(onlineChatMember.uid)); + List list = ButtonItemFactory.createCommonButtonItems( + getActivity(), JavaUtil.str2long(account), false, true, true, null); + GiftDialog.GIFT_DIALOG_FROM = "房间"; + new UserInfoDialog( + mContext, + JavaUtil.str2long(account), + list, + true + ).show(); + } else { + if (UserModel.get().getCacheLoginUserInfo().getNobleUsers() != null) { + toast(R.string.already_noble); + return; + } + if (onlineChatMember.getItemType() == OnlineChatMember.TEXT) return; + new OpenNobleDialog(mContext, 0, 0, null).show(); + } + } + } + + @Override + public void onMemberIn(String account, List dataList) { +// if (!isResumed()) return; +// getMvpPresenter().onMemberInRefreshData(account, dataList, mPage); + } + + @Override + public void onMemberExit(String account, List dataList) { +// if (!isResumed()) return; +// if (!isShowToUser()) return; +// firstLoad(); + } + + @Override + public void onMemberDownUpMic(String account, boolean isUpMic, List dataList) { + if (!isResumed()) return; + getMvpPresenter().onMemberDownUpMic(account, isUpMic, dataList, mPage); + } + + @Override + public void onUpdateMemberManager(String account, boolean isRemoveManager, List dataList) { + if (!isResumed()) return; + getMvpPresenter().onUpdateMemberManager(account, dataList, isRemoveManager, mPage); + } + + @Override + public void addMemberBlack() { + if (!isResumed()) return; + if (!isShowToUser()) return; + firstLoad(); + } + + public boolean isShowToUser() { + return isShowToUser; + } + + public void setShowToUser(boolean showToUser) { + isShowToUser = showToUser; + if (showToUser && isResumed()) { + firstLoad(); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmListFragment.java new file mode 100644 index 000000000..6189af0e4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmListFragment.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.support.v4.app.Fragment; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.avroom.widget.RankNavigatorAdapter; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeDataInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.erban.databinding.FragmentRoomCharmListBinding; + + +import java.util.ArrayList; + +@ActLayoutRes(R.layout.fragment_room_charm_list) +public class RoomCharmListFragment extends BaseBindingFragment { + + public static RoomCharmListFragment newInstance() { + return new RoomCharmListFragment(); + } + + @Override + public void initiate() { + ArrayList fragments = new ArrayList<>(2); + fragments.add(RoomCharmRankingListFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_DAY_RANKING)); + fragments.add(RoomCharmRankingListFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_WEEK_RANKING)); +// fragments.add(RoomCharmRankingListFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_TOTAL_RANKING)); + mBinding.vpCharmRankings.setAdapter(new RoomContributeListAdapter(getChildFragmentManager(), fragments)); + CommonNavigator commonNavigator = new CommonNavigator(getActivity()); + commonNavigator.setAdjustMode(true); + + RankNavigatorAdapter indicator = new RankNavigatorAdapter(); + indicator.setOnItemSelectListener(new RankNavigatorAdapter.OnItemSelectListener() { + @Override + public void onItemSelect(int position) { + mBinding.vpCharmRankings.setCurrentItem(position); + } + }); + commonNavigator.setAdapter(indicator); + mBinding.viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mBinding.viewIndicator, mBinding.vpCharmRankings); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmRankingListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmRankingListFragment.java new file mode 100644 index 000000000..446b6b180 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomCharmRankingListFragment.java @@ -0,0 +1,144 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.ButtonItemFactory; +import com.yizhuan.erban.avroom.adapter.RoomConsumerListAdapterTemp; +import com.yizhuan.erban.avroom.presenter.RoomCharmRankingPresenter; +import com.yizhuan.erban.avroom.view.IRoomCharmRankingListView; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +@CreatePresenter(RoomCharmRankingPresenter.class) +public class RoomCharmRankingListFragment extends BaseMvpFragment + implements IRoomCharmRankingListView, BaseQuickAdapter.OnItemClickListener, RoomConsumerListAdapterTemp.RoomConsumerTopThreeListener { + public static final String KEY_TYPE = "type"; + + private RoomConsumerListAdapterTemp mConsumeListAdapter; + private RecyclerView mRecyclerView; + private SmartRefreshLayout mRefreshLayout; + + private View mEmptyView; + + public static Fragment newInstance(String type) { + Fragment fragment = new RoomCharmRankingListFragment(); + Bundle bundle = new Bundle(); + bundle.putString(KEY_TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void onFindViews() { + mEmptyView = LayoutInflater.from(mContext).inflate(R.layout.list_item_room_consume_list_empty, null, false); + mRecyclerView = mView.findViewById(R.id.recycler_view); + mRefreshLayout = mView.findViewById(R.id.refresh_layout); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + mConsumeListAdapter = new RoomConsumerListAdapterTemp(mContext); + mConsumeListAdapter.setmRoomConsumerTopThreeListener(this); + mRecyclerView.setAdapter(mConsumeListAdapter); + mConsumeListAdapter.setOnItemClickListener(this); + mRefreshLayout.setEnableRefresh(true); + mRefreshLayout.setOnRefreshListener(new OnRefreshListener() { + @Override + public void onRefresh(RefreshLayout refreshlayout) { + loadData(); + } + }); + + mRefreshLayout.autoRefresh(100); + } + + + @Override + public void onItemClick(BaseQuickAdapter baseQuickAdapter, View view, int i) { + List list = mConsumeListAdapter.getData(); + if (ListUtils.isListEmpty(list)) { + return; + } + RoomRankMultiItem item = list.get(i); + if (item != null && item.getItemType() != RoomContributeUserInfo.TYPE_GRID) { + RoomContributeUserInfo info = (RoomContributeUserInfo) item.getData(); + if (info == null) return; + if (info.isHide()) return; + if (info.isEmptyBean()) return; + showUserInfoDialog(info.getUid()); + } + } + + private void showUserInfoDialog(long uid) { + List buttonList = ButtonItemFactory.createCommonButtonItems( + mContext, uid, false, true, true, null); + GiftDialog.GIFT_DIALOG_FROM = "房间"; + new UserInfoDialog( + mContext, + uid, + buttonList, + true + ).show(); + } + + private void loadData(){ + String type = getArguments().getString(KEY_TYPE); + RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (mCurrentRoomInfo == null){ + mRefreshLayout.finishRefresh(); + return; + } + + getMvpPresenter().getRoomCharmList(mCurrentRoomInfo.getUid(), type); + } + + @Override + public void topThreeListener(long uid) { + showUserInfoDialog(uid); + } + + @Override + public int getRootLayoutId() { + return R.layout.common_refresh_recycler_view; + } + + @Override + public void roomCharmListSuccess(List list) { + mRefreshLayout.finishRefresh(); + mConsumeListAdapter.setNewData(list); + } + + @Override + public void roomCharListFail(String message) { + mRefreshLayout.finishRefresh(); + if (!TextUtils.isEmpty(message)) + toast(message); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeFragment.java new file mode 100644 index 000000000..831a11210 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeFragment.java @@ -0,0 +1,213 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.ButtonItemFactory; +import com.yizhuan.erban.avroom.adapter.RoomConsumerListAdapterTemp; +import com.yizhuan.erban.avroom.presenter.RoomContributeListPresenter; +import com.yizhuan.erban.avroom.view.IRoomContributeListView; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeDataInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + *

房间贡献榜用户列表

+ * + * @author Administrator + * @date 2017/12/4 + */ +@CreatePresenter(RoomContributeListPresenter.class) +public class RoomContributeFragment extends BaseMvpFragment + implements IRoomContributeListView, BaseQuickAdapter.OnItemClickListener, RoomConsumerListAdapterTemp.RoomConsumerTopThreeListener { + + public static final String KEY_TYPE = "type"; + + private String type; + private List dataInfoList; + private RecyclerView mRecyclerView; + private SmartRefreshLayout mRefreshLayout; + private RoomConsumerListAdapterTemp mConsumeListAdapter; + private View mEmptyView; + private int page = 1; + + public static RoomContributeFragment newInstance(String type) { + RoomContributeFragment roomContributeFragment = new RoomContributeFragment(); + Bundle bundle = new Bundle(); + bundle.putString(KEY_TYPE, type); + roomContributeFragment.setArguments(bundle); + return roomContributeFragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + type = bundle.getString(KEY_TYPE); + } + + @Override + public void onFindViews() { + mRecyclerView = mView.findViewById(R.id.recycler_view); + mRefreshLayout = mView.findViewById(R.id.refresh_layout); + } + + @Override + public void onSetListener() { + mRefreshLayout.setEnableLoadmore(false); + mRefreshLayout.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(mContext)) { + mRefreshLayout.finishLoadmore(); + return; + } + List data = mConsumeListAdapter.getData(); + if (ListUtils.isListEmpty(data)) { + mRefreshLayout.finishLoadmore(); + return; + } + loadData(); + } + + @Override + public void onRefresh(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(mContext)) { + mRefreshLayout.finishRefresh(); + return; + } + firstLoad(); + } + }); + } + + @Override + public void initiate() { + mEmptyView = LayoutInflater.from(mContext).inflate(R.layout.list_item_room_consume_list_empty, null, false); + mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + mConsumeListAdapter = new RoomConsumerListAdapterTemp(mContext); + mConsumeListAdapter.setmRoomConsumerTopThreeListener(this); + mRecyclerView.setAdapter(mConsumeListAdapter); + mConsumeListAdapter.setOnItemClickListener(this); + + mRefreshLayout.autoRefresh(100); + } + + @Override + public int getRootLayoutId() { + return R.layout.common_refresh_recycler_view; + } + + public void firstLoad() { + page = Constants.PAGE_START; + loadData(); + } + + public void loadData() { + getMvpPresenter().getSingleRoomRanking(page, type); + } + + @Override + public void onItemClick(BaseQuickAdapter baseQuickAdapter, View view, int i) { + List list = mConsumeListAdapter.getData(); + if (ListUtils.isListEmpty(list)) { + return; + } + RoomRankMultiItem item = list.get(i); + if (item != null && item.getItemType() != RoomContributeUserInfo.TYPE_GRID) { + RoomContributeUserInfo info = (RoomContributeUserInfo) item.getData(); + if (info == null) return; + if (info.isHide()) return; + if (info.isEmptyBean()) return; + showUserInfoDialog(info.getUid()); + } + } + + private void showUserInfoDialog(long uid) { + List buttonList = ButtonItemFactory.createCommonButtonItems( + mContext, uid, false, true, true, null); + GiftDialog.GIFT_DIALOG_FROM = "房间"; + new UserInfoDialog( + mContext, + uid, + buttonList, + true + ).show(); + } + + @Override + public void getSingleRankingSuccess(RoomContributeDataInfo roomContributeDataInfo) { + List list = roomContributeDataInfo.getRankings(); + if (!ListUtils.isListEmpty(list)) { + if (page == Constants.PAGE_START) { + dataInfoList = roomContributeDataInfo.getRankings(); + setContributeDataView(roomContributeDataInfo); + mRefreshLayout.finishRefresh(); + } else { + dataInfoList.addAll(list); + addRoomContributeData(list); + mRefreshLayout.finishLoadmore(0); + } + page++; + } else { + if (page == Constants.PAGE_START) { + dataInfoList = null; + mRefreshLayout.finishRefresh(); + setContributeDataView(roomContributeDataInfo); + } else { + mRefreshLayout.finishLoadmore(0); + } + } + } + + private void setContributeDataView(RoomContributeDataInfo roomContributeDataInfo) { + List list = roomContributeDataInfo.getRankings(); + if (list == null) { + list = new ArrayList<>(); + } + + mConsumeListAdapter.setNewData(getMvpPresenter().handleList(list)); + } + + private void addRoomContributeData(List list) { + + for (RoomContributeUserInfo info : list) { + RoomRankMultiItem item = new RoomRankMultiItem(); + item.setData(info); + item.setItemType(RoomRankMultiItem.TYPE_LINEAR); + mConsumeListAdapter.addData(item); + } + + } + + @Override + public void getSingleRakingFail(int errorCode, String errorMsg) { + if (page == Constants.PAGE_START) { + mRefreshLayout.finishRefresh(); + } else { + mRefreshLayout.finishLoadmore(0); + } + } + + @Override + public void topThreeListener(long uid) { + showUserInfoDialog(uid); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeListFragment.java new file mode 100644 index 000000000..097df08f8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomContributeListFragment.java @@ -0,0 +1,65 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.avroom.widget.RankNavigatorAdapter; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeDataInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.ArrayList; + +/** + * Created by MadisonRong on 25/04/2018. + */ +public class RoomContributeListFragment extends BaseMvpFragment implements IMvpBaseView { + + private ViewPager viewPager; + private MagicIndicator viewIndicator; + + @Override + public void onFindViews() { + viewIndicator = mView.findViewById(R.id.view_indicator); + viewPager = mView.findViewById(R.id.vp_contribute_rankings); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + ArrayList fragments = new ArrayList<>(2); + fragments.add(RoomContributeFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_DAY_RANKING)); + fragments.add(RoomContributeFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_WEEK_RANKING)); +// fragments.add(RoomContributeFragment.newInstance(RoomContributeDataInfo.TYPE_ROOM_TOTAL_RANKING)); + viewPager.setAdapter(new RoomContributeListAdapter(getChildFragmentManager(), fragments)); + + CommonNavigator commonNavigator = new CommonNavigator(getActivity()); + commonNavigator.setAdjustMode(true); + + RankNavigatorAdapter indicator = new RankNavigatorAdapter(); + indicator.setOnItemSelectListener(new RankNavigatorAdapter.OnItemSelectListener() { + @Override + public void onItemSelect(int position) { + viewPager.setCurrentItem(position); + } + }); + commonNavigator.setAdapter(indicator); + viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(viewIndicator, viewPager); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_room_contribute; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogFragment.java new file mode 100644 index 000000000..5f55b2185 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogFragment.java @@ -0,0 +1,115 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatDialogFragment; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomRankFragmentPageAdapter; + +import java.util.ArrayList; +import java.util.List; + +public class RoomRankDialogFragment extends AppCompatDialogFragment implements IRoomRankDialogDismissListener, IRoomRankDialogChangePageListener { + + private ViewPager mViewPager; + + private long roomOwnerUid;// 房主Uid + + public static RoomRankDialogFragment newInstance(long roomOwnerUid) { + Bundle args = new Bundle(); + args.putLong("room_owner_uid", roomOwnerUid); + RoomRankDialogFragment fragment = new RoomRankDialogFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (getArguments() != null) { + roomOwnerUid = getArguments().getLong("room_owner_uid"); + } + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if (getActivity() != null) { + Dialog dialog = new Dialog(getActivity(), R.style.room_rank_dialog); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.dialog_fragment_room_rank); + dialog.setCanceledOnTouchOutside(true); + + // 设置弹出框布局参数,宽度铺满全屏,底部。 + Window window = dialog.getWindow(); + if (window != null) { + WindowManager.LayoutParams wlp = window.getAttributes(); + wlp.gravity = Gravity.BOTTOM; + wlp.width = WindowManager.LayoutParams.MATCH_PARENT; + wlp.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setDimAmount(0.3f); + window.setAttributes(wlp); + window.setBackgroundDrawableResource(R.drawable.bg_room_rank); + return dialog; + } else { + return super.onCreateDialog(savedInstanceState); + } + } else { + return super.onCreateDialog(savedInstanceState); + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_fragment_room_rank, container, false); + mViewPager = view.findViewById(R.id.vp_room_rank); + List fragmentList = new ArrayList<>(); + if (getChildFragmentManager().getFragments() != null && getChildFragmentManager().getFragments().size() != 0) { + fragmentList = getChildFragmentManager().getFragments(); + } else { + RoomRankHalfHourFragment halfHourFragment = RoomRankHalfHourFragment.newInstance(roomOwnerUid); + halfHourFragment.setDismissListener(this); + halfHourFragment.setChangePageListener(this); + fragmentList.add(halfHourFragment); + + RoomRankListFragment roomInsideFragment = RoomRankListFragment.newInstance(); + roomInsideFragment.setDismissListener(this); + roomInsideFragment.setChangePageListener(this); + fragmentList.add(roomInsideFragment); + + } + mViewPager.setAdapter(new RoomRankFragmentPageAdapter(getChildFragmentManager(), fragmentList)); + mViewPager.setOffscreenPageLimit(fragmentList.size()); + mViewPager.setCurrentItem(0, false); + return view; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setCancelable(true); + } + + @Override + public void onDismiss() { + dismiss(); + } + + @Override + public void onChangePage(int pos) { + mViewPager.setCurrentItem(pos, false); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogUtils.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogUtils.java new file mode 100644 index 000000000..6f261dc5e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankDialogUtils.java @@ -0,0 +1,64 @@ +package com.yizhuan.erban.avroom.fragment; + +import com.yizhuan.erban.R; + +import java.math.BigDecimal; + +public class RoomRankDialogUtils { + public static String getRoomRankValueText(int value) { + if (value >= 10000) { + BigDecimal bigDecimal = new BigDecimal(value / 10000.0); + double doubleValue = bigDecimal.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue(); + return String.valueOf(doubleValue) + "万"; + } else { + return String.valueOf(value); + } + } + + public static int getNumberImage(int number) { + switch (number) { + case 1: + return R.drawable.ic_rank_1; + case 2: + return R.drawable.ic_rank_2; + case 3: + return R.drawable.ic_rank_3; + case 4: + return R.drawable.ic_rank_4; + case 5: + return R.drawable.ic_rank_5; + case 6: + return R.drawable.ic_rank_6; + case 7: + return R.drawable.ic_rank_7; + case 8: + return R.drawable.ic_rank_8; + case 9: + return R.drawable.ic_rank_9; + case 10: + return R.drawable.ic_rank_10; + case 11: + return R.drawable.ic_rank_11; + case 12: + return R.drawable.ic_rank_12; + case 13: + return R.drawable.ic_rank_13; + case 14: + return R.drawable.ic_rank_14; + case 15: + return R.drawable.ic_rank_15; + case 16: + return R.drawable.ic_rank_16; + case 17: + return R.drawable.ic_rank_17; + case 18: + return R.drawable.ic_rank_18; + case 19: + return R.drawable.ic_rank_19; + case 20: + return R.drawable.ic_rank_20; + default: + return 0; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankHalfHourFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankHalfHourFragment.java new file mode 100644 index 000000000..eb01a4bf6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankHalfHourFragment.java @@ -0,0 +1,359 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.content.Context; +import android.os.Bundle; +import android.support.v4.widget.NestedScrollView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.adapter.RoomRankHalfHourListAdapter; +import com.yizhuan.erban.avroom.presenter.RoomRankHalfHourPresenter; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourMeInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourRankInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +@CreatePresenter(RoomRankHalfHourPresenter.class) +public class RoomRankHalfHourFragment extends BaseMvpFragment + implements IRoomRankHalfHourView, View.OnClickListener { + + @BindView(R.id.tv_room_rank_half_hour_tab) + TextView mHalfHourTab; + @BindView(R.id.tv_room_rank_in_room_tab) + TextView mInsideRoomTab; + + @BindView(R.id.layout_room_rank_mine_info) + LinearLayout mMineInfoLayout; + @BindView(R.id.tv_room_rank_mine_ranking) + TextView mMineRanking; + @BindView(R.id.iv_number) + ImageView ivNumber; + @BindView(R.id.iv_room_rank_mine_avatar) + CircleImageView mMineAvatar; + + @BindView(R.id.tv_room_rank_mine_title) + TextView mMineTitle; + @BindView(R.id.tv_room_id) + TextView tvRoomId; + + @BindView(R.id.ll_number_one) + LinearLayout llNumberOne; + + @BindView(R.id.ll_to_last) + LinearLayout llToLast; + @BindView(R.id.tv_to_last) + TextView tvToLast; + @BindView(R.id.tv_label_to) + TextView tvLabelTo; + + @BindView(R.id.layout_room_rank_top_2) + RelativeLayout mTop2Layout; + @BindView(R.id.iv_room_rank_top_2_avatar_default) + ImageView mTop2AvatarDF;// 无数据时才显示 + @BindView(R.id.iv_room_rank_top_2_avatar) + CircleImageView mTop2Avatar;// 有数据时才显示 + @BindView(R.id.tv_number_two_id) + TextView mTop2Id; + @BindView(R.id.tv_two_to_last) + TextView mTop2Value; + @BindView(R.id.tv_label_number_two) + TextView mTop2Name; + + @BindView(R.id.layout_room_rank_top_1) + RelativeLayout mTop1Layout; + @BindView(R.id.iv_room_rank_top_1_avatar_default) + ImageView mTop1AvatarDF;// 无数据时才显示 + @BindView(R.id.iv_room_rank_top_1_avatar) + CircleImageView mTop1Avatar;// 有数据时才显示 + @BindView(R.id.tv_rank_half_one) + TextView tvRankHalfOne; + @BindView(R.id.tv_label_number_one) + TextView mTop1Name; + @BindView(R.id.tv_number_one_id) + TextView mTop1Id; + + @BindView(R.id.layout_room_rank_top_3) + RelativeLayout mTop3Layout; + @BindView(R.id.iv_room_rank_top_3_avatar_default) + ImageView mTop3AvatarDF;// 无数据时才显示 + @BindView(R.id.iv_room_rank_top_3_avatar) + CircleImageView mTop3Avatar;// 有数据时才显示 + @BindView(R.id.tv_number_three_id) + TextView mTop3Id; + @BindView(R.id.tv_three_to_last) + TextView mTop3Value; + @BindView(R.id.tv_label_number_three) + TextView mTop3Name; + + @BindView(R.id.recycler_room_rank_list) + RecyclerView mRoomRankRecycler; + @BindView(R.id.refresh_layout) + SmartRefreshLayout mRefreshLayout; + @BindView(R.id.nsv_rank_half) + NestedScrollView nestedScrollView; + + private RoomRankHalfHourListAdapter mAdapter; + + private IRoomRankDialogDismissListener dismissListener; + private IRoomRankDialogChangePageListener changePageListener; + + private long roomOwnerUid;// 房主Uid + + public static RoomRankHalfHourFragment newInstance(long roomOwnerUid) { + + Bundle args = new Bundle(); + args.putLong("room_owner_uid", roomOwnerUid); + RoomRankHalfHourFragment fragment = new RoomRankHalfHourFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (getArguments() != null) { + roomOwnerUid = getArguments().getLong("room_owner_uid"); + } + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_room_rank_half_hour; + } + + @Override + public void onFindViews() { + ButterKnife.bind(this, mView); + } + + @Override + public void onSetListener() { + mHalfHourTab.setOnClickListener(this); + mInsideRoomTab.setOnClickListener(this); + } + + @Override + public void initiate() { + // 列表 + mAdapter = new RoomRankHalfHourListAdapter(mContext); + mRoomRankRecycler.setAdapter(mAdapter); + LinearLayoutManager layoutManager = new LinearLayoutManager(mContext); + layoutManager.setSmoothScrollbarEnabled(true); + mRoomRankRecycler.setLayoutManager(layoutManager); + mRoomRankRecycler.setHasFixedSize(true); + mRoomRankRecycler.setNestedScrollingEnabled(false); + mAdapter.setOnItemClickListener((adapter, view, position) -> { + RoomRankMultiItem roomRankMultiItem = mAdapter.getItem(position); + if (roomRankMultiItem == null) + return; + + if (roomRankMultiItem.getItemType() == RoomRankMultiItem.TYPE_LINEAR) { + RoomRankHalfHourRankInfo item = (RoomRankHalfHourRankInfo) roomRankMultiItem.getData(); + if (item != null && item.getUid() != 0) { + goToUserInfoPage(item.getUid()); + } + + } + }); + // 加载数据 + mRefreshLayout.setEnableRefresh(true); + mRefreshLayout.setOnRefreshListener(refreshlayout -> loadData()); + + mRefreshLayout.autoRefresh(100); + mRefreshLayout.setEnableLoadmore(false); + } + + private void loadData() { + if (!NetworkUtil.isNetAvailable(mContext)) { + showNetworkErr(); + mRefreshLayout.finishRefresh(); + return; + } + showLoading(); + getMvpPresenter().getRankListInfo(); + } + + private void goToUserInfoPage(long userId) { + if (dismissListener != null) { + dismissListener.onDismiss(); + } + UIHelper.showUserInfoAct(mContext, userId);// 个人中心 + } + + @Override + public void showMeInfo(RoomRankHalfHourMeInfo info) { + mRefreshLayout.finishRefresh(); + if (info == null) { + mMineRanking.setVisibility(View.GONE); + ivNumber.setVisibility(View.GONE); + llNumberOne.setVisibility(View.GONE); + llToLast.setVisibility(View.GONE); + mMineTitle.setText(""); + tvRoomId.setText(""); + return; + } + mMineInfoLayout.setOnClickListener(view -> goToUserInfoPage(roomOwnerUid)); + // 头像 + ImageLoadUtils.loadAvatar(mContext, info.getAvatar(), mMineAvatar, true); + // title + mMineTitle.setText(info.getRoomTitle()); + tvRoomId.setText("ID:" + info.getErbanNo()); + tvToLast.setText(RoomRankDialogUtils.getRoomRankValueText(info.getTotalNum())); + // value + // 展示方式不同:排名 + 值 + if (info.getSeqNo() == 0) {// 未上榜 + llNumberOne.setVisibility(View.GONE); + mMineRanking.setVisibility(View.VISIBLE); + llToLast.setVisibility(View.VISIBLE); + tvLabelTo.setText(""); + ivNumber.setVisibility(View.GONE); + } else { + int seqNo = info.getSeqNo(); + boolean isOne = seqNo == 1; + llNumberOne.setVisibility(isOne ? View.VISIBLE : View.GONE); + + if (seqNo >= 2 && seqNo <= 10) + tvLabelTo.setText("距离上一名"); + else if (seqNo > 10 && seqNo <= 20) + tvLabelTo.setText("距离上榜"); + else if (seqNo > 20) + tvLabelTo.setText(""); + + llToLast.setVisibility(isOne ? View.GONE : View.VISIBLE); + + int drawable = RoomRankDialogUtils.getNumberImage(seqNo); + if (drawable != 0) { + ivNumber.setVisibility(View.VISIBLE); + mMineRanking.setVisibility(View.GONE); + ivNumber.setImageResource(drawable); + } else { + ivNumber.setVisibility(View.GONE); + mMineRanking.setVisibility(View.VISIBLE); + } + } + } + + @Override + public void showTop3Info(List dataInfoList) { + if (dataInfoList == null) { + dataInfoList = new ArrayList<>(); + } + for (int i = 0; i < dataInfoList.size(); i++) { + RoomRankHalfHourRankInfo rankInfo = dataInfoList.get(i); + if (rankInfo == null) { + return; + } + if (i == 0) { + ImageLoadUtils.loadAvatar(mContext, rankInfo.getAvatar(), mTop1Avatar, true);// 头像 + mTop1Id.setText("ID:" + rankInfo.getErbanNo()); + mTop1Name.setText(rankInfo.getRoomTitle()); + mTop1AvatarDF.setImageResource(R.drawable.icon_consume_first); + tvRankHalfOne.setVisibility(View.VISIBLE); + mTop1Layout.setOnClickListener(view -> goToUserInfoPage(rankInfo.getUid())); + } + if (i == 1) { + ImageLoadUtils.loadAvatar(mContext, rankInfo.getAvatar(), mTop2Avatar, true);// 头像 + mTop2Id.setText("ID:" + rankInfo.getErbanNo()); + mTop2Value.setText("距前一名 " + RoomRankDialogUtils.getRoomRankValueText(rankInfo.getTotalNum()));// 经验值 + mTop2Name.setText(rankInfo.getRoomTitle()); + mTop2AvatarDF.setImageResource(R.drawable.icon_consume_second); + mTop2Layout.setOnClickListener(view -> goToUserInfoPage(rankInfo.getUid())); + } + if (i == 2) { + ImageLoadUtils.loadAvatar(mContext, rankInfo.getAvatar(), mTop3Avatar, true);// 头像 + mTop3Id.setText("ID:" + rankInfo.getErbanNo()); + mTop3Value.setText("距前一名 " + RoomRankDialogUtils.getRoomRankValueText(rankInfo.getTotalNum()));// 经验值 + mTop3Name.setText(rankInfo.getRoomTitle()); + mTop3AvatarDF.setImageResource(R.drawable.icon_consume_third); + mTop3Layout.setOnClickListener(view -> goToUserInfoPage(rankInfo.getUid())); + } + } + switch (dataInfoList.size()) { + case 0: + mTop1AvatarDF.setImageResource(R.drawable.icon_consume_first_empty); + mTop1Avatar.setVisibility(View.GONE); + tvRankHalfOne.setVisibility(View.GONE); + mTop1Id.setText(""); + + case 1: + mTop2AvatarDF.setImageResource(R.drawable.icon_consume_second_empty); + mTop2Avatar.setVisibility(View.GONE); + mTop2Id.setText(""); + mTop2Value.setText(""); + + case 2: + mTop3AvatarDF.setImageResource(R.drawable.icon_consume_third_empty); + mTop3Avatar.setVisibility(View.GONE); + mTop3Id.setText(""); + mTop3Value.setText(""); + break; + } + } + + @Override + public void showRankListInfo(List dataList) { + if (dataList == null) { + dataList = new ArrayList<>(); + } + mAdapter.replaceData(dataList); + if (dataList.size() > 0) { + mRoomRankRecycler.setVisibility(View.VISIBLE); + nestedScrollView.scrollTo(0, 0); + } else { + mRoomRankRecycler.setVisibility(View.GONE); + } + } + + @Override + public void loadDataFailure() { + mRefreshLayout.finishRefresh(); + showMeInfo(null/*, 0, ""*/); + showTop3Info(null); + showRankListInfo(null); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.tv_room_rank_half_hour_tab) {// 半小时榜 + goToChangePage(0); + } else if (id == R.id.tv_room_rank_in_room_tab) {// 房内榜 + goToChangePage(1); + } + } + + /** + * 修改最外层Dialog的显示页面 + */ + private void goToChangePage(int pos) { + if (changePageListener != null) { + changePageListener.onChangePage(pos); + } + } + + public void setDismissListener(IRoomRankDialogDismissListener dismissListener) { + this.dismissListener = dismissListener; + } + + public void setChangePageListener(IRoomRankDialogChangePageListener changePageListener) { + this.changePageListener = changePageListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankListFragment.java new file mode 100644 index 000000000..26c1cfaca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomRankListFragment.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.support.v4.app.Fragment; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.avroom.widget.RoomRankNavigatorAdapter; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.util.ArrayList; +import java.util.List; +import com.yizhuan.erban.databinding.FragmentRoomRankListBinding; + +@ActLayoutRes(R.layout.fragment_room_rank_list) +public class RoomRankListFragment extends BaseBindingFragment implements View.OnClickListener, IRoomRankDialogDismissListener{ + + public static RoomRankListFragment newInstance() { + return new RoomRankListFragment(); + } + + @Override + public void initiate() { + mBinding.setClick(this); + List list = new ArrayList<>(2); + list.add(new RoomContributeListFragment()); + list.add(RoomCharmListFragment.newInstance()); + mBinding.viewPager.setAdapter(new RoomContributeListAdapter(getChildFragmentManager(), list)); + + CommonNavigator commonNavigator = new CommonNavigator(getActivity()); + commonNavigator.setAdjustMode(true); + + RoomRankNavigatorAdapter indicator = new RoomRankNavigatorAdapter(); + indicator.setOnItemSelectListener(position -> mBinding.viewPager.setCurrentItem(position)); + commonNavigator.setAdapter(indicator); + mBinding.miRoomRank.setNavigator(commonNavigator); + ViewPagerHelper.bind(mBinding.miRoomRank, mBinding.viewPager); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_room_rank_half_hour_tab: + goToChangePage(0); + break; + + case R.id.tv_room_rank_in_room_tab: + goToChangePage(1); + break; + } + } + + private IRoomRankDialogDismissListener dismissListener; + private IRoomRankDialogChangePageListener changePageListener; + @Override + public void onDismiss() { + if (dismissListener != null) { + dismissListener.onDismiss(); + } + } + public void setDismissListener(IRoomRankDialogDismissListener dismissListener) { + this.dismissListener = dismissListener; + } + /** + * 修改最外层Dialog的显示页面 + */ + private void goToChangePage(int pos) { + if (changePageListener != null) { + changePageListener.onChangePage(pos); + } + } + + public void setChangePageListener(IRoomRankDialogChangePageListener changePageListener) { + this.changePageListener = changePageListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomTitleDialogFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomTitleDialogFragment.java new file mode 100644 index 000000000..ca7810944 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/RoomTitleDialogFragment.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.avroom.fragment; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.text.TextUtils; +import android.text.method.ScrollingMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +public class RoomTitleDialogFragment extends DialogFragment { + + public static DialogFragment getInstance(String title, String desc) { + DialogFragment dialogFragment = new RoomTitleDialogFragment(); + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("desc", desc); + dialogFragment.setArguments(bundle); + return dialogFragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NO_TITLE, R.style.DialogFragment); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_dialog_room_title, container); + + TextView tvTitle = root.findViewById(R.id.tv_title); + + TextView textView = root.findViewById(R.id.tv_dialog_desc); + textView.setMovementMethod(ScrollingMovementMethod.getInstance()); + + String title = null; + String desc = null; + Bundle bundle = getArguments(); + if (bundle != null) { + title = bundle.getString("title", ""); + desc = bundle.getString("desc", ""); + } + + if (TextUtils.isEmpty(title)) + title = "房间公告"; + + if (TextUtils.isEmpty(desc)) + desc = "这个房主很懒哟..."; + + tvTitle.setText(title); + textView.setText(desc); + + root.findViewById(R.id.tv_close).setOnClickListener(v -> { + dismiss(); + }); + + return root; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + Window window = getDialog().getWindow(); + if (window != null) { + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/game/GameAdapter.java new file mode 100644 index 000000000..bae3c8aab --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.avroom.game; + +import android.databinding.ViewDataBinding; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.ItemRoomGameBinding; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.xchat_android_core.room.game.GameInfo; + +public class GameAdapter extends BaseAdapter { + public GameAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + private int select = 0; + private boolean isFirst; + public void setSelect(int select) { + this.select = select; + if (!isFirst){ + isFirst=true; + }else { + // notifyDataSetChanged(); + } + } + + @Override + protected void convert(BindingViewHolder helper, GameInfo item) { + super.convert(helper, item); +// ItemRoomGameBinding binding = (ItemRoomGameBinding)helper.getBinding(); +// if (select==helper.getAdapterPosition()){ +// binding.root.setBackgroundResource(R.drawable.room_cp_game_sel); +// binding.shade.setVisibility(View.GONE); +// }else { +// binding.root.setBackgroundResource(R.color.transparent); +// binding.shade.setVisibility(View.VISIBLE); +// } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameExitDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/game/GameExitDialog.java new file mode 100644 index 000000000..709301f3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameExitDialog.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.avroom.game; + +import android.content.Context; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.DialogGameExitBinding; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.dialog_game_exit) +public class GameExitDialog extends BaseBindingDialog { + private Context mContext; + private OkCancelListener okCancelListener; + + public GameExitDialog(Context context, OkCancelListener okCancelListener) { + super(context); + mContext = context; + this.okCancelListener = okCancelListener; + } + + @Override + protected void init() { + binding.tvContinue.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + binding.tvExit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (okCancelListener != null) { + okCancelListener.onOk(); + dismiss(); + } + } + }); + } + + public interface OkCancelListener { + + void onOk(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameResultDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/game/GameResultDialog.java new file mode 100644 index 000000000..efcd9d154 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameResultDialog.java @@ -0,0 +1,277 @@ +package com.yizhuan.erban.avroom.game; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.view.View; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogGameResultBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.game.ChangeGameEvent; +import com.yizhuan.xchat_android_core.room.game.ChangeUserEvent; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; + +import cn.sharesdk.framework.Platform; +import nl.dionsegijn.konfetti.models.Shape; +import nl.dionsegijn.konfetti.models.Size; + +import static com.yizhuan.erban.ui.widget.ShareDialog.TYPE_SHARE_H5; + +@ActLayoutRes(R.layout.dialog_game_result) +public class GameResultDialog extends BaseBindingDialog implements View.OnClickListener, ShareDialog.OnShareDialogItemClick { + private GameResultInfo.ResultBean resultBean; + private PlayGameVm resultVm; + private Observer observer; + private OnClickListner clickListner; + private boolean isPub; + + public void setPub(boolean pub) { + isPub = pub; + } + + public void setClickListner(OnClickListner clickListner) { + this.clickListner = clickListner; + } + + public GameResultDialog(Context context, GameResultInfo.ResultBean resultBean, PlayGameVm resultVm) { + super(context); + this.resultBean = resultBean; + this.resultVm = resultVm; + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + observer = (Observer) message -> { + // 在这里处理自定义通知。 + if (message != null) { + String content = message.getContent(); + try { + JSONObject json = JSON.parseObject(content); + int type = json.getIntValue("gameType"); + if (type == PlayGameVm.AGAIN) { + binding.tvAgain.setText("对方已准备,马上再战"); + binding.tvAgain.setBackgroundResource(R.drawable.shape_24d7a7); + } else if (type == PlayGameVm.AGAIN_REPONSED) { + GameModel.get().getGameUrl(resultBean.getRoomId(), resultBean.getGameId(), resultBean.getChannelId(), 0) + .subscribe(gameUrlInfo -> { + dismiss(); + if (clickListner != null) { + clickListner.onReLoadGame(gameUrlInfo.getUrl()); + } + }); + } else if (type == PlayGameVm.LEAVE) { + binding.tvAgain.setText("对方已离开"); + binding.tvAgain.setBackgroundResource(R.drawable.shape_gray_round); + } + + } catch (Exception e) { + + } + } + }; + // 如果有自定义通知是作用于全局的,不依赖某个特定的 Activity,那么这段代码应该在 Application 的 onCreate 中就调用 + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, true); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // 如果有自定义通知是作用于全局的,不依赖某个特定的 Activity,那么这段代码应该在 Application 的 onCreate 中就调用 + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + } + + @Override + protected void init() { + + setCancelable(false); + binding.setViewModel(resultVm); + resultVm.isPraised(); + binding.setClick(this); + + if (!isPub) { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + binding.tvChangeUser.setVisibility(View.GONE); + } else if (AvRoomDataManager.get().isCpRoom()) { + binding.tvChangeUser.setVisibility(View.GONE); + } + } + + if (GameResultInfo.DRAW.equals(resultBean.getResultType())) { + binding.ivGameResult.setImageResource(R.drawable.room_cp_game_draw); + } else { + if (resultBean.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid()) { + binding.ivGameResult.setImageResource(R.drawable.room_cp_game_victory); + binding.konfettiView.build() + .addColors(Color.parseColor("#fe3864"), + Color.parseColor("#64ffa6"), + Color.parseColor("#ffdb00"), + Color.parseColor("#73eaff"), + Color.parseColor("#d350ff")) + .setDirection(0.0, 359.0) + .setSpeed(1f, 5f) + .setFadeOutEnabled(true) + .setTimeToLive(2000L) + .addShapes(Shape.RECT) + .addSizes(new Size(12, 5), new Size(16, 6f)) + .setPosition(-50f, UIUtil.getScreenWidth(context) + 50f, -50f, -50f) + .burst(60); + } else if (resultBean.getFailers().get(0).getUid() == AuthModel.get().getCurrentUid()) { + binding.ivGameResult.setImageResource(R.drawable.room_cp_game_defeated); + } else { + binding.ivGameResult.setImageResource(R.drawable.room_cp_game_victory); + } + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_attention: + PraiseModel.get().praise(resultVm.adverseUserInfo.get().getUid(), true) + .subscribe(s -> resultVm.isPraised.set(true)); + break; + case R.id.iv_share: + ShareDialog shareDialog = new ShareDialog(getContext()); + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + shareDialog.setType(TYPE_SHARE_H5); + } + shareDialog.setOnShareDialogItemClick(this); + shareDialog.show(); + break; + case R.id.tv_again: + if (binding.tvAgain.getText().toString().equals("再来一局")) { + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_again, "点击再来一局"); + } else if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_again, "点击再来一局"); + } else if (!AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_again, "点击再来一局"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game__again, "点击再来一局"); + } + + ImGameMode.get().sendNotify(resultVm.adverseUserInfo.get().getUid() + "", PlayGameVm.AGAIN); + binding.tvAgain.setText("等待对方接受"); + binding.tvAgain.setBackgroundResource(R.drawable.shape_gray_round); + } else if (binding.tvAgain.getText().toString().equals("对方已准备,马上再战")) { + ImGameMode.get().sendNotify(resultVm.adverseUserInfo.get().getUid() + "", PlayGameVm.AGAIN_REPONSED); + GameModel.get().getGameUrl(resultBean.getRoomId(), resultBean.getGameId(), resultBean.getChannelId(), 0) + .subscribe(gameUrlInfo -> { + dismiss(); + if (clickListner != null) { + clickListner.onReLoadGame(gameUrlInfo.getUrl()); + } + }); + } + break; + case R.id.tv_change_game: + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_newgame, "点击换个游戏"); + } else if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_newgame, "点击换个游戏"); + } else if (!AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_newgame, "点击换个游戏"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game_newgame, "点击换个游戏"); + } + + RxBus.get().post(new ChangeGameEvent()); + ((Activity) context).finish(); + break; + case R.id.tv_change_user: + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_newmatch, "点击换个对手"); + } else if (AvRoomDataManager.get().mCurrentRoomInfo != null && !AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_newmatch, "点击换个对手"); + } else if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game_newgame, "点击换个对手"); + } + + GameModel.get().getGameInfoById(resultBean.getGameId()) + .subscribe(gameInfo -> { + RxBus.get().post(new ChangeUserEvent(gameInfo)); + ((Activity) context).finish(); + }); + + break; + case R.id.tv_back: + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_return, "点击返回"); + } else if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_return, "点击返回"); + } else if (!AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_return, "点击返回"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game_return, "点击返回"); + } + ((Activity) context).finish(); + break; + } + } + + @Override + public void onInAppSharingItemClick() { + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_share, "点击分享app内"); + } else if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_share, "点击分享app内"); + } else if (!AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_share, "点击分享app内"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game_share, "点击分享app内"); + } + + SelectFriendActivity.startForSharingRoom((Activity) context); + } + + @Override + public void onSharePlatformClick(Platform platform) { + int result = 1; + if (resultBean.getResultType().equals(GameResultInfo.DRAW)) { + result = 3; + } else if (resultBean.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid()) { + result = 1; + } else if (resultBean.getFailers().get(0).getUid() == AuthModel.get().getCurrentUid()) { + result = 2; + } + if (isPub) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.public_chat_game_share, "点击分享" + platform.getName()); + } else if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_share, "点击分享" + platform.getName()); + } else if (!AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_game_share, "点击分享" + platform.getName()); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_game_share, "点击分享" + platform.getName()); + } + ImGameMode.get().getShareImg(result) + .subscribe(s -> { + ShareModel.get().shareImage(platform, s); + }); + } + + interface OnClickListner { + public void onReLoadGame(String url); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameSelectDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/game/GameSelectDialog.java new file mode 100644 index 000000000..720b0b4f7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameSelectDialog.java @@ -0,0 +1,198 @@ +package com.yizhuan.erban.avroom.game; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetDialog; +import android.support.v4.view.PagerAdapter; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.util.SparseArray; +import android.view.Display; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.widget.GalleryLayoutManager; +import com.yizhuan.erban.avroom.widget.ScaleTransformer; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.common.ViewPagerAdapter; +import com.yizhuan.erban.databinding.DialogGameSelectBinding; +import com.yizhuan.erban.ui.gift.dialog.GiftInfoVm; +import com.yizhuan.erban.ui.gift.dialog.MagicInfoVm; +import com.yizhuan.erban.ui.widget.OnPageSelectedListener; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_library.bindinglist.IItem; +import com.yizhuan.xchat_android_library.bindinglist.MultiTypeAdapter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +public class GameSelectDialog extends BottomSheetDialog { + private DialogGameSelectBinding mBinding; + private OnSelectClick onSelectClick; + private Context context; + private boolean isPublicHall; + + public GameSelectDialog(@NonNull Context context, boolean isPublicHall) { + super(context); + this.context = context; + this.isPublicHall = isPublicHall; + } + + public void setOnSelectClick(OnSelectClick onSelectClick) { + this.onSelectClick = onSelectClick; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_game_select); + mBinding = DataBindingUtil.bind(findViewById(R.id.root)); + + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + + try { + ViewGroup parent = (ViewGroup) mBinding.root.getParent(); + parent.setBackgroundResource(android.R.color.transparent); + } catch (Exception e) { + e.printStackTrace(); + } + + init(); + } + + private void init() { + mBinding.indicator.setSelectRes(R.drawable.shape_appcolor_corner); + mBinding.indicator.setNoSelectRes(R.drawable.shape_gray_5dp); + mBinding.indicator.setDotSize(UIUtil.dip2px(context, 12)); + mBinding.indicator.setHeight(UIUtil.dip2px(context, 5)); + + if (isPublicHall) { + GameModel.get().getHomeGameList() + .subscribe(gameInfos -> { + setGridViewData(beanTransformVm(gameInfos, 8)); + }); + } else { + GameModel.get().getGameList(AvRoomDataManager.get().getRoomUid()) + .subscribe(gameInfos -> { + setGridViewData(beanTransformVm(gameInfos, 8)); + }); + } + } + + private void setGridViewData(List> pagerList) { + LogUtil.e(pagerList.toString()); + if (ListUtils.isListEmpty(pagerList)) { + return; + } + mBinding.indicator.initIndicator(pagerList.size()); + mBinding.indicator.setDifSelectedPage(0); + mBinding.indicator.setVisibility(pagerList.size() > 1 ? View.VISIBLE : View.INVISIBLE); + SparseArray cacheItemView = new SparseArray<>(); + mBinding.gridView.setAdapter(new PagerAdapter() { + + @Override + public int getCount() { + return pagerList.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int pagePos) { + RecyclerView recyclerView; + BaseAdapter giftAdapter; + if (cacheItemView.get(pagePos) == null) { + recyclerView = new RecyclerView(context); + recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + recyclerView.setLayoutManager(new GridLayoutManager(context, 4)); + giftAdapter = new BaseAdapter(R.layout.item_im_game_select, BR.gameInfo); + recyclerView.setAdapter(giftAdapter); + cacheItemView.put(pagePos, recyclerView); + } else { + recyclerView = cacheItemView.get(pagePos); + giftAdapter = (BaseAdapter) recyclerView.getAdapter(); + } + giftAdapter.setNewData(pagerList.get(pagePos)); + giftAdapter.setOnItemClickListener((adapter, view, position) -> { + if (onSelectClick != null) { + onSelectClick.onClick(giftAdapter.getItem(position)); + } + dismiss(); + }); + container.addView(recyclerView); + return recyclerView; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + RecyclerView recyclerView = cacheItemView.get(position); + BaseAdapter adapter = (BaseAdapter) recyclerView.getAdapter(); + adapter.getData().clear(); + container.removeView(recyclerView); + } + }); + mBinding.gridView.addOnPageChangeListener(new OnPageSelectedListener() { + @Override + public void onPageSelected(int position) { + if (pagerList.size() > 1) { + mBinding.indicator.setDifSelectedPage(position); + } + } + }); + } + public interface OnSelectClick { + public void onClick(GameInfo gameInfo); + } + + private static List> beanTransformVm(List data, int pageSize) { + List> result = new ArrayList<>(); + if (ListUtils.isListEmpty(data)) { + return result; + } + for (int i = 0; i < data.size(); i++) { + GameInfo item = data.get(i); + List page = null; + if (i % pageSize == 0) { + page = new ArrayList<>(); + result.add(page); + } else { + if (result.size() > 0) { + page = result.get(result.size() - 1); + } + } + if (item != null && page != null) { + page.add(item); + } + } + return result; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameView.java b/app/src/main/java/com/yizhuan/erban/avroom/game/GameView.java new file mode 100644 index 000000000..b4c621f54 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameView.java @@ -0,0 +1,552 @@ +package com.yizhuan.erban.avroom.game; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.presenter.HomePartyPresenter; +import com.yizhuan.erban.avroom.widget.GalleryLayoutManager; +import com.yizhuan.erban.avroom.widget.ScaleTransformer; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.LayoutGameInviteSelfBinding; +import com.yizhuan.erban.databinding.LayoutGamePlayingBinding; +import com.yizhuan.erban.databinding.LayoutGamePreparedBinding; +import com.yizhuan.erban.databinding.LayoutGameSelectBinding; +import com.yizhuan.erban.databinding.LayoutGameInviteOtherBinding; +import com.yizhuan.erban.databinding.LayoutGameResultBinding; +import com.yizhuan.erban.databinding.LayoutGameResultAudienceBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.game.ChangeGameEvent; +import com.yizhuan.xchat_android_core.room.game.GameEvent; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.room.game.GameUrlInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.SaConstant; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +public class GameView extends FrameLayout { + + private FrameLayout container; + private LayoutGameSelectBinding gameSelectBinding; + private LayoutGameInviteOtherBinding inviteOtherBinding; + private TextView tvClose; + private Context mContext; + private Disposable subscribe; + private View statuView; + private boolean isPrepare; + private Disposable disposable; + + public GameView(@NonNull Context context) { + this(context, null); + } + + public GameView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + mContext = context; + init(); + } + + private void init() { + inflate(getContext(), R.layout.layout_game_view, this); + container = findViewById(R.id.play_container); + tvClose = findViewById(R.id.tv_close); + // statusView = showSelectGame(); + subscribe = RxBus.get().toFlowable(GameEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(gameEvent -> handEvent(gameEvent)); + + disposable = RxBus.get().toFlowable(ChangeGameEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(gameEvent -> { + statuView = showSelectGame(); + }); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (subscribe != null) subscribe.dispose(); + if (disposable != null) disposable.dispose(); + } + + public void setCloseClick(OnClickListener closeClick) { + tvClose.setOnClickListener(closeClick); + } + + public void updateView(int type) { + if (!AvRoomDataManager.get().isRoomOwner()) { + tvClose.setVisibility(GONE); + } + if (AvRoomDataManager.get().mCurrentRoomInfo == null) return; + switch (type) { + case GameModel.SELECTING: + statuView = showSelectGame(); + break; + case GameModel.PREPARING: + if (AvRoomDataManager.get().mCurrentRoomInfo.roomGame == null) return; + GameModel.get().getGameInfoById(AvRoomDataManager.get().mCurrentRoomInfo.roomGame.getGameId()) + .subscribe(gameInfo -> { + if (AvRoomDataManager.get().mCurrentRoomInfo.roomGame.startUid == AuthModel.get().getCurrentUid()) { + statuView = showSelfPrepareView(gameInfo); + } else { + statuView = showPrepareView(gameInfo); + } + }); + break; + case GameModel.PLAYING: + if (AvRoomDataManager.get().mCurrentRoomInfo.roomGame == null) return; + GameModel.get().getGameInfoById(AvRoomDataManager.get().mCurrentRoomInfo.roomGame.getGameId()) + .subscribe(gameInfo -> statuView = showPlayingView(gameInfo)); + break; + default: + statuView = showSelectGame(); + } + } + + private void handEvent(GameEvent gameEvent) { + switch (gameEvent.getType()) { + case GameEvent.SELF_PREPARE: + statuView = showSelfPrepareView(gameEvent.getGameInfo()); + break; + case GameEvent.SELECT_GAME: + statuView = showPrepareView(gameEvent.getGameInfo()); + break; + case GameEvent.CANCEL_PREPARE: + statuView = showSelectGame(); + break; + case GameEvent.START_GAME: + statuView = showStartView(gameEvent.getGameInfo()); + break; + case GameEvent.GAME_END: + if (AvRoomDataManager.get().isOwnerOnMic()) { + statuView = showPlayerResultView(gameEvent.getResultInfo()); + } else { + statuView = showAudienceResultView(gameEvent.getResultInfo()); + } + break; + } + } + + public void updateUpMic() { + updateStatus(); + } + + public void downMic() { + updateStatus(); + if (AvRoomDataManager.get().findFreePosition() <= 0) { + if (isPrepare && !AvRoomDataManager.get().isOwnerOnMic()) { + GameModel.get().removePool(GameModel.get().getGameId()).subscribe(); + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.SELECTING, + GameModel.get().getGameId(), + GameModel.get().getGameName(), + false) + .subscribe(s -> GameModel.get().sendCancelPrepare()); + } + } + } + + private void updateStatus() { + if (gameSelectBinding != null) { + if (!AvRoomDataManager.get().isOwnerOnMic()) { + gameSelectBinding.tvSelect.setVisibility(GONE); + gameSelectBinding.tvSelecting.setVisibility(VISIBLE); + } else { + gameSelectBinding.tvSelecting.setVisibility(GONE); + gameSelectBinding.tvSelect.setVisibility(VISIBLE); + } + } + if (inviteOtherBinding != null) { + if (!AvRoomDataManager.get().isOwnerOnMic()) { + inviteOtherBinding.tvAgree.setText("立即准备"); + inviteOtherBinding.tvCancel.setVisibility(GONE); + } else { + inviteOtherBinding.tvAgree.setText("接受"); + inviteOtherBinding.tvCancel.setVisibility(VISIBLE); + } + } + } + + /** + * 游客看到的正在游戏中页面 + * + * @param gameInfo + * @return + */ + private View showPlayingView(GameInfo gameInfo) { + View view = inflate(getContext(), R.layout.layout_game_playing, null); + isPrepare = false; + if (gameInfo == null || statuView == view) return view; + GameModel.get().setGameInfo(gameInfo); + LayoutGamePlayingBinding binding = DataBindingUtil.bind(view); + binding.tvName.setText(gameInfo.getGameName()); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(-1); + if (roomQueueInfo != null && roomQueueInfo.mChatRoomMember != null) { + ImageLoadUtils.loadAvatar(getContext(), roomQueueInfo.mChatRoomMember.getAvatar(), binding.ivAvatarLeft); + } + RoomQueueInfo roomQueueInfo1 = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(0); + if (roomQueueInfo1 != null && roomQueueInfo1.mChatRoomMember != null) { + ImageLoadUtils.loadAvatar(getContext(), roomQueueInfo1.mChatRoomMember.getAvatar(), binding.ivAvatarRight); + } + binding.tvWatch.setOnClickListener(v -> + GameModel.get().getWatchGameUrl(AvRoomDataManager.get().getRoomId(), + gameInfo.getGameId(), + gameInfo.getGameChannel()) + .subscribe(gameUrlInfo -> PlayGameActivity.start(getContext(), gameUrlInfo.getUrl(), 0))); + showStatusView(view); + return null; + } + + /** + * 玩家看到的游戏结果页面 + * + * @return + */ + private View showPlayerResultView(GameResultInfo.ResultBean resultInfo) { + View view = inflate(getContext(), R.layout.layout_game_result, null); + isPrepare = false; + if (resultInfo == null || statuView == view) return view; + LayoutGameResultBinding resultBinding = DataBindingUtil.bind(view); + GameModel.get().getGameInfoById(resultInfo.getGameId()) + .subscribe(gameInfo -> resultBinding.tvName.setText("- " + gameInfo.getGameName() + " -")); + + if (GameResultInfo.NOT_DRAW.equals(resultInfo.getResultType())) { + ImageLoadUtils.loadAvatar(getContext(), UserModel.get().getCacheLoginUserInfo().getAvatar(), resultBinding.ivAvatar); + loadAvatar(AuthModel.get().getCurrentUid(), resultBinding.ivAvatar); + if (resultInfo.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid()) { + resultBinding.ivHeadWear.setVisibility(VISIBLE); + } + } else if (GameResultInfo.DRAW.equals(resultInfo.getResultType())) { + resultBinding.flAvatarLayout.setVisibility(GONE); + loadAvatar(resultInfo.getUsers().get(0).getUid(), resultBinding.ivAvatarLeft); + loadAvatar(resultInfo.getUsers().get(1).getUid(), resultBinding.ivAvatarRight); + } + + GameModel.get().getGameInfoById(resultInfo.getGameId()) + .subscribe(gameInfo -> { + resultBinding.tvChangeGame.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gameover_changegame_click, "换个游戏"); + GameModel.get().updateGameStatus(AvRoomDataManager.get().getRoomUid(), + GameModel.SELECTING, gameInfo.getGameId(), gameInfo.getGameName()) + .subscribe(s -> GameModel.get().sendCancelPrepare()); + }); + resultBinding.tvAgain.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gameover_anotherround_click, "再来一局"); + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.PREPARING, gameInfo.getGameId(), gameInfo.getGameName()) + .subscribe(s -> GameModel.get().selectGameEnd(gameInfo)); + if (GameModel.get().cannAddPool()) { + GameModel.get().addPool(gameInfo.getGameId()).subscribe(); + } + }); + }); + + showStatusView(view); + return view; + } + + /** + * 观众看到的游戏结果页面 + * + * @return + */ + @SuppressLint("CheckResult") + private View showAudienceResultView(GameResultInfo.ResultBean resultInfo) { + View view = inflate(getContext(), R.layout.layout_game_result_audience, null); + isPrepare = false; + if (resultInfo == null || statuView == view) return view; + + LayoutGameResultAudienceBinding resultBinding = DataBindingUtil.bind(view); + ImageLoadUtils.loadAvatar(getContext(), UserModel.get().getCacheLoginUserInfo().getAvatar(), resultBinding.ivAvatarLeft); + GameModel.get().getGameInfoById(resultInfo.getGameId()) + .subscribe(gameInfo -> resultBinding.tvName.setText("- " + gameInfo.getGameName() + " -")); + + Long leftUid = 0l; + Long rightUid = 0l; + + if (GameResultInfo.NOT_DRAW.equals(resultInfo.getResultType())) { + leftUid = resultInfo.getWinners().get(0).getUid(); + resultBinding.llRight.setVisibility(GONE); + } else { + leftUid = resultInfo.getUsers().get(0).getUid(); + rightUid = resultInfo.getUsers().get(1).getUid(); + UserModel.get().getUserInfo(rightUid) + .subscribe(userInfo -> { + resultBinding.tvNickRight.setText(userInfo.getNick()); + resultBinding.tvNickRight + .setCompoundDrawablesWithIntrinsicBounds(0, 0, userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female, 0); + ImageLoadUtils.loadAvatar(getContext(), userInfo.getAvatar(), resultBinding.ivAvatarRight); + }); + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), rightUid) + .subscribe(aBoolean -> { + if (aBoolean) { + resultBinding.tvAttentionRight.setVisibility(INVISIBLE); + } + }); + } + UserModel.get().getUserInfo(leftUid) + .subscribe(userInfo -> { + resultBinding.tvNickLeft.setText(userInfo.getNick()); + resultBinding.tvNickLeft + .setCompoundDrawablesWithIntrinsicBounds(0, 0, userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female, 0); + ImageLoadUtils.loadAvatar(getContext(), userInfo.getAvatar(), resultBinding.ivAvatarLeft); + }); + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), leftUid) + .subscribe(aBoolean -> { + if (aBoolean) { + resultBinding.tvAttention.setVisibility(INVISIBLE); + } + }); + + Long finalLeftUid = leftUid; + resultBinding.tvAttention.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gameover_follow_click, "关注按钮"); + + PraiseModel.get().praise(finalLeftUid, true) + .subscribe(s -> resultBinding.tvAttention.setVisibility(INVISIBLE)); + }); + + + Long finalRightUid = rightUid; + resultBinding.tvAttentionRight.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gameover_follow_click, "关注按钮"); + PraiseModel.get().praise(finalRightUid, true) + .subscribe(s -> resultBinding.tvAttentionRight.setVisibility(INVISIBLE)); + }); + + showStatusView(view); + return view; + } + + /** + * 选择游戏邀请的页面 + * + * @return + */ + public View showSelectGame() { + View view = inflate(getContext(), R.layout.layout_game_select, null); + isPrepare = false; + if (AvRoomDataManager.get().mCurrentRoomInfo == null || statuView == view) return view; + gameSelectBinding = DataBindingUtil.bind(view.findViewById(R.id.container)); + + GalleryLayoutManager layoutManager = new GalleryLayoutManager(GalleryLayoutManager.HORIZONTAL); + layoutManager.attach(gameSelectBinding.recyclerView, 0); + layoutManager.setItemTransformer(new ScaleTransformer()); + + GameAdapter adapter = new GameAdapter(R.layout.item_room_game, BR.gameInfo); + adapter.setOnItemClickListener((adapt, view1, position) -> gameSelectBinding.recyclerView.smoothScrollToPosition(position)); + gameSelectBinding.recyclerView.setAdapter(adapter); + + GameModel.get().getGameList(AvRoomDataManager.get().getRoomUid()) + .subscribe(gameInfos -> { + layoutManager.setOnItemSelectedListener((recyclerView, item, position) -> adapter.setSelect(position)); + adapter.setNewData(gameInfos); + }); + + gameSelectBinding.tvSelect.setOnClickListener(v -> { + if (adapter.getData() == null || adapter.getData().size() == 0) return; + GameInfo item = adapter.getItem(layoutManager.getCurSelectedPosition()); + + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.PREPARING, item.getGameId(), item.getGameName()) + .subscribe(s -> GameModel.get().selectGameEnd(item)); + + if (GameModel.get().cannAddPool()) { + GameModel.get().addPool(item.getGameId()).subscribe(); + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamechose_ready_click, "麦上用户发起按钮"); + + }); + if (!AvRoomDataManager.get().isRoomOwner()) { + gameSelectBinding.tvInvite.setVisibility(GONE); + } + gameSelectBinding.tvInvite.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamechose_invitation_click, "邀请好友按钮"); + SelectFriendActivity.startForSharingRoom((Activity) mContext); + }); + if (AvRoomDataManager.get().isOwnerOnMic()) { + gameSelectBinding.tvSelect.setVisibility(VISIBLE); + gameSelectBinding.tvSelecting.setVisibility(GONE); + } else { + gameSelectBinding.tvSelecting.setVisibility(VISIBLE); + gameSelectBinding.tvSelect.setVisibility(GONE); + } + showStatusView(view); + return view; + } + + /** + * 接收游戏邀请的页面 + * + * @param gameInfo + * @return + */ + private View showPrepareView(GameInfo gameInfo) { + View view = inflate(getContext(), R.layout.layout_game_invite_other, null); + isPrepare = false; + if (gameInfo == null || statuView == view) return view; + GameModel.get().setGameInfo(gameInfo); + inviteOtherBinding = DataBindingUtil.bind(view); + inviteOtherBinding.setGameInfo(gameInfo); + if (!AvRoomDataManager.get().isOwnerOnMic()) { + inviteOtherBinding.tvAgree.setText("立即准备"); + inviteOtherBinding.tvCancel.setVisibility(GONE); + } else { + inviteOtherBinding.tvAgree.setText("接受"); + inviteOtherBinding.tvCancel.setVisibility(VISIBLE); + } + inviteOtherBinding.tvAgree.setOnClickListener(v -> { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(AvRoomDataManager.get().findFreePosition()); + if (AvRoomDataManager.get().isOwnerOnMic()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamechose_invitation_click, "麦上用户接受按钮"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_accept_click, "游戏等待面板-麦上用户接受按钮"); + agreeGame(gameInfo); + } else { + if (AvRoomDataManager.get().findFreePosition() > 0 || + (roomQueueInfo.mRoomMicInfo != null && roomQueueInfo.mRoomMicInfo.isMicLock())) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_ready_click, "麦下用户准备按钮"); + SingleToastUtil.showToast("上麦才能玩游戏哦"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_ready_click, "麦下用户准备按钮"); + new HomePartyPresenter().upMicroPhone( + AvRoomDataManager.get().findFreePosition(), + AuthModel.get().getCurrentUid() + "", + false); + agreeGame(gameInfo); + } + } + }); + inviteOtherBinding.tvCancel.setOnClickListener(v -> { + if (AvRoomDataManager.get().isOwnerOnMic()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_gamematching_refuse_click, "麦上用户拒绝按钮"); + + GameModel.get().removePool(gameInfo.getGameId()).subscribe(); + GameModel.get().updateGameStatus(AvRoomDataManager.get().getRoomUid(), + GameModel.SELECTING, gameInfo.getGameId(), gameInfo.getGameName()) + .subscribe(s -> GameModel.get().sendCancelPrepare()); + } else { + SingleToastUtil.showToast("上麦才能玩游戏哦"); + } + }); + showStatusView(view); + return view; + } + + private void agreeGame(GameInfo gameInfo) { + GameModel.get().removePool(gameInfo.getGameId()).subscribe(); + GameModel.get().updateGameStatus(AvRoomDataManager.get().getRoomUid(), + GameModel.PLAYING, gameInfo.getGameId(), gameInfo.getGameName()) + .subscribe(s -> GameModel.get().sendGameStartMsg(gameInfo)); + } + + /** + * 都准备好了进入游戏时2秒的过度页面 + * + * @param gameInfo + * @return + */ + private View showStartView(GameInfo gameInfo) { + View view = inflate(getContext(), R.layout.layout_game_prepared, null); + isPrepare = false; + if (gameInfo == null || statuView == view) return view; + GameModel.get().setGameInfo(gameInfo); + LayoutGamePreparedBinding inviteOtherBinding = DataBindingUtil.bind(view); + inviteOtherBinding.setGameInfo(gameInfo); + boolean ownerOnMic = AvRoomDataManager.get().isOwnerOnMic(); + Single.timer(2, TimeUnit.SECONDS) + .flatMap((Function>) aLong -> { + if (ownerOnMic) { + return GameModel.get().getGameUrl(AvRoomDataManager.get().getRoomId(), gameInfo.getGameId(), gameInfo.getGameChannel(), 0); + } else { + return GameModel.get().getWatchGameUrl(AvRoomDataManager.get().getRoomId(), gameInfo.getGameId(), gameInfo.getGameChannel()); + } + }).subscribe(gameUrlInfo -> { + if (ownerOnMic) { + GameModel.get().removePool(gameInfo.getGameId()).subscribe(); + PlayGameActivity.start(getContext(), gameUrlInfo.getUrl(), 0); + showSelectGame(); + } else { + showPlayingView(gameInfo); + } + }); + + + showStatusView(view); + return view; + } + + private View showSelfPrepareView(GameInfo gameInfo) { + View view = inflate(getContext(), R.layout.layout_game_invite_self, null); + isPrepare = true; + if (gameInfo == null || statuView == view) return view; + GameModel.get().setGameInfo(gameInfo); + LayoutGameInviteSelfBinding inviteSelfBinding = DataBindingUtil.bind(view); + inviteSelfBinding.setGameInfo(gameInfo); + inviteSelfBinding.tvCancel.setOnClickListener(v -> { + GameModel.get().updateGameStatus( + AvRoomDataManager.get().getRoomUid(), + GameModel.SELECTING, + gameInfo.getGameId(), + gameInfo.getGameName()) + .subscribe(s -> GameModel.get().sendCancelPrepare()); + + GameModel.get().removePool(gameInfo.getGameId()).subscribe(); + + }); + showStatusView(view); + return view; + } + + private void loadAvatar(long uid, ImageView imageView) { + UserModel.get().getUserInfo(uid) + .subscribe(userInfo -> ImageLoadUtils.loadAvatar(getContext(), userInfo.getAvatar(), imageView)); + } + + private void showStatusView(View view) { + container.setVisibility(VISIBLE); + container.removeAllViews(); + container.addView(view); + statuView = view; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/MatchActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/game/MatchActivity.java new file mode 100644 index 000000000..3e1be3f2c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/MatchActivity.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.avroom.game; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.AnimationDrawable; +import android.view.View; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityMatchBinding; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameAttachInfo; +import com.yizhuan.xchat_android_core.room.game.GameMatchInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.model.exception.SAdminCannotGameException; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +@ActLayoutRes(R.layout.activity_match) +public class MatchActivity extends BaseBindingActivity { + + private MatchViewModel viewModel; + private Observer observer; + private boolean isMatch; + private long time; + + public static void start(Context context, GameInfo gameInfo) { + Intent intent = new Intent(context, MatchActivity.class); + intent.putExtra("gameInfo", gameInfo); + context.startActivity(intent); + } + + @Override + protected void init() { + time = System.currentTimeMillis(); + mBinding.ivClose.setOnClickListener(v -> onBackPressed()); + + viewModel = new MatchViewModel((GameInfo) getIntent().getSerializableExtra("gameInfo")); + mBinding.setViewModel(viewModel); + viewModel.match() + .doOnError(throwable -> { + if (throwable instanceof SAdminCannotGameException) { + finish(); + } + }) + .subscribe(); + + AnimationDrawable anim = (AnimationDrawable) getResources().getDrawable(R.drawable.anim_match); + mBinding.ivAvatar.setImageDrawable(anim); + anim.start(); + + observer = (Observer) message -> { + // 在这里处理自定义通知。 + if (message != null) { + try { + mBinding.ivClose.setVisibility(View.GONE); + anim.stop(); + isMatch = true; + + JSONObject object = JSON.parseObject(message.getContent()); + GameMatchInfo matchInfo = new Gson().fromJson(object.toJSONString(), GameMatchInfo.class); + LogUtil.e("系统消息" + object.toJSONString()); + if (matchInfo == null || matchInfo.getData() == null) return; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_matching_getnews, "接受匹配消息" + (System.currentTimeMillis() - time) / 1000); + + String gameUrl = ""; + if (matchInfo.getData().getPlayer1().getUid() != AuthModel.get().getCurrentUid()) { + viewModel.matchUser.set(matchInfo.getData().getPlayer1()); + gameUrl = matchInfo.getData().getPlayer2().getGameUrl(); + } else if (matchInfo.getData().getPlayer2().getUid() != AuthModel.get().getCurrentUid()) { + viewModel.matchUser.set(matchInfo.getData().getPlayer2()); + gameUrl = matchInfo.getData().getPlayer1().getGameUrl(); + } + + String finalGameUrl = gameUrl; + Single.timer(2, TimeUnit.SECONDS) + // .compose(bindToLifecycle()) + .subscribe(aLong -> { + AvRoomDataManager.get().mIsNeedOpenMic = false; + AVRoomActivity.start(MatchActivity.this, matchInfo.getData().getRoomId(), viewModel.gameInfo, finalGameUrl, matchInfo.getData().getAiUid()); + finish(); + }); + } catch (Exception e) { + } + } + }; + + Single.timer(20, TimeUnit.SECONDS) + .compose(bindToLifecycle()) + .subscribe(aLong -> { + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + if (!isMatch) { + toast("匹配超时,请尝试重新匹配"); + finish(); + } + }); + // 如果有自定义通知是作用于全局的,不依赖某个特定的 Activity,那么这段代码应该在 Application 的 onCreate 中就调用 + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, true); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + viewModel.cancelMatch().subscribe(); + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + } + + @Override + public void onBackPressed() { + if (isMatch) { + return; + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.gamematching_close_click, "取消匹配"); + super.onBackPressed(); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/MatchViewModel.java b/app/src/main/java/com/yizhuan/erban/avroom/game/MatchViewModel.java new file mode 100644 index 000000000..6129d1f47 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/MatchViewModel.java @@ -0,0 +1,62 @@ +package com.yizhuan.erban.avroom.game; + +import android.databinding.ObservableField; + +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameMatchInfo; +import com.yizhuan.xchat_android_core.super_admin.model.exception.SAdminCannotGameException; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.ErrorConsumer; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.net.rxnet.RxNet; + +import io.reactivex.Single; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.POST; + +public class MatchViewModel { + public ObservableField userInfo = new ObservableField<>(); + public ObservableField matchUser = new ObservableField<>(); + public GameInfo gameInfo; + private Api api; + + public MatchViewModel(GameInfo gameInfo) { + api = RxNet.create(Api.class); + this.gameInfo = gameInfo; + userInfo.set(UserModel.get().getCacheLoginUserInfo()); + } + + public Single match() { + if (gameInfo == null) { + return Single.error(new Throwable("gameInfo为空")); + } + return api.match(AuthModel.get().getCurrentUid(), gameInfo.getGameId()) + .compose(RxHelper.handleSAdminError()) + .compose(RxHelper.handleStringData()) + .doOnError(new ErrorConsumer(true)); + } + + public Single cancelMatch() { + if (gameInfo == null) { + return Single.error(new Throwable("gameInfo为空")); + } + return api.cancelMatch(AuthModel.get().getCurrentUid(), gameInfo.getGameId()) + .compose(RxHelper.handleStringData()); + } + + interface Api { + + @FormUrlEncoded + @POST("game/v1/match/add") + public Single> match(@Field("uid") long uid, @Field("gameId") String gameId); + + @FormUrlEncoded + @POST("game/v1/match/remove") + public Single> cancelMatch(@Field("uid") long uid, @Field("gameId") String gameId); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameActivity.java new file mode 100644 index 000000000..2c4ba4cf9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameActivity.java @@ -0,0 +1,550 @@ +package com.yizhuan.erban.avroom.game; + +import android.animation.Animator; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.media.Image; +import android.net.http.SslError; +import android.os.Build; +import android.os.Environment; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.webkit.JavascriptInterface; +import android.webkit.SslErrorHandler; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ImageView; +import android.widget.Toast; + +//import com.tongdaxing.tutu.R; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityPlayGameBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameAttachment; +import com.yizhuan.xchat_android_core.im.game.GameResultEvent; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.game.AiPlayEndEvent; +import com.yizhuan.xchat_android_core.room.game.GameAttachInfo; +import com.yizhuan.xchat_android_core.room.game.GameEvent; +import com.yizhuan.xchat_android_core.room.game.GameMatchInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.room.game.GameUidInfo; +import com.yizhuan.xchat_android_core.room.game.GameUrlInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.ImageSplitter; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.softinput.SoftHideKeyBoardUtil; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import io.agora.rtc.Constants; +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +@ActLayoutRes(R.layout.activity_play_game) +public class PlayGameActivity extends BaseBindingActivity { + + private PlayGameVm viewModel; + private long aiUid; + //从私聊和公聊进来 + private boolean isIm; + //是否观战 + boolean isWatch; + private long channelId; + //是否是玩家 + private boolean isPlayer = false; + + private String msgId; + private Observer observer; + + public static void start(Context context, String url, long aiUid) { + Intent intent = new Intent(context, PlayGameActivity.class); + intent.putExtra("url", url); + intent.putExtra("aiUid", aiUid); + context.startActivity(intent); + } + + public static void start(Context context, String url, String uuid) { + Intent intent = new Intent(context, PlayGameActivity.class); + intent.putExtra("url", url); + intent.putExtra("uuId", uuid); + context.startActivity(intent); + } + + public static void start(Context context, String url, long roomId, String uuId) { + Intent intent = new Intent(context, PlayGameActivity.class); + intent.putExtra("url", url); + intent.putExtra("roomId", roomId);//声网频道,一般为游戏发起方的uid + intent.putExtra("isIm", true); + intent.putExtra("uuId", uuId); + context.startActivity(intent); + } + + public static void pubStart(Context context, String url, long roomId, String uuId) { + Intent intent = new Intent(context, PlayGameActivity.class); + intent.putExtra("url", url); + intent.putExtra("roomId", roomId);//声网频道,一般为游戏发起方的uid + intent.putExtra("isIm", true); + intent.putExtra("uuId", uuId); + //是否是公聊大厅进来的 + intent.putExtra("isPub", true); + context.startActivity(intent); + } + + public static void start(Context context, String url, long roomId, String uuId, boolean isWatch) { + Intent intent = new Intent(context, PlayGameActivity.class); + intent.putExtra("url", url); + intent.putExtra("roomId", roomId);//声网频道,一般为游戏发起方的uid + intent.putExtra("isIm", true); + intent.putExtra("uuId", uuId); + intent.putExtra("isWatch", isWatch); + context.startActivity(intent); + } + + @Override + protected void init() { + + viewModel = new PlayGameVm(); + mBinding.setViewModel(viewModel); + + aiUid = getIntent().getLongExtra("aiUid", 0); + isIm = getIntent().getBooleanExtra("isIm", false); + channelId = getIntent().getLongExtra("roomId", 0); + isWatch = getIntent().getBooleanExtra("isWatch", false); + msgId = getIntent().getStringExtra("uuId"); + + enterAgo(); + + if (aiUid != 0) { + viewModel.setRightUid(aiUid) + .subscribe(userInfo -> GameModel.get().sendAiEnterMsg(userInfo.getNick())); + } + + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .subscribe(roomEvent -> { + if (roomEvent.getEvent() == RoomEvent.UP_MIC) { + viewModel.isOnMic.set(AvRoomDataManager.get().isOwnerOnMic()); + } + }); + + initWebView(); + String url = getIntent().getStringExtra("url"); +// LogUtil.e(url); +// LogUtil.e("http://127.0.0.1:8080" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/feidao/index.html?" + url.substring(url.indexOf("?") + 1)); +// if (url.contains("feidao")) { +// mBinding.webview.loadUrl("http://localhost:8080" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/feidao/index.html?" + url.substring(url.indexOf("?") + 1)); +// } else { + mBinding.webview.loadUrl(url); + // } + // mBinding.webview.loadUrl(getIntent().getStringExtra("url"));` + registNotifyMsg(); + registerNimBroadcastMessage(false); + + } + + private void registNotifyMsg() { + observer = (Observer) message -> { + // 在这里处理自定义通知。 + if (message != null) { + String content = message.getContent(); + try { + JSONObject json = JSON.parseObject(content); + String faceUrl = json.getString(PlayGameVm.FACE_URL); + if (TextUtils.isEmpty(faceUrl)) return; + showFaceAnim(faceUrl, false); + } catch (Exception e) { + } + } + }; + // 如果有自定义通知是作用于全局的,不依赖某个特定的 Activity,那么这段代码应该在 Application 的 onCreate 中就调用 + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, true); + } + + private void enterAgo() { + if (isIm && !AvRoomDataManager.get().roomNoDestory) { + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + } + + @Override + public void onFail(int code, String error) { + } + }); + + RtcEngineManager.get().joinChannel(channelId, AuthModel.get().getCurrentUid()); + if (!isWatch) { + viewModel.isOnMic.set(true); + RtcEngineManager.get().setRole(Constants.CLIENT_ROLE_BROADCASTER); + } else { + RtcEngineManager.get().setRole(Constants.CLIENT_ROLE_AUDIENCE); + } + } + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.tv_exit: + onBackPressed(); + break; + case R.id.iv_voice: + mBinding.webview.loadUrl("javascript:mute()"); + viewModel.gameVoice.set(!viewModel.gameVoice.get()); + break; + case R.id.iv_help: + mBinding.webview.loadUrl("javascript:intro()"); + break; + case R.id.iv_change_watch: + mBinding.webview.loadUrl("javascript:changeWatch()"); + viewModel.watchLeft.set(!viewModel.watchLeft.get()); + break; + case R.id.iv_face1: + if (ListUtils.isListEmpty(viewModel.faceList)) return; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.h5_gamepage_expression, "发表情1"); + viewModel.sendNotifyMsg(0); + showFaceAnim(viewModel.faceList.get(0), true); + break; + case R.id.iv_face2: + if (ListUtils.isListEmpty(viewModel.faceList)) return; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.h5_gamepage_expression, "发表情2"); + viewModel.sendNotifyMsg(1); + showFaceAnim(viewModel.faceList.get(1), true); + break; + case R.id.iv_face3: + if (ListUtils.isListEmpty(viewModel.faceList)) return; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.h5_gamepage_expression, "发表情3"); + viewModel.sendNotifyMsg(2); + showFaceAnim(viewModel.faceList.get(2), true); + break; + + } + + } + + private void initWebView() { + mBinding.webview.getSettings().setJavaScriptEnabled(true); + mBinding.webview.getSettings().setUseWideViewPort(true); + mBinding.webview.getSettings().setDomStorageEnabled(true); + mBinding.webview.setWebContentsDebuggingEnabled(true); + // 设置 WebView 可以在 HTTPS 通道上加载 HTTP 资源,Android 4.4 后的暗坑 + // 因为 Android 4.4 后默认不允许在 HTTPS 通道上加载 HTTP 资源 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mBinding.webview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + } + mBinding.webview.getSettings().setTextZoom(100); + JsInterface jsInterface = new JsInterface(); + mBinding.webview.addJavascriptInterface(jsInterface, "nativeApp"); + mBinding.webview.setWebViewClient(new WebViewClient() { + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Logger.e("shouldOverrideUrlLoading--------" + url); + //modules/noble/paySuccess.html + //modules/noble/order.html?nobleIndex=1 // 获取上下文, H5PayDemoActivity为当前页面 + // ------ 对alipays:相关的scheme处理 ------- + // ------- 处理结束 ------- + + if (!(url.startsWith("http") || url.startsWith("https"))) { + return true; + } + + view.loadUrl(url); + return true; + } + + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { +// super.onReceivedSslError(view, handler, error); //一定要去掉 + // handler.cancel();// Android默认的处理方式 + handler.proceed();// 接受所有网站的证书 + // handleMessage(Message msg);// 进行其他处理 + } + + @Override + public void onPageFinished(WebView view, String url) { + Logger.e("onPageFinished--------" + url); + super.onPageFinished(view, url); + } + }); + // 设置Webview的user-agent + mBinding.webview.getSettings().setUserAgentString(mBinding.webview.getSettings().getUserAgentString() + " tutuAppAndroid erbanAppAndroid"); + } + + private void showFaceAnim(String url, boolean isSelf) { + + GlideApp.with(this) + .asBitmap() + .dontAnimate() + .dontTransform() + .load(url) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(Bitmap resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + ImageView imageView = new ImageView(PlayGameActivity.this); + imageView.setScaleType(ImageView.ScaleType.FIT_XY); + ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(UIUtil.dip2px(PlayGameActivity.this, 44) + , UIUtil.dip2px(PlayGameActivity.this, 44)); + imageView.setLayoutParams(layoutParams); + imageView.setImageBitmap(resource); + if (isSelf) { + imageView.setX(mBinding.ivAvatarLeft.getX() + UIUtil.dip2px(PlayGameActivity.this, 18)); + imageView.setY(mBinding.ivAvatarLeft.getY() + UIUtil.dip2px(PlayGameActivity.this, 8)); + } else { + imageView.setX(mBinding.ivAvatarRight.getX() + UIUtil.dip2px(PlayGameActivity.this, 18)); + imageView.setY(mBinding.ivAvatarRight.getY() + UIUtil.dip2px(PlayGameActivity.this, 8)); + } + mBinding.root.addView(imageView); + double a = new Random().nextDouble(); + float x = (float) (250 * Math.cos(a)); + float y = (float) (250 * Math.sin(a)); + + imageView.animate() + .translationX(isSelf ? imageView.getX() + x : imageView.getX() - x) + .translationY(isSelf ? imageView.getY() + y : imageView.getY() + y) + .setDuration(1000) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + mBinding.root.removeView(imageView); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + }) + .start(); + imageView.animate() + .alpha(0) + .setStartDelay(700) + .setDuration(300) + .start(); + return false; + } + }).submit(); + + } + + @Override + public void onBackPressed() { + if (isPlayer) { + new GameExitDialog(this, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.h5_gamepage_giveup_click, "认输退出"); + + mBinding.webview.loadUrl("javascript:surrender()"); + if (!isIm) { + GameModel.get().updateGameStatus(AuthModel.get().getCurrentUid(), + GameModel.SELECTING, "", "") + .subscribe(); + } + finish(); + }).openDialog(); + } else { + finish(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + + if (aiUid != 0 && AvRoomDataManager.get().isRoomOwner()) { + //游戏结束时把ai踢出房间 + RxBus.get().post(new AiPlayEndEvent(aiUid)); + } + if (isIm && !AvRoomDataManager.get().roomNoDestory) { + RtcEngineManager.get().leaveChannel(); + } + if (mBinding.webview != null) { + ViewParent parent = mBinding.webview.getParent(); + if (parent != null) { + ((ViewGroup) parent).removeView(mBinding.webview); + } + mBinding.webview.removeAllViews(); + mBinding.webview.destroy(); + } + ImGameMode.get().resetTime(); + + if (isPlayer && viewModel.adverseUserInfo.get() != null) { + ImGameMode.get().sendNotify(viewModel.adverseUserInfo.get().getUid() + "", PlayGameVm.LEAVE); + } + } + + private void shouResultDialog(GameResultInfo.ResultBean resultBean) { + GameResultDialog gameResultDialog = new GameResultDialog(this, resultBean, + viewModel); + gameResultDialog.setPub(getIntent().getBooleanExtra("isPub", false)); + gameResultDialog.setClickListner(url -> { + mBinding.webview.loadUrl(url); + if (!viewModel.gameVoice.get()) { + viewModel.gameVoice.set(!viewModel.gameVoice.get()); + } + }); + gameResultDialog.openDialog(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SelectFriendActivity.CODE_REQUEST_TO_SHARE_ROOM && + resultCode == Activity.RESULT_OK) { + String targetUid = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_UID); + String nick = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_NAME); + int sessionType = data.getIntExtra(SelectFriendActivity.EXTRA_SESSION_TYPE, SessionType.P2P); + IMNetEaseManager.get().sendSharingRoomMessage(sessionType, targetUid); + } + } + + class JsInterface { + + private boolean haveChangeWatch; + + @JavascriptInterface + public void onPKFinish(String json) { + LogUtil.e("onPKFinish" + json); + try { + GameResultInfo.ResultBean resultBean = JSON.parseObject(json, GameResultInfo.class).getResult(); + if (resultBean == null) { + return; + } + if (!isIm) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + if ((GameResultInfo.NOT_DRAW.equals(resultBean.getResultType()) && resultBean.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid()) + || aiUid != 0) { + viewModel.sendGameResult(json, msgId, roomInfo, resultBean); + } else if (GameResultInfo.DRAW.equals(resultBean.getResultType()) && resultBean.getUsers().get(0).getUid() == AuthModel.get().getCurrentUid()) { + viewModel.sendGameResult(json, msgId, roomInfo, resultBean); + } + } else { + if ((GameResultInfo.NOT_DRAW.equals(resultBean.getResultType()) && + resultBean.getWinners().get(0).getUid() == AuthModel.get().getCurrentUid())) { + GameModel.get().saveGameResult(json, msgId).subscribe(); + RxBus.get().post(new GameResultEvent(resultBean)); + } else if (GameResultInfo.DRAW.equals(resultBean.getResultType()) + && AuthModel.get().getCurrentUid() == channelId) { + GameModel.get().saveGameResult(json, msgId).subscribe(); + RxBus.get().post(new GameResultEvent(resultBean)); + } + } + if (isPlayer && !AvRoomDataManager.get().isCpRoom()) { + mBinding.webview.post(() -> shouResultDialog(resultBean)); + } else { + finish(); + } + } catch (Exception e) { + } + } + + @JavascriptInterface + public void onPKStart(String json) { + GameUidInfo urlInfo = JSON.parseObject(json, GameUidInfo.class); + if (urlInfo.getUidLeft() == AuthModel.get().getCurrentUid()) { + isPlayer = true; + viewModel.setRightUid(urlInfo.getUidRight()).subscribe(); + } else if (urlInfo.getUidRight() == AuthModel.get().getCurrentUid()) { + isPlayer = true; + viewModel.setRightUid(urlInfo.getUidLeft()).subscribe(); + } else { + viewModel.setLeftUid(urlInfo.getUidLeft()); + viewModel.setRightUid(urlInfo.getUidRight()).subscribe(); + } + runOnUiThread(() -> { + mBinding.webview.loadUrl("javascript:hideButton()"); + mBinding.ivChangeWatch.setVisibility(haveChangeWatch && !isPlayer ? View.VISIBLE : View.GONE); + }); + LogUtil.e("onPKStart" + json); + } + + @JavascriptInterface + public void onPKExceptionFinish(String json) { + LogUtil.e("onPKExceptionFinish" + json); + if (!isIm) { + GameModel.get().updateGameStatus(AuthModel.get().getCurrentUid(), + GameModel.SELECTING, "", "") + .subscribe(); + GameModel.get().sendCancelPrepare(); + } + PlayGameActivity.this.finish(); + } + + @JavascriptInterface + public void haveChangeWatch(boolean haveChangeWatch) { + this.haveChangeWatch = haveChangeWatch; + runOnUiThread(() -> mBinding.ivChangeWatch.setVisibility(haveChangeWatch && !isPlayer ? View.VISIBLE : View.GONE)); + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameVm.java b/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameVm.java new file mode 100644 index 000000000..da4f8510d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/PlayGameVm.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.avroom.game; + +import android.databinding.ObservableArrayList; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.text.TextUtils; +import android.view.View; + +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameAttachment; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.game.GameAttachInfo; +import com.yizhuan.xchat_android_core.room.game.GameEvent; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.net.URL; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +public class PlayGameVm extends BaseViewModel { + public static final int AGAIN = 1;//再来一局 + public static final int CHANGE_GAME = 2;//换个游戏 + public static final int AGAIN_REPONSED = 3;//同意再来一局 + public static final int LEAVE = 4;//离开 + public static final String FACE_URL = "faceUrl"; + + public ObservableField selfUserInfo = new ObservableField<>(); + public ObservableField adverseUserInfo = new ObservableField<>(); + + public ObservableBoolean isPraised = new ObservableBoolean(false); + public ObservableBoolean isMute = new ObservableBoolean(false); + public ObservableBoolean isRemoteMute = new ObservableBoolean(false); + public ObservableBoolean isOnMic = new ObservableBoolean(false); + + public ObservableBoolean gameVoice = new ObservableBoolean(true); + public ObservableBoolean watchLeft = new ObservableBoolean(true); + + + public ObservableArrayList faceList = new ObservableArrayList<>(); + public View.OnClickListener micClick = v -> { + RtcEngineManager.get().setMute(!RtcEngineManager.get().isMute); + isMute.set(RtcEngineManager.get().isMute); + }; + + public View.OnClickListener voiceClick = v -> { + RtcEngineManager.get().setRemoteMute(!RtcEngineManager.get().isRemoteMute); + isRemoteMute.set(RtcEngineManager.get().isRemoteMute); + }; + + public PlayGameVm() { + selfUserInfo.set(UserModel.get().getCacheLoginUserInfo()); + isOnMic.set(AvRoomDataManager.get().isOwnerOnMic()); + isMute.set(RtcEngineManager.get().isMute); + isRemoteMute.set(RtcEngineManager.get().isRemoteMute); + GameModel.get().getGameFace() + .subscribe(strings -> { + faceList.addAll(strings); + }); + } + + public Single setRightUid(long uid) { + return UserModel.get().getUserInfo(uid) + .doOnSuccess(userInfo -> adverseUserInfo.set(userInfo)); + } + + public void setLeftUid(long uid) { + UserModel.get().getUserInfo(uid) + .subscribe(userInfo -> selfUserInfo.set(userInfo)); + } + + public void sendGameResult(String json, String msgId, RoomInfo roomInfo, GameResultInfo.ResultBean resultBean) { + GameModel.get().updateGameStatus(AuthModel.get().getCurrentUid(), + GameModel.NO_STATUS, "", "", false) + .subscribe(); + GameModel.get().saveGameResult(json, msgId).subscribe(); + + GameAttachment gameAttachment = new GameAttachment(CustomAttachment.CUSTOM_MSG_GAME, CustomAttachment.CUSTOM_MSG_GAME_END); + GameAttachInfo attachInfo = new GameAttachInfo(); + attachInfo.setNick(UserModel.get().getCacheLoginUserInfo().getNick()); + attachInfo.setGameResultInfo(resultBean); + gameAttachment.setGameInfo(attachInfo); + ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomCustomMessage( + // 聊天室id + roomInfo.getRoomId() + "", + gameAttachment + ); + + //发送消息 + IMNetEaseManager.get() + .sendChatRoomMessage(message, new CallBack() { + @Override + public void onSuccess(ChatRoomMessage data) { + RxBus.get().post(new GameEvent().setType(GameEvent.GAME_END).setResultInfo(resultBean)); + IMNetEaseManager.get().addMessagesImmediately(data); + } + + @Override + public void onFail(int code, String error) { + } + }); + } + + public void isPraised() { + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), adverseUserInfo.get().getUid()) + .subscribe(aBoolean -> { + isPraised.set(aBoolean); + }); + } + + public void sendNotifyMsg(int index) { + // 发送自定义系统通知通知对方状态改变 + + if (adverseUserInfo.get() == null || ListUtils.isListEmpty(faceList)) return; + CustomNotification notification = new CustomNotification(); + notification.setSessionId(adverseUserInfo.get().getUid() + ""); + notification.setSessionType(SessionTypeEnum.P2P); + + JSONObject json = new JSONObject(); + json.put(FACE_URL, faceList.get(index)); + notification.setContent(json.toString()); + + NIMClient.getService(MsgService.class).sendCustomNotification(notification); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/giftvalue/GiftValueDialogUiHelper.java b/app/src/main/java/com/yizhuan/erban/avroom/giftvalue/GiftValueDialogUiHelper.java new file mode 100644 index 000000000..6b4710ee1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/giftvalue/GiftValueDialogUiHelper.java @@ -0,0 +1,131 @@ +package com.yizhuan.erban.avroom.giftvalue; + +import android.content.Context; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +/** + * 礼物值的弹框处理 + * create by lvzebiao @2019/4/12 + */ +public class GiftValueDialogUiHelper { + + public final static int TYPE_CLOSE_SHOW_GIFT_VALUE = 1; + + /** + * 主动下麦 + */ + public final static int TYPE_DOWN_MIC = 2; + + /** + * 管理踢人下麦 + */ + public final static int TYPE_KICK_DOWN_MIC = 3; + + /** + * 换麦 + */ + public final static int TYPE_CHANGE_MIC = 4; + + /** + * 如果此key保留的值为ture,关闭礼物值模式的时候,需要弹框确认 + */ + public final static String KEY_NEED_DIALOG_WHEN_CLOSE_GIFT_VALUE_MODEL = + "need_dialog_when_close_gift_value_model"; + + /** + * 主动下麦的情况 + */ + public final static String KEY_DOWN_MIC_NEED_DIALOG_TIPS = "down_mic_need_dialog_tips"; + + /** + * 踢人下麦的情况 + */ + public final static String KEY_KICK_DOWN_MIC_NEED_DIALOG_TIPS = "kick_down_mic_need_dialog_tips"; + + /** + * 换麦 + */ + public final static String KEY_CHANGE_MIC_NEED_DIALOG_TIPS = "change_mic_need_dialog_tips"; + + private static final class Helper { + public static final GiftValueDialogUiHelper INSTANCE = new GiftValueDialogUiHelper(); + } + + public static GiftValueDialogUiHelper get() { + return Helper.INSTANCE; + } + + public boolean isNeedConfirmDialog(int type) { + if (type == TYPE_CLOSE_SHOW_GIFT_VALUE) { + Boolean value = (Boolean) SharedPreferenceUtils.get(KEY_NEED_DIALOG_WHEN_CLOSE_GIFT_VALUE_MODEL, true); + return value != null && value; + } else if (type == TYPE_DOWN_MIC) { + Boolean value = (Boolean) SharedPreferenceUtils.get(KEY_DOWN_MIC_NEED_DIALOG_TIPS, true); + return value != null && value; + } else if (type == TYPE_KICK_DOWN_MIC) { + Boolean value = (Boolean) SharedPreferenceUtils.get(KEY_KICK_DOWN_MIC_NEED_DIALOG_TIPS, true); + return value != null && value; + } else if (type == TYPE_CHANGE_MIC) { + Boolean value = (Boolean) SharedPreferenceUtils.get(KEY_CHANGE_MIC_NEED_DIALOG_TIPS, true); + return value != null && value; + } + return true; + } + + public boolean isNeedKickDownMicDialog() { + return AvRoomDataManager.get().isShowGiftValue() && isNeedConfirmDialog(TYPE_KICK_DOWN_MIC); + } + + /** + * 换麦时,是否需要弹窗提示 + */ + public boolean isNeedChangeMicDialog() { + return AvRoomDataManager.get().isShowGiftValue() && isNeedConfirmDialog(TYPE_CHANGE_MIC); + } + + public void showGiftValueDialog(Context context, DialogManager dialogManager, int type, + DialogManager.OkCancelDialogListener l) { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + String message = ""; + if (type == TYPE_CLOSE_SHOW_GIFT_VALUE) { + message = context.getString(R.string.close_show_gift_value_tips); + } else if (type == TYPE_DOWN_MIC) { + message = context.getString(R.string.down_mic_tips); + } else if (type == TYPE_KICK_DOWN_MIC) { + message = context.getString(R.string.kick_down_mic_tips); + } else if (type == TYPE_CHANGE_MIC) { + message = context.getString(R.string.change_mic_tips); + } + final DialogManager finalDialogManager = dialogManager; + dialogManager.showOkCancelSwitchDialog(message, () -> { + if (l != null) { + l.onOk(); + } + boolean isTrue = finalDialogManager.isOpenSwitch(); + if (!isTrue) { + return; + } + if (type == TYPE_CLOSE_SHOW_GIFT_VALUE) { + SharedPreferenceUtils.put(KEY_NEED_DIALOG_WHEN_CLOSE_GIFT_VALUE_MODEL, false); + } else if (type == TYPE_DOWN_MIC) { + SharedPreferenceUtils.put(KEY_DOWN_MIC_NEED_DIALOG_TIPS, false); + } else if (type == TYPE_KICK_DOWN_MIC) { + SharedPreferenceUtils.put(KEY_KICK_DOWN_MIC_NEED_DIALOG_TIPS, false); + } else if (type == TYPE_CHANGE_MIC) { + SharedPreferenceUtils.put(KEY_CHANGE_MIC_NEED_DIALOG_TIPS, false); + } + }); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/helper/RoomViewModel.java b/app/src/main/java/com/yizhuan/erban/avroom/helper/RoomViewModel.java new file mode 100644 index 000000000..d66eabe44 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/helper/RoomViewModel.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.avroom.helper; + +import android.arch.lifecycle.MutableLiveData; +import android.arch.lifecycle.ViewModel; + +import lombok.Getter; + +/** + * 房间数据的一些管理 + * Created by lvzebiao on 2018/11/16. + */ + +public class RoomViewModel extends ViewModel { + + @Getter + private final MutableLiveData isKtvModel = new MutableLiveData<>(); + + @Getter + private final MutableLiveData isGameModel = new MutableLiveData<>(); + + public void init() { + isKtvModel.setValue(false); + isGameModel.postValue(false); + } + + @Override + protected void onCleared() { + super.onCleared(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KickDownMicEvent.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KickDownMicEvent.java new file mode 100644 index 000000000..d5b506dde --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KickDownMicEvent.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.avroom.ktv; + +public class KickDownMicEvent { + + private String account; + private String nick; + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getNick() { + return nick; + } + + public void setNick(String nick) { + this.nick = nick; + } + + public KickDownMicEvent(String account, String nick) { + this.account = account; + this.nick = nick; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvCommitErrorDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvCommitErrorDialog.java new file mode 100644 index 000000000..0b0609636 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvCommitErrorDialog.java @@ -0,0 +1,107 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogKtvCommitErrorBinding; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + + +@ActLayoutRes(R.layout.dialog_ktv_commit_error) +public class KtvCommitErrorDialog extends BaseBindingDialog implements View.OnClickListener { + + private String[] errs = new String[]{ + "歌词有误", + "歌词与伴奏有错位", + "原唱与伴奏不匹配", + "伴奏有误", + "伴奏音质差", + "MV质量差", + "无法播放", + "其他"}; + private int musicId; + + public KtvCommitErrorDialog(Context context, int musicId) { + super(context, R.style.TranslucentNoTitle); + this.musicId = musicId; + } + + public static KtvCommitErrorDialog newInstance(Context context, int musicId) { + return new KtvCommitErrorDialog(context, musicId); + } + + @Override + protected void init() { + binding.setClick(this); + TextView checkBox; + for (String err : errs) { + checkBox = (TextView) getLayoutInflater().inflate(R.layout.item_ktv_err, null); + checkBox.setText(err); + binding.llErrs.addView(checkBox, createLayoutParams()); + checkBox.setOnClickListener(v -> { + v.setSelected(!v.isSelected()); + updateCommitStatus(); + }); + } + } + + private void updateCommitStatus() { + boolean clickable = false; + for (int i = 0; i < binding.llErrs.getChildCount(); i++) { + if (binding.llErrs.getChildAt(i).isSelected()) { + clickable = true; + break; + } + } + binding.tvSure.setClickable(clickable); + binding.tvSure.setSolid(clickable ? context.getResources().getColor(R.color.appColor) : + context.getResources().getColor(R.color.color_FFC4A7)); + } + + private LinearLayout.LayoutParams createLayoutParams() { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, UIUtil.dip2px(context, 38)); + layoutParams.setMarginStart(UIUtil.dip2px(context, 15)); + layoutParams.setMarginEnd(UIUtil.dip2px(context, 15)); + return layoutParams; + } + + public void onClick(View view) { + TextView checkBox; + switch (view.getId()) { + case R.id.tv_sure: + StringBuilder errMsg = new StringBuilder(); + for (int i = 0; i < binding.llErrs.getChildCount(); i++) { + checkBox = (TextView) binding.llErrs.getChildAt(i); + if (checkBox.isSelected()) { + if (i != 0) errMsg.append(","); + errMsg.append(checkBox.getText().toString()); + } + } + if (TextUtils.isEmpty(errMsg.toString())) { + SingleToastUtil.showToast("请至少选择一种错误!"); + return; + } + KtvMusicManager.INSTANCE.musicError(musicId, errMsg.toString()) + .subscribe(s -> { + closeDialog(); + SingleToastUtil.showToast("提交成功!"); + }); + break; + default: + break; + } + } + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvHelper.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvHelper.java new file mode 100644 index 000000000..0cf65e758 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvHelper.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.im.custom.bean.MusicInfoAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; + +import io.reactivex.Single; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_KTV; + + +public class KtvHelper { + + public static final int NO_NET = 1; + public static final int NO_SONG = 2; + public static final int NO_ROOM = 3; + public static final int NO_DATA = 4; + public static View createKtvEmptyView(Context context,int type ) { + if (!NetworkUtils.isNetworkAvailable(context)) type = NO_NET; + String hint =""; + int resId = 0; + switch (type) { + case NO_NET: + hint = "网络异常,加载失败"; + resId = R.drawable.icon_common_failure; + break; + case NO_DATA: + hint = "搜索无歌曲"; + resId = R.drawable.icon_common_failure; + break; + case NO_ROOM: + hint = "无房间开唱"; + resId = R.drawable.icon_common_failure; + break; + case NO_SONG: + hint = "无点唱歌曲"; + resId = R.drawable.icon_common_failure; + break; + } + View view = LayoutInflater.from(context).inflate(R.layout.fragment_no_data_large_iv, null); + view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + ((TextView)view.findViewById(R.id.no_data_text)).setText(hint); + ((ImageView)view.findViewById(R.id.no_data_icon)).setImageResource(resId); + return view; + } + + public static Single sendChatRoomMusicMessage(int sub, MusicInfo musicInfo) { + MusicInfoAttachment musicInfoAttachment = new MusicInfoAttachment(CUSTOM_MSG_KTV, sub); + if (musicInfo != null) { + musicInfo.setOperationNick(UserUtils.getUserInfo().getNick()); + musicInfo.setOperationUid(UserUtils.getUserUid()); + musicInfoAttachment.setMusicInfo(musicInfo); + } + final ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomCustomMessage( + UserUtils.getCurrentRoomId() + "", musicInfoAttachment); + return IMNetEaseManager.get().sendChatRoomMessage(message, false); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvMusicManager.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvMusicManager.java new file mode 100644 index 000000000..0bfa79351 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvMusicManager.java @@ -0,0 +1,211 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.coorchice.library.utils.LogUtils; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; + +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.bean.RoomMusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.room.ktv.event.MusicCountEvent; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_DELETE_USER_ALL; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_FINISH; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_SWITCH; + +public enum KtvMusicManager { + INSTANCE; + private final ArrayList mData = new ArrayList<>(); + private MusicInfo currMusic; + private double currPlayPos; + private Disposable ktvDisposable; + private Disposable startDisposable; + private Disposable dataDisposable; + private Disposable switchDisposable; + + public void reset() { + dispose(ktvDisposable); + ktvDisposable = RxBus.get().toFlowable(KtvEvent.class) + .subscribe(this::handleKtvEvent); + initData(); + } + + private void initData() { + dispose(dataDisposable); + dataDisposable = KtvModel.get().getRoomMusic(UserUtils.getCurrentRoomUid()) + .compose(RxHelper.handleBeanData()) + .doOnSuccess(this::setData) + .filter(roomMusicInfo -> !AvRoomDataManager.get().isOwnerOnMic() && !ListUtils.isListEmpty(roomMusicInfo.getUserChooseMusicVos())) + .toObservable() + .flatMap(roomMusicInfo -> Observable.fromIterable(roomMusicInfo.getUserChooseMusicVos())) + .filter(musicInfo -> musicInfo.getUid() == UserUtils.getUserUid()) + .firstElement() + .toSingle() + .flatMap(musicInfo -> deleteUserAllChooseMusic()) + .subscribe(s -> { }, e -> { }); + } + + public void setData(RoomMusicInfo roomMusicInfo) { + mData.clear(); + currMusic = roomMusicInfo.getSingingMusicVo(); + if (!ListUtils.isListEmpty(roomMusicInfo.getUserChooseMusicVos())) { + mData.addAll(roomMusicInfo.getUserChooseMusicVos()); + } + RxBus.get().post(KtvEvent.newInstance(KtvEvent.MUSIC_UPDATE, null)); + RxBus.get().post(new MusicCountEvent(mData.size())); + } + + //处理KTV相关的各种事件 + private void handleKtvEvent(KtvEvent ktvEvent) { + LogUtils.d(ktvEvent.toString()); + MusicInfo musicInfo = ktvEvent.getMusicInfo(); + switch (ktvEvent.getType()) { + case KtvEvent.SWITCH_MUSIC: + if (currMusic != null) mData.remove(currMusic); + currMusic = musicInfo; + RtcEngineManager.get().stopPush(); + startMv(musicInfo); + break; + case KtvEvent.ADD_MUSIC: + if (musicInfo != null) { + mData.add(musicInfo); + } + break; + case KtvEvent.POP_MUSIC: + if (musicInfo != null) { + mData.remove(musicInfo); + } + break; + case KtvEvent.NO_MUSIC: + case KtvEvent.CLOSE_KTV_MODEL: + RtcEngineManager.get().stopPush(); + RtcEngineManager.get().setLive(false); + mData.clear(); + currMusic = null; + break; + case KtvEvent.DELETE_USER_CHOOSE_MUSIC: + if (musicInfo != null) { + mData.remove(musicInfo); + } + case KtvEvent.DELETE_USER_ALL_MUSIC: + if (musicInfo != null) { + Iterator iterator = mData.iterator(); + while (iterator.hasNext()) { + if (iterator.next().getUid() == musicInfo.getUid()) { + iterator.remove(); + } + } + } + break; + case KtvEvent.MUSIC_COMPLETE: + LogUtils.d("MUSIC_COMPLETE"); + // if (RtcEngineManager.get().isPush()) switchSong(false); + break; + default: + break; + } + RxBus.get().post(new MusicCountEvent(mData.size())); + } + + private void startMv(MusicInfo musicInfo) { + if (musicInfo == null ||UserUtils.getUserUid() != musicInfo.getUid()) return; + dispose(startDisposable); + currPlayPos = -1; + startDisposable = Observable.just(0) + .subscribeOn(Schedulers.io()) + .delay(2, TimeUnit.SECONDS) + .takeUntil(integer -> !KtvView.isShowPrepare || UserUtils.getUserUid() != getCurrMusic().getUid())//准备中下麦处理 + .doOnNext(integer -> RtcEngineManager.get().startMv(musicInfo.getMusicUrl())) + .flatMap(integer -> Observable.interval(0, 1, TimeUnit.SECONDS)) + .observeOn(AndroidSchedulers.mainThread()) + .takeUntil(aLong -> !RtcEngineManager.get().isPush()) + .filter(aLong -> (RtcEngineManager.get().getPlayPos() > 0.99d || + (RtcEngineManager.get().getPlayPos() > 0.94d && RtcEngineManager.get().isPlaying() && + currPlayPos == (currPlayPos = RtcEngineManager.get().getPlayPos())))) + .take(1) + .subscribe(aLong -> switchSong(false)); + + } + + public Single addMusic(MusicInfo musicInfo) { + return KtvModel.get().chooseMusic(musicInfo.getMusicId(), UserUtils.getUserUid(), UserUtils.getCurrentRoomUid()); + } + + public Single popMusic(MusicInfo musicInfo) { + return KtvModel.get().popMusic(musicInfo.getMusicId(), musicInfo.getUid(), UserUtils.getCurrentRoomUid()); + } + + public Single switchMusic() { + return KtvModel.get().switchMusic(UserUtils.getCurrentRoomUid()); + } + + public Single deleteUserChooseMusic(MusicInfo musicInfo) { + return KtvModel.get().deleteUserChooseMusic(musicInfo.getMusicId(), musicInfo.getUid(), UserUtils.getCurrentRoomUid()); + } + + public Single deleteRoomAllChooseMusic() { + return KtvModel.get().deleteRoomAllChooseMusic(UserUtils.getCurrentRoomUid()); + } + + public Single deleteUserAllChooseMusic() { + return deleteUserAllChooseMusic(UserUtils.getCurrentRoomUid()); + } + + public Single deleteUserAllChooseMusic(long roomUid) { + return KtvModel.get() + .deleteUserAllChooseMusic(UserUtils.getUserUid(), roomUid) + .doOnSuccess(s -> KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_DELETE_USER_ALL, null) + .subscribe(chatRoomMessage -> RxBus.get().post(KtvEvent.newInstance(KtvEvent.DELETE_USER_ALL_MUSIC, null)))); + } + + public void switchSong(boolean isSwitch) { + MusicInfo musicInfo = getCurrMusic(); + dispose(switchDisposable); + switchDisposable = KtvMusicManager.INSTANCE.switchMusic() + .flatMap(s -> KtvHelper.sendChatRoomMusicMessage(isSwitch ? CUSTOM_MSG_SUB_KTV_SWITCH : CUSTOM_MSG_SUB_KTV_FINISH, musicInfo)) + .subscribe(chatRoomMessage -> IMNetEaseManager.get().addMessages(chatRoomMessage)); + } + + public Single musicError(int musicId,String errorMsg) { + return KtvModel.get().musicError(musicId, UserUtils.getUserUid(),errorMsg); + } + + + private void dispose(@Nullable Disposable disposable) { + if (disposable != null) disposable.dispose(); + } + + @NonNull + public List getMusicList() { + return mData; + } + + @NonNull + public MusicInfo getCurrMusic() { + return currMusic == null ? new MusicInfo() : currMusic; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListActivity.java new file mode 100644 index 000000000..dd4148a1c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListActivity.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.Fragment; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.common.ViewPagerAdapter; +import com.yizhuan.erban.databinding.ActivityKtvRoomListBinding; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.CommonUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + *

KTV房间列表

+ * + */ +@ActLayoutRes(R.layout.activity_ktv_room_list) +public class KtvRoomListActivity extends BaseBindingActivity implements CarMagicIndicator.OnItemSelectListener { + + public static void start(Context context) { + if (CommonUtils.isFastDoubleClick(500)) return; + Intent starter = new Intent(context, KtvRoomListActivity.class); + //starter.putExtra(); + context.startActivity(starter); + } + @Override + protected void init() { + List list = new ArrayList<>(); + list.add(KtvRoomListFragment.newInstance(KtvRoomListFragment.NEW)); + list.add(KtvRoomListFragment.newInstance(KtvRoomListFragment.HOT)); + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(1, "最新")); + tabInfoList.add(new TabInfo(2, "最热")); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mBinding.viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mBinding.viewIndicator, mBinding.viewPager); + String[] titles = {"最新", "最热"}; + mBinding.setClick(this); + initTitleBar("KTV房"); + // mBinding.tabLayout.setupWithViewPager(mBinding.viewPager); + // mBinding.tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER); + mBinding.viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), list, titles)); + } + + @Override + public void onItemSelect(int position) { + mBinding.viewPager.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListFragment.java new file mode 100644 index 000000000..b4d039b33 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListFragment.java @@ -0,0 +1,108 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; + +import com.chad.library.adapter.base.BaseQuickAdapter; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.databinding.FragmentRecyclerViewBindNoBgBinding; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.xchat_android_core.room.ktv.bean.KtvRoomInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.fragment_recycler_view_bind_no_bg) +public class KtvRoomListFragment extends BaseBindingFragment implements SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + private BaseAdapter adapter; + private KtvRoomListVm ktvRoomListVm; + public static final int NEW = 1; + public static final int HOT = 2; + + @Override + public void initiate() { + int type = getArguments().getInt("type", HOT); + ktvRoomListVm = new KtvRoomListVm(mBinding, type); + adapter = new BaseAdapter<>(R.layout.list_item_ktv_room, BR.ktvRoomInfo); + adapter.setEmptyView(KtvHelper.createKtvEmptyView(getContext(),KtvHelper.NO_ROOM )); + mBinding.setViewmodel(ktvRoomListVm); + mBinding.recyclerView.setLayoutManager(new GridLayoutManager(mContext,2)); + mBinding.recyclerView.setAdapter(adapter); + mBinding.swipeRefresh.setOnRefreshListener(this); + loadData(false); + adapter.setOnLoadMoreListener(this, mBinding.recyclerView); + adapter.setOnItemClickListener((adapter, view, position) ->{ + AVRoomActivity.start(getActivity(), ((KtvRoomInfo)adapter.getData().get(position)).getRoomUid()); +// getActivity().finish(); + } + ); + + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ConnectiveChangedReceiver.getInstance().registerConnectiveChange(this); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + ConnectiveChangedReceiver.getInstance().unRegisterConnectiveChange(this); + } + + private void loadData(boolean isLoad) { + ktvRoomListVm.loadData(isLoad) + .compose(bindToLifecycle()) + .doAfterTerminate(() -> { + if (adapter.getItemCount() == 0) showNoData(); + else hideStatus(); + }).subscribe(); + } + + public static KtvRoomListFragment newInstance(int type) { + Bundle args = new Bundle(); + args.putInt("type", type); + KtvRoomListFragment fragment = new KtvRoomListFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onReloadData() { + loadData(false); + showLoading(); + } + + @Override + public void onRefresh() { + loadData(false); + } + + @Override + public void onLoadMoreRequested() { + loadData(true); + } + + @Override + public void change2NoConnection() { + super.change2NoConnection(); + if (adapter!=null) adapter.setEmptyView(KtvHelper.createKtvEmptyView(getContext(),KtvHelper.NO_NET)); + + } + + @Override + public void connectiveMobileData() { + connectiveWifi(); + } + + @Override + public void connectiveWifi() { + if (adapter!=null) adapter.setEmptyView(KtvHelper.createKtvEmptyView(getContext(),KtvHelper.NO_ROOM)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListVm.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListVm.java new file mode 100644 index 000000000..970b6bcc4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvRoomListVm.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.avroom.ktv; + + +import com.yizhuan.erban.base.BaseListViewModel; +import com.yizhuan.erban.base.BaseMsListViewModel; +import com.yizhuan.erban.databinding.FragmentRecyclerViewBindNoBgBinding; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.KtvRoomInfo; + +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by huangmeng1 on 2018/5/9. + */ + +public class KtvRoomListVm extends BaseMsListViewModel { + + private int sortType; + + public KtvRoomListVm(FragmentRecyclerViewBindNoBgBinding mBinding, int sortType) { + super(mBinding); + this.sortType = sortType; + pageSize = 20; + } + + @Override + public Single>> getSingle() { + return KtvModel.get().getKtvRooms(sortType, page, pageSize); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongActivity.java new file mode 100644 index 000000000..b77dcbfe3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongActivity.java @@ -0,0 +1,224 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.coorchice.library.SuperTextView; +import com.google.android.flexbox.FlexboxLayout; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.databinding.ActivityKtvSearchSongBinding; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.room.ktv.event.MusicCountEvent; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.CommonUtils; + +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + *

KTV搜索歌曲

+ * + */ + +@ActLayoutRes(R.layout.activity_ktv_search_song) +public class KtvSearchSongActivity extends BaseBindingActivity implements TextWatcher, BaseQuickAdapter.RequestLoadMoreListener, BaseQuickAdapter.OnItemClickListener, TextView.OnEditorActionListener { + private KtvSearchSongVm vm; + private BaseAdapter adapter; + + + public static void start(Context context) { + if (CommonUtils.isFastDoubleClick(500)) return; + Intent starter = new Intent(context, KtvSearchSongActivity.class); + //starter.putExtra(); + context.startActivity(starter); + } + + @SuppressLint("CheckResult") + @Override + protected void init() { + initTitleBar("点歌台"); + vm = new KtvSearchSongVm(mBinding); + mBinding.setViewModel(vm); + mBinding.setClick(this); + mBinding.swipeRefresh.setEnabled(false); + mBinding.edtSearch.addTextChangedListener(this); + adapter = new BaseAdapter<>(R.layout.list_item_ktv_search, BR.musicInfo); + adapter.setOnLoadMoreListener(this, mBinding.recyclerView); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context)); + mBinding.recyclerView.setAdapter(adapter); + adapter.setOnItemClickListener(this); + adapter.setEmptyView(KtvHelper.createKtvEmptyView(context, KtvHelper.NO_DATA)); + mBinding.edtSearch.setOnEditorActionListener(this); + if (vm.getHistoryList().size() == 0) { + mBinding.ivClearHistory.setVisibility(View.INVISIBLE); + } else { + for (String item : vm.getHistoryList()) { + mBinding.fblHistory.addView(createSearchItem(item), createLayoutParams()); + } + } + mBinding.tvSongCount.setText("已点" + KtvMusicManager.INSTANCE.getMusicList().size()); + RxBus.get().toFlowable(KtvEvent.class) + .compose(bindToLifecycle()) + .filter(ktvEvent -> ktvEvent.getType() == KtvEvent.ADD_MUSIC_BY_USER) + .subscribe(ktvEvent -> finish()); + RxBus.get().toFlowable(MusicCountEvent.class) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(musicCountEvent -> mBinding.tvSongCount.setText("已点" + musicCountEvent.getCount())); + } + + private SuperTextView createSearchItem(String text) { + SuperTextView textView = (SuperTextView) LayoutInflater.from(context).inflate(R.layout.item_ktv_search_history, null); + textView.setText(text); + textView.setMaxLines(1); + textView.setOnClickListener(v -> { + mBinding.edtSearch.setText(text); + mBinding.edtSearch.setSelection(mBinding.edtSearch.getText().toString().length()); + loadData(text); + }); + return textView; + } + + private FlexboxLayout.LayoutParams createLayoutParams() { + FlexboxLayout.LayoutParams layoutParams = new FlexboxLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, UIUtil.dip2px(this, 28)); + layoutParams.setMargins(0, 0, UIUtil.dip2px(this, 8), UIUtil.dip2px(this, 10)); + return layoutParams; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_search: + loadData(mBinding.edtSearch.getText().toString()); + break; + case R.id.iv_clear_history: + mBinding.fblHistory.removeAllViews(); + mBinding.ivClearHistory.setVisibility(View.INVISIBLE); + SharedPreferenceUtils.remove("ktv_history"); + break; + + case R.id.ib_clear_edt: + mBinding.edtSearch.setText(""); + break; + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + mBinding.recyclerView.setVisibility(View.GONE); + mBinding.llHistory.setVisibility(View.VISIBLE); + } + + } + + private void loadData(String searchKey) { + if (TextUtils.isEmpty(searchKey)) { + toast("请输入搜索关键字~"); + return; + } + hideIME(); + mBinding.recyclerView.setVisibility(View.VISIBLE); + mBinding.llHistory.setVisibility(View.GONE); + if (vm.addHistory(searchKey)) { + if (mBinding.ivClearHistory.getVisibility() == View.INVISIBLE) { + mBinding.ivClearHistory.setVisibility(View.VISIBLE); + } + if (mBinding.fblHistory.getChildCount() == 12) mBinding.fblHistory.removeViewAt(11); + mBinding.fblHistory.addView(createSearchItem(searchKey), 0, createLayoutParams()); + } + vm.setSearchKey(searchKey); + vm.loadData(this, false); + } + + @Override + public void onLoadMoreRequested() { + vm.loadData(this, true); + } + + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + if (CommonUtils.isFastDoubleClick(500)) return; + if (AvRoomDataManager.get().isOnMic(UserUtils.getUserUid())) { + KtvSelectSongDialog.newInstance(context, this.adapter.getData().get(position)) + .openDialog(); + } else { + getDialogManager().showOkDialog("只有麦上用户才可以点歌哦~"); + } + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_SEARCH + || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode() && KeyEvent.ACTION_DOWN == event.getAction())) { + loadData(mBinding.edtSearch.getText().toString()); + return true; + } + return false; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ConnectiveChangedReceiver.getInstance().registerConnectiveChange(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + ConnectiveChangedReceiver.getInstance().unRegisterConnectiveChange(this); + } + + @Override + public void change2NoConnection() { + super.change2NoConnection(); + if (adapter!=null) + adapter.setEmptyView(KtvHelper.createKtvEmptyView(context,KtvHelper.NO_NET)); + } + + @Override + public void connectiveMobileData() { + connectiveWifi(); + } + + @Override + public void connectiveWifi() { + if (adapter!=null) + adapter.setEmptyView(KtvHelper.createKtvEmptyView(context,KtvHelper.NO_DATA)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongVm.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongVm.java new file mode 100644 index 000000000..95043c670 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSearchSongVm.java @@ -0,0 +1,59 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import com.yizhuan.erban.base.BaseMsListViewModel; +import com.yizhuan.erban.databinding.ActivityKtvSearchSongBinding; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; + +public class KtvSearchSongVm extends BaseMsListViewModel { + + private String searchKey; + + public KtvSearchSongVm(ActivityKtvSearchSongBinding mBinding) { + super(mBinding); + } + + public void setSearchKey(String searchKey) { + this.searchKey = searchKey; + } + + @Override + public Single>> getSingle() { + return KtvModel.get().searchMusic(searchKey, page, pageSize); + } + + + public boolean addHistory(String searchKey) { + if (TextUtils.isEmpty(searchKey)) return false; + List historyList = getHistoryList(); + if (!historyList.contains(searchKey)) { + if (historyList.size() > 11) historyList.remove(11); + historyList.add(0, searchKey); + SharedPreferenceUtils.put("ktv_history", new Gson().toJson(historyList)); + return true; + } + return false; + } + + public List getHistoryList() { + String historys = (String) SharedPreferenceUtils.get("ktv_history", ""); + List historyList = new ArrayList<>(); + if (!TextUtils.isEmpty(historys)) { + historyList.addAll(new Gson().fromJson(historys, new TypeToken>() { + }.getType())); + } + return historyList; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongActivity.java new file mode 100644 index 000000000..0bb5c451d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongActivity.java @@ -0,0 +1,106 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityKtvSelectSongBinding; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.MusicCountEvent; +import com.yizhuan.xchat_android_core.super_admin.SaConstant; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.CommonUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + *

KTV点歌台

+ * + */ + +@ActLayoutRes(R.layout.activity_ktv_select_song) +public class KtvSelectSongActivity extends BaseBindingActivity implements BaseQuickAdapter.RequestLoadMoreListener, BaseQuickAdapter.OnItemClickListener { + private KtvSelectSongVm vm; + private BaseAdapter adapter; + + public static void start(Context context, boolean isHint) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + if (CommonUtils.isFastDoubleClick(500)) return; + if (!AvRoomDataManager.get().isOnMic(UserUtils.getUserUid()) && isHint) { + new DialogManager(context).showOkDialog("只有麦上用户才可以点歌哦~"); + return; + } + Intent starter = new Intent(context, KtvSelectSongActivity.class); + // starter.putExtra(); + context.startActivity(starter); + } + + + @SuppressLint("CheckResult") + @Override + protected void init() { + initTitleBar("点歌台"); + vm = new KtvSelectSongVm(mBinding); + mBinding.setViewModel(vm); + mBinding.setClick(this); + adapter = new BaseAdapter<>(R.layout.list_item_ktv_select, BR.musicInfo); + adapter.setOnLoadMoreListener(this, mBinding.recyclerView); + mBinding.swipeRefresh.setEnabled(false); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); + mBinding.recyclerView.setAdapter(adapter); + vm.loadData(this, false); + adapter.setOnItemClickListener(this); + mBinding.stvKtvSong.setText("已点" + KtvMusicManager.INSTANCE.getMusicList().size()); + RxBus.get().toFlowable(MusicCountEvent.class) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(musicCountEvent -> mBinding.stvKtvSong.setText("已点" + musicCountEvent.getCount())); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.container_search: + KtvSearchSongActivity.start(context); + break; + case R.id.stv_ktv_song: + KtvSongListActivity.start(context, true); + break; + } + } + + @Override + public void onLoadMoreRequested() { + vm.loadData(this, true); + } + + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + if (CommonUtils.isFastDoubleClick(500)) return; + if (!AvRoomDataManager.get().isOnMic(UserUtils.getUserUid())) { + getDialogManager() + .showOkDialog("只有麦上用户才可以点歌喔~"); + return; + } + KtvSelectSongDialog.newInstance(context, (MusicInfo) adapter.getData().get(position)) + + .openDialog(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongDialog.java new file mode 100644 index 000000000..da7443e2a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongDialog.java @@ -0,0 +1,91 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.content.Context; +import android.text.style.ForegroundColorSpan; +import android.view.View; + + +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.DialogKtvSelectSongBinding; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_ADD; + + +@ActLayoutRes(R.layout.dialog_ktv_select_song) +public class KtvSelectSongDialog extends BaseBindingDialog implements View.OnClickListener { + private MusicInfo musicInfo; + + public KtvSelectSongDialog(Context context, MusicInfo musicInfo) { + super(context, R.style.MyAlertDialogStyle); + this.musicInfo = musicInfo; + } + + public static KtvSelectSongDialog newInstance(Context context, MusicInfo musicInfo) { + return new KtvSelectSongDialog(context, musicInfo); + } + + @Override + protected void init() { + binding.setMusicInfo(musicInfo); + binding.setClick(this); + + MessageView.SpannableBuilder builder = new MessageView.SpannableBuilder(binding.tvUploader) + .append("感谢 ") + .append(musicInfo.getUploader(), new ForegroundColorSpan(context.getResources().getColor(R.color.appColor))) + .append(" 上传"); + binding.tvUploader.setText(builder.build()); + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.tv_cancel: + closeDialog(); + break; + case R.id.tv_sure: + if (!RtcEngineManager.get().isOpenKtv()){ + SingleToastUtil.showToast("管理已经已经关闭KTV模式哦~~"); + return; + } + if (!AvRoomDataManager.get().isOnMic(UserUtils.getUserUid())) { + new DialogManager(context).showOkDialog("只有麦上用户才可以点歌哦~"); + return; + } + KtvMusicManager.INSTANCE.addMusic(musicInfo) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + } + + @Override + public void onSuccess(String s) { + closeDialog(); + SingleToastUtil.showToast("点歌成功~~"); + RxBus.get().post(KtvEvent.newInstance(KtvEvent.ADD_MUSIC_BY_USER, musicInfo)); + RxBus.get().post(KtvEvent.newInstance(KtvEvent.ADD_MUSIC, musicInfo)); + KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_ADD, musicInfo) + .subscribe(chatRoomMessage -> { + IMNetEaseManager.get().addMessages(chatRoomMessage); + }); + } + }); + break; + default: + break; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongVm.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongVm.java new file mode 100644 index 000000000..9c1554eb8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSelectSongVm.java @@ -0,0 +1,24 @@ +package com.yizhuan.erban.avroom.ktv; + + +import com.yizhuan.erban.base.BaseMsListViewModel; +import com.yizhuan.erban.databinding.ActivityKtvSelectSongBinding; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; + +import java.util.List; + +import io.reactivex.Single; + +public class KtvSelectSongVm extends BaseMsListViewModel { + + public KtvSelectSongVm(ActivityKtvSelectSongBinding mBinding) { + super(mBinding); + } + + @Override + public Single>> getSingle() { + return KtvModel.get().hotMusic(page, pageSize); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListActivity.java new file mode 100644 index 000000000..fd115f7cb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListActivity.java @@ -0,0 +1,169 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.trello.rxlifecycle2.android.ActivityEvent; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.databinding.ActivityKtvSongListBinding; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.super_admin.SaConstant; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.CommonUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.Collections; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_DELETE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_TOP; + +/** + *

KTV房间已点列表

+ * + */ + +@ActLayoutRes(R.layout.activity_ktv_song_list) +public class KtvSongListActivity extends BaseBindingActivity implements SwipeRefreshLayout.OnRefreshListener { + + private KtvSongListVm vm; + private BaseAdapter adapter; + private boolean hasSelectSong; + + public static void start(Context context, boolean hasSelectSong) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + if (CommonUtils.isFastDoubleClick(500)) return; + Intent starter = new Intent(context, KtvSongListActivity.class); + //starter.putExtra(); + context.startActivity(starter); + } + + @Override + protected void init() { + initTitleBar("已点(0)"); + vm = new KtvSongListVm(mBinding); + mBinding.setViewModel(vm); + mBinding.setClick(this); + vm.count.observe(this, count -> { + if (count == null) { + return; + } + setTitleBarText("已点(" + count + ")"); + }); + adapter = new KtvSongListAdapter(R.layout.list_item_ktv_song, BR.musicInfo, new int[]{R.id.stv_delete, R.id.stv_top}); + adapter.setEmptyView(KtvHelper.createKtvEmptyView(context,KtvHelper.NO_SONG )); + mBinding.swipeRefresh.setOnRefreshListener(this); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(context)); + mBinding.recyclerView.setAdapter(adapter); + vm.loadData(this, false); + adapter.setOnItemChildClickListener((adapter, view, position) -> { + MusicInfo musicInfo = (MusicInfo) adapter.getItem(position); + if (musicInfo == null) return; + switch (view.getId()) { + case R.id.stv_top: + KtvMusicManager.INSTANCE.popMusic(musicInfo) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(s -> { + for (int i = position; i > 1; i--) { + Collections.swap(adapter.getData(), i, i - 1); + } + KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_TOP,musicInfo) + .subscribe(chatRoomMessage -> IMNetEaseManager.get().addMessages(chatRoomMessage)); + }); + break; + case R.id.stv_delete: + KtvMusicManager.INSTANCE.deleteUserChooseMusic(musicInfo) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(s -> { + adapter.remove(position); + vm.count.setValue(adapter.getItemCount()); + KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_DELETE,musicInfo) + .subscribe(chatRoomMessage -> IMNetEaseManager.get().addMessages(chatRoomMessage)); + }); + break; + } + }); + RxBus.get().toFlowable(KtvEvent.class) + .compose(bindToLifecycle()) + .filter(ktvEvent -> ktvEvent.getType() == KtvEvent.ADD_MUSIC_BY_USER) + .subscribe(ktvEvent -> vm.loadData(KtvSongListActivity.this, false)); + } + + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.mipmap.common_ic_back); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.icon_ktv_select_song_right) { + @Override + public void performAction(View view) { + KtvSelectSongActivity.start(context, true); + } + }); + } + } + + public void setTitleBarText(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + } + } + + @Override + public void onClick(View v) { + + } + + @Override + public void onRefresh() { + vm.loadData(this, false); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ConnectiveChangedReceiver.getInstance().registerConnectiveChange(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + ConnectiveChangedReceiver.getInstance().unRegisterConnectiveChange(this); + } + @Override + public void change2NoConnection() { + super.change2NoConnection(); + if (adapter!=null) adapter.setEmptyView(KtvHelper.createKtvEmptyView(context,KtvHelper.NO_NET)); + } + + @Override + public void connectiveMobileData() { + connectiveWifi(); + } + + @Override + public void connectiveWifi() { + if (adapter!=null) adapter.setEmptyView(KtvHelper.createKtvEmptyView(context,KtvHelper.NO_SONG)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListAdapter.java new file mode 100644 index 000000000..3767bd2e4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListAdapter.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.support.annotation.Nullable; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.ui.widget.LivingIconView; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; + +public class KtvSongListAdapter extends BaseAdapter { + + public KtvSongListAdapter(int layoutResId, int brid, @Nullable int[] clickIds) { + super(layoutResId, brid, clickIds); + } + + @Override + protected void convert(BindingViewHolder helper, MusicInfo item) { + super.convert(helper, item); + int position = helper.getLayoutPosition(); + boolean isManager = AvRoomDataManager.get().isRoomOwner() || AvRoomDataManager.get().isRoomAdmin(); + helper.setVisible(R.id.stv_top, position != 0 && position != 1 && isManager); + helper.setVisible(R.id.stv_delete, position != 0 && (isManager || UserUtils.getUserUid() == item.getUid())); + helper.setTextColor(R.id.tv_song_name, position == 0 ? 0xffff4362 : 0xff333333); + helper.setVisible(R.id.tv_singing, position == 0); + ((LivingIconView) helper.getView(R.id.tv_singing)).stop(); + if (position == 0) { + ((LivingIconView) helper.getView(R.id.tv_singing)).start(); + } + helper.addOnClickListener(R.id.stv_top) + .addOnClickListener(R.id.stv_delete); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListVm.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListVm.java new file mode 100644 index 000000000..5be4f8228 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvSongListVm.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.arch.lifecycle.MutableLiveData; +import android.databinding.ObservableInt; + + +import com.yizhuan.erban.base.BaseMsListViewModel; +import com.yizhuan.erban.databinding.ActivityKtvSongListBinding; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.ktv.KtvModel; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; + +import java.util.List; + +import io.reactivex.Single; + +public class KtvSongListVm extends BaseMsListViewModel { + + public MutableLiveData count = new MutableLiveData<>(); + + public KtvSongListVm(ActivityKtvSongListBinding mBinding) { + super(mBinding); + pageSize = 50; + count.setValue(0); + } + + @Override + public Single>> getSingle() { + return KtvModel.get().getRoomMusic(UserUtils.getCurrentRoomUid()) + .flatMap(result -> { + KtvMusicManager.INSTANCE.setData(result.getData()); + List musicInfoList = result.getData().getUserChooseMusicVos(); + count.setValue(musicInfoList.size()); + return Single.just(new ServiceResult>() + .setCode(result.getCode()) + .setMessage(result.getMessage()) + .setData(musicInfoList)); + } + ); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvView.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvView.java new file mode 100644 index 000000000..cf39b1d04 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/KtvView.java @@ -0,0 +1,541 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.constraint.Group; +import android.support.v7.widget.CardView; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SurfaceView; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.utils.UserUtils; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.ktv.event.KtvEvent; +import com.yizhuan.xchat_android_core.room.ktv.event.RemoteVideoEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.SaConstant; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.concurrent.TimeUnit; + + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.agora.ktvkit.VideoPlayerView; +import io.agora.rtc.RtcEngine; +import io.agora.rtc.video.VideoCanvas; +import io.reactivex.Observable; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_KTV_CLOSE; + +public class KtvView extends CardView { + + private Context context; + public static final int KTV_ROOM_OWNER = 1;//房主 + public static final int KTV_ROOM_MANAGER = 2;//管理员 + public static final int KTV_ROOM_MV_BROADCASTER = 3;//mv主播 + public static final int KTV_ROOM_AUDIENCE = 4;//观众 + + @Nullable + private View statusView; + private CompositeDisposable disposables; + private FrameLayout playContainer; + private FrameLayout statusContainer; + private VideoPlayerView xPlay; + private boolean isShowNoSong; + public static boolean isShowPrepare; + private Disposable tipDisposable; + private Disposable prepareDisposable; + + public KtvView(@NonNull Context context) { + this(context, null); + } + + public KtvView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + init(); + } + + private void init() { + inflate(context, R.layout.layout_ktv_view, this); + setRadius(ScreenUtil.dip2px(10)); + disposables = new CompositeDisposable(); + playContainer = findViewById(R.id.play_container); + statusContainer = findViewById(R.id.status_container); + this.setOnClickListener(listener); + playContainer.setOnClickListener(listener); + statusContainer.setOnClickListener(listener); + showXPlay(RtcEngineManager.get().isPush()); + if (!RtcEngineManager.get().isLive() || KtvMusicManager.INSTANCE.getMusicList().size() == 0) { + statusView = showNoSong(); + } else if (!RtcEngineManager.get().isPush()) { + setupRemoteVideo(RtcEngineManager.get().getRemoteUid()); + } + subscribeEvent(); + } + + private Runnable runnable = this::resetStatusView; + private OnClickListener listener = new OnClickListener() { + @Override + public void onClick(View v) { + if (statusView != null) { + resetStatusView(); + return; + } + statusView = getUserType() == KTV_ROOM_AUDIENCE ? showChooseSong() : showCommand(); + } + }; + + private void subscribeEvent() { + Disposable disposable1 = RxBus.get().toFlowable(RemoteVideoEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(remoteVideoEvent -> setupRemoteVideo(remoteVideoEvent.getUid())); + Disposable disposable2 = RxBus.get().toFlowable(KtvEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::handleKtvEvent); + disposables.addAll(disposable1, disposable2); + } + + + //处理KTV相关的各种事件 + private void handleKtvEvent(KtvEvent ktvEvent) { + MusicInfo musicInfo = ktvEvent.getMusicInfo(); + switch (ktvEvent.getType()) { + case KtvEvent.SWITCH_MUSIC: + if (musicInfo != null) { + statusView = showPrepare(musicInfo); + } + break; + case KtvEvent.STOP: + if (RtcEngineManager.get().isPush() && RtcEngineManager.get().isPlaying()) { + RtcEngineManager.get().playOrPause(); + } + break; + case KtvEvent.CONTINUE: + if (RtcEngineManager.get().isPush() && !RtcEngineManager.get().isPlaying()) { + RtcEngineManager.get().playOrPause(); + } + break; + case KtvEvent.NO_MUSIC: + statusView = showNoSong(); + break; + case KtvEvent.MUSIC_UPDATE: + if (KtvMusicManager.INSTANCE.getMusicList().size() > 0 && isShowNoSong) { + resetStatusView(); + } + if (KtvMusicManager.INSTANCE.getMusicList().size() == 0 && !isShowNoSong) { + statusView = showNoSong(); + } + break; + case KtvEvent.ROOM_USER_MANAGER_STATUS: + if (btnCloseNoSong != null) { + initCloseBtn(btnCloseNoSong); + } + break; + default: + break; + } + } + + + public synchronized void setupRemoteVideo(int uid) { + if (UserUtils.getUserUid() == uid || RtcEngineManager.get().isPush()) return; + if (!isShowPrepare) resetStatusView(); + playContainer.removeAllViews(); + SurfaceView surfaceView = RtcEngine.CreateRendererView(context.getApplicationContext()); + playContainer.addView(surfaceView); + RtcEngineManager.get().setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_ADAPTIVE, uid), uid); + } + + + static class NoSongViewHolder { + @BindView(R.id.tv_no_user) + TextView tvNoUser; + @BindView(R.id.tv_tips) + TextView tvTips; + @BindView(R.id.tv_choose_song) + SuperTextView tvChooseSong; + @BindView(R.id.ib_close) + ImageButton ibClose; + + NoSongViewHolder(View view) { + ButterKnife.bind(this, view); + } + } + + private String[] tips = new String[]{ + "点击“我要点歌”按钮可进行点歌哦~", + "建议唱歌的用户上麦点歌,以免有声音延迟", + "演唱时,佩戴耳机效果更佳哦~", + "耳机离嘴唇一定距离可防止喷麦", + "演唱时试试由腹部发声,会有意外收获"}; + + /** + * 无人唱歌界面的关闭按钮 + */ + private ImageButton btnCloseNoSong; + + private View showNoSong() { + isShowNoSong = true; + isShowPrepare = false; + playContainer.removeCallbacks(runnable); + View view = inflate(context, R.layout.layout_ktv_no_song, null); + NoSongViewHolder holder = new NoSongViewHolder(view); + view.setOnClickListener(v -> { + //吃掉父view点击事件 + }); + Logger.i("显示无人唱歌的ui"); + btnCloseNoSong = holder.ibClose; + initCloseBtn(holder.ibClose); + if (tipDisposable != null) tipDisposable.dispose(); + tipDisposable = Observable.interval(0, 5, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> holder.tvTips.setText(tips[(int) (aLong % tips.length)])); + holder.tvChooseSong.setOnClickListener(v -> KtvSelectSongActivity.start(context, true)); + showStatusView(view); + return view; + } + + + static class CommandViewHolder { + @BindView(R.id.ib_close) + ImageButton ibClose; + @BindView(R.id.tv_change_audio) + SuperTextView tvChangeAudio; + @BindView(R.id.tv_song_name) + TextView tvSongName; + @BindView(R.id.tv_commit_err) + TextView tvCommitErr; + @BindView(R.id.iv_play_or_pause) + ImageView ivPlayOrPause; + + @BindView(R.id.iv_switch_song) + ImageView ivSwitchSong; + @BindView(R.id.sb_person_voice) + SeekBar sbPersonVoice; + @BindView(R.id.sb_accompany_voice) + SeekBar sbAccompanyVoice; + @BindView(R.id.sb_song_current_position) + SeekBar sbSongCurrentPosition; + @BindView(R.id.group_seek_bar) + Group group; + @BindView(R.id.tv_surplus_time) + TextView tvSurplusTime; + CommandViewHolder(View view) { + ButterKnife.bind(this, view); + } + } + + private View commandView; + + private Disposable commandDisposable; + + private View showCommand() { + playContainer.postDelayed(runnable, 3000); + if (commandView == null) { + commandView = inflate(context, R.layout.layout_ktv_command, null); + } + CommandViewHolder holder = new CommandViewHolder(commandView); + if (getUserType() != KTV_ROOM_MV_BROADCASTER) { + holder.group.setVisibility(GONE); + } else { + holder.group.setVisibility(VISIBLE); + } + holder.tvSongName.setText(KtvMusicManager.INSTANCE.getCurrMusic().getMusicName()); + initPlayBtn(holder); + initCloseBtn(holder.ibClose); + initChangeAudioBtn(holder.tvChangeAudio); + holder.tvChangeAudio.setOnClickListener(v -> { + RtcEngineManager.get().changeAudioStream(); + initChangeAudioBtn(holder.tvChangeAudio); + resetStatusView(); + }); + holder.tvCommitErr.setOnClickListener(v -> + KtvCommitErrorDialog.newInstance(context, KtvMusicManager.INSTANCE.getCurrMusic().getMusicId()).show()); + holder.ivPlayOrPause.setOnClickListener(v -> { + if (RtcEngineManager.get().isPush()) { + RtcEngineManager.get().playOrPause(); + } + /* else { //暂时不需要 + KtvHelper.sendChatRoomMusicMessage( + RtcEngineManager.get().isPlaying() ? CUSTOM_MSG_SUB_KTV_STOP : CUSTOM_MSG_SUB_KTV_CONTINUE, + null) + .subscribe(); + }*/ + initPlayBtn(holder); + resetStatusView(); + }); + holder.ivSwitchSong.setOnClickListener(v -> { + KtvMusicManager.INSTANCE.switchSong(true); + resetStatusView(); + }); + holder.sbAccompanyVoice.setProgress((int) (RtcEngineManager.get().getAccompanyVoice()*100)); + holder.sbAccompanyVoice.setOnSeekBarChangeListener( + (LambdaOnSeekBarChangeListener) (seekBar, progress, fromUser) -> + RtcEngineManager.get().setAccompanyVoice(progress/100d)); + holder.sbPersonVoice.setProgress((int) (RtcEngineManager.get().getPersonVoice()*100)); + holder.sbPersonVoice.setOnSeekBarChangeListener( + (LambdaOnSeekBarChangeListener) (seekBar, progress, fromUser) -> + RtcEngineManager.get().setPersonVoice(progress/100d)); + releaseCommandDisposable(); + commandDisposable = Observable.interval(0, 1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) + .subscribe(aLong -> setSeekDuration(holder)); + showStatusView(commandView); + return commandView; + } + + private void releaseCommandDisposable() { + if (commandDisposable != null && !commandDisposable.isDisposed()) { + commandDisposable.dispose(); + commandDisposable = null; + } + } + + @SuppressLint("ClickableViewAccessibility") + private void setSeekDuration(CommandViewHolder holder) { + double pos = RtcEngineManager.get().getPlayPos(); + holder.sbSongCurrentPosition.setProgress((int) (100 * pos)); + //禁止点击 + holder.sbSongCurrentPosition.setClickable(false); + holder.sbSongCurrentPosition.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + int duration = RtcEngineManager.get().getPlayDuration() / 1000;//单位秒 + duration = (int) (duration - duration * pos);//剩余的时间 + if (duration < 0) { + duration = 0; + } + int min = duration / 60; + int sec = duration % 60; + String secStr = String.valueOf(sec); + if (sec < 10) { + secStr = "0" + secStr; + } + holder.tvSurplusTime.setText("-" + min + ":" + secStr); + } + + private void initPlayBtn(CommandViewHolder holder) { + if (RtcEngineManager.get().isPlaying()) { + holder.ivPlayOrPause.setImageResource(R.drawable.icon_ktv_pause); + } else { + holder.ivPlayOrPause.setImageResource(R.drawable.icon_ktv_play); + } + } + + private void initChangeAudioBtn(SuperTextView textView) { + if (!RtcEngineManager.get().isAccompany()) { + textView.setTextColor(getResources().getColor(R.color.color_CCFF5B69)); + textView.setText("原唱"); + } else { + textView.setTextColor(getResources().getColor(R.color.white_transparent_60)); + textView.setText("伴奏"); + } + } + + static class PrepareViewHolder { + @BindView(R.id.ib_close) + ImageButton ibClose; + @BindView(R.id.iv_avatar) + ImageView ivAvatar; + @BindView(R.id.tv_no_user) + TextView tvNoUser; + @BindView(R.id.tv_song_name) + TextView tvSongName; + @BindView(R.id.tv_tips) + SuperTextView tvTips; + @BindView(R.id.iv_singer_avatar_bg) + ImageView ivSingerAvatarBg; + + PrepareViewHolder(View view) { + ButterKnife.bind(this, view); + } + } + + private View showPrepare(MusicInfo musicInfo) { + isShowPrepare = true; + isShowNoSong = false; + View view = inflate(context, R.layout.layout_ktv_prepare, null); + view.setOnClickListener(v -> { + //吃掉父view点击事件 + }); + PrepareViewHolder holder = new PrepareViewHolder(view); + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByAccount(String.valueOf(musicInfo.getUid())); + if (roomQueueInfo != null && roomQueueInfo.mChatRoomMember != null) { + ImageLoadUtils.loadAvatar(context, roomQueueInfo.mChatRoomMember.getAvatar(), holder.ivAvatar); + ImageLoadUtils.loadImageWithBlur(context, + roomQueueInfo.mChatRoomMember.getAvatar(), holder.ivSingerAvatarBg, 24, 10); + } + holder.tvNoUser.setText(musicInfo.getUserNick() + " 请准备"); + initCloseBtn(holder.ibClose); + if (prepareDisposable != null) prepareDisposable.dispose(); + + boolean isPushUser = UserUtils.getUserUid() == musicInfo.getUid(); + showXPlay(isPushUser); + Observable.intervalRange(0, 4, 0, 1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onNext(Long aLong) { + holder.tvSongName.setText((3 - aLong) + "秒后开始演唱: " + musicInfo.getMusicName()); + } + + @Override + public void onComplete() { + //准备中下麦处理 + if (isShowPrepare) { + resetStatusView(); + } + + } + + @Override + public void onSubscribe(Disposable d) { + prepareDisposable = d; + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + showStatusView(view); + return view; + } + + static class ChooseSongViewHolder { + @BindView(R.id.tv_tips) + TextView tvTips; + @BindView(R.id.tv_choose_song) + SuperTextView tvChooseSong; + + ChooseSongViewHolder(View view) { + ButterKnife.bind(this, view); + } + } + + private View showChooseSong() { + playContainer.postDelayed(runnable, 3000); + View view = inflate(context, R.layout.layout_ktv_choose_song, null); + ChooseSongViewHolder holder = new ChooseSongViewHolder(view); + holder.tvTips.setText(KtvMusicManager.INSTANCE.getCurrMusic().getMusicName()); + holder.tvChooseSong.setOnClickListener(v -> KtvSelectSongActivity.start(context, true)); + showStatusView(view); + return view; + } + + private void showStatusView(View view) { + statusContainer.setVisibility(VISIBLE); + statusContainer.removeAllViews(); + statusContainer.addView(view); + } + + private void resetStatusView() { + if (statusView != null) { + isShowNoSong = false; + isShowPrepare = false; + playContainer.removeCallbacks(runnable); + statusContainer.setVisibility(GONE); + statusView = null; + } + btnCloseNoSong = null; + releaseCommandDisposable(); + } + + private int getUserType() { + MusicInfo currMusic = KtvMusicManager.INSTANCE.getCurrMusic(); + if (currMusic.getUid() == UserUtils.getUserUid()) { + return KTV_ROOM_MV_BROADCASTER; + } + if (AvRoomDataManager.get().isRoomOwner()) { + return KTV_ROOM_OWNER; + } + if (AvRoomDataManager.get().isRoomAdmin()) { + return KTV_ROOM_MANAGER; + } + return KTV_ROOM_AUDIENCE; + } + + /** + * 如果是房主或管理员,显示关闭ktv的按钮 + * + * @param button 关闭ktv的按钮 + */ + + private void initCloseBtn(ImageButton button) { + if (AvRoomDataManager.get().isManager()) { + button.setVisibility(VISIBLE); + button.setOnClickListener(v -> { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS); + return; + } + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.roomcp_ktv_close_click, "关闭KTV"); + } + new DialogManager(context).showOkCancelWithTitleDialog("关闭KTV后,所有歌曲将被删除!", + () -> { + RxBus.get().post(new KtvEvent(KtvEvent.CLOSE_KTV_MODEL)); + KtvHelper.sendChatRoomMusicMessage(CUSTOM_MSG_SUB_KTV_CLOSE, new MusicInfo()) + .subscribe(chatRoomMessage -> IMNetEaseManager.get().addMessages(chatRoomMessage)); + }); + }); + + } else { + button.setVisibility(INVISIBLE); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (disposables != null) disposables.dispose(); + if (tipDisposable != null) tipDisposable.dispose(); + if (prepareDisposable != null) prepareDisposable.dispose(); + } + + private void showXPlay(boolean isShow) { + if (isShow && RtcEngineManager.get().getKtvKit()!=null) { + playContainer.removeAllViews(); + xPlay = new VideoPlayerView(context, RtcEngineManager.get().getKtvKit()); + xPlay.setZOrderMediaOverlay(true); + playContainer.addView(xPlay); + } + + } + + public void updateCloseBtnNoSong() { + if (btnCloseNoSong != null) { + initCloseBtn(btnCloseNoSong); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/ktv/LambdaOnSeekBarChangeListener.java b/app/src/main/java/com/yizhuan/erban/avroom/ktv/LambdaOnSeekBarChangeListener.java new file mode 100644 index 000000000..fafca7b98 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/ktv/LambdaOnSeekBarChangeListener.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.avroom.ktv; + +import android.widget.SeekBar; + +public interface LambdaOnSeekBarChangeListener extends SeekBar.OnSeekBarChangeListener { + @Override + default void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + default void onStopTrackingTouch(SeekBar seekBar) { + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/AvRoomPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/AvRoomPresenter.java new file mode 100644 index 000000000..43dfbc17f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/AvRoomPresenter.java @@ -0,0 +1,575 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; +import android.util.SparseArray; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomInfo; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.EnterChatRoomResultData; +import com.netease.nimlib.sdk.util.Entry; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.avroom.view.IAvRoomView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.model.MonsterHuntingModel; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager; +import com.yizhuan.xchat_android_core.room.bean.ActivityInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.MicQueueModel; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.QueuingMicMemeberInfo; +import com.yizhuan.xchat_android_core.room.queuing_mic.event.QueuingMicNotEmptyEvent; +import com.yizhuan.xchat_android_core.statistic.LogFactory; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.LogProtocol; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; + +import com.yizhuan.xchat_android_core.super_admin.SuperAdminDataMrg; + +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.threadmgr.ThreadPoolManager; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.ObservableSource; +import io.reactivex.Observer; +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +/** + *

+ * + * @author jiahui + * @date 2017/12/11 + */ +public class AvRoomPresenter extends BaseMvpPresenter { + + private static final String TAG = "AvRoomPresenter"; + + private final AvRoomModel mAvRoomModel; + private final Gson mGson; + private Disposable mGetOnlineNumberDisposable; + private static final String GET_ROOM_FROM_IMNET_ERROR = "-1101"; + + public AvRoomPresenter() { + mAvRoomModel = AvRoomModel.get(); + mGson = new Gson(); + } + + /** + * 进入云信聊天室回调 + */ + public void enterRoom(RoomInfo roomInfo) { + if (roomInfo == null) { + if (getMvpView() != null) + getMvpView().showFinishRoomView(); + return; + } + if (!TextUtils.isEmpty(PublicChatHallDataManager.get().getPublicChatHallUid()) && + Objects.equals(roomInfo.getUid(), Long.parseLong( + PublicChatHallDataManager.get().getPublicChatHallUid()))) { + dealEnterRoomError(new Throwable("13002")); + return; + } + final RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom != null) { + if (currentRoom.getUid() == roomInfo.getUid()) { + getMvpView().dismissLoadingDialog(); + return; + } + //进入新的房间需要先退出房间 + exitRoom(); + } + //我们自己服务端信息 + AvRoomDataManager.get().mCurrentRoomInfo = roomInfo; + + // 第一次进房,离开模式下更新本地房主位ui + AvRoomDataManager.get().nick = roomInfo.getNick(); + AvRoomDataManager.get().gender = roomInfo.getGender(); + AvRoomDataManager.get().avatar = roomInfo.getAvatar(); + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_LIST_TYPE, + "区分房间类型:" + roomInfo.getRoomTypeLable()); + + Observable enterRoomObservable = mAvRoomModel.enterRoom(roomInfo.getRoomId(), 3); + + Disposable subscribe = enterRoomObservable.flatMap(this::dealServerMicInfo) + .map(this::dealMicMemberFromIMNet) + .flatMap(this::dealMicChatRoomMemberFromIMNet) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(roomQueueInfoSparseArray -> { + long uid = AuthModel.get().getCurrentUid(); + RtcEngineManager.get().startRtcEngine(uid); + + //成功进入房间发送log 到阿里 + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_VERBOSE, + LogProtocol.Topic.TOPIC_IM_LOG, + LogProtocol.Event.EVENT_IM_CHANNEL + ) + .append("roomUid", String.valueOf(roomInfo.getUid())) + .append("uid", String.valueOf(AuthModel.get().getCurrentUid())) + .append("type", "1")); + + if (getMvpView() != null) { + getMvpView().enterRoomSuccess(); + } + }, this::dealEnterRoomError); + } + + private void dealEnterRoomError(Throwable throwable) { + throwable.printStackTrace(); + String roomUid = AvRoomDataManager.get().mCurrentRoomInfo != null ? + String.valueOf(AvRoomDataManager.get().mCurrentRoomInfo.getUid()) : ""; + String error = ""; + switch (throwable.getMessage()) { + case "414": + error = "参数错误"; + if (getMvpView() != null) { + getMvpView().enterRoomFail(-1, error); + } + break; + case "404": + case "13002": + if (getMvpView() != null) + getMvpView().showFinishRoomView(); + error = "聊天室不存在"; + break; + case "403": + error = "无权限"; + if (getMvpView() != null) { + getMvpView().enterRoomFail(-1, error); + } + break; + case "500": + error = "服务器内部错误"; + break; + case "13001": + error = "IM主连接状态异常"; + if (getMvpView() != null) { + getMvpView().enterRoomFail(-1, error); + } + break; + case "13003": + error = "黑名单用户禁止进入聊天室"; + if (getMvpView() != null) + getMvpView().showBlackEnterRoomView(); + break; + case GET_ROOM_FROM_IMNET_ERROR: + error = "云信进入聊天室后,返回的聊天室信息异常"; + exitRoom(); + if (getMvpView() != null) { + getMvpView().enterRoomFail(-1, "网络异常"); + } + break; + default: + error = "网络异常"; + if (getMvpView() != null) { + getMvpView().enterRoomFail(-1, error); + } + break; + + } + + //进入房间失败发送阿里log + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_ERROR, + LogProtocol.Topic.TOPIC_IM_LOG, + LogProtocol.Event.EVENT_IM_CHANNEL + ) + .append("roomUid", roomUid) + .append("uid", String.valueOf(AuthModel.get().getCurrentUid())) + .append("type", "1") + .append("error", "{code:" + throwable.getMessage() + ", reason:" + error + "}")); + + // 首页取消转圈圈 + IMNetEaseManager.get().getChatRoomEventObservable().onNext(new RoomEvent().setEvent(RoomEvent.ROOM_EXIT)); + } + + /** + * 处理网易云信队列上人员的信息 + */ + private Observable> dealMicChatRoomMemberFromIMNet(List accounts) { + if (ListUtils.isListEmpty(accounts)) + return Observable.just(AvRoomDataManager.get().mMicQueueMemberMap); + return IMNetEaseManager.get().fetchRoomMembersByIds(accounts).observeOn(AndroidSchedulers.mainThread()) + .flatMap(chatRoomMembers -> { + for (ChatRoomMember chatRoomMember : chatRoomMembers) { + AvRoomDataManager.get().updateQueueChatRoomMemberExtension(chatRoomMember); + } + return Single.just(AvRoomDataManager.get().mMicQueueMemberMap); + }).toObservable(); + } + + + /** + * 处理网易云信坑位信息 + */ + private List dealMicMemberFromIMNet(List> entries) { + List accounts = new ArrayList<>(); + if (!ListUtils.isListEmpty(entries)) { + JsonParser jsonParser = new JsonParser(); + ChatRoomMember chatRoomMember; + for (Entry entry : entries) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(Integer.parseInt(entry.key)); + if (roomQueueInfo != null) { + JsonObject valueJsonObj = jsonParser.parse(entry.value).getAsJsonObject(); + if (valueJsonObj != null) { + chatRoomMember = new ChatRoomMember(); + if (valueJsonObj.has("uid")) { + int uid = valueJsonObj.get("uid").getAsInt(); + accounts.add(String.valueOf(uid)); + chatRoomMember.setAccount(String.valueOf(uid)); + } + if (valueJsonObj.has("nick")) { + chatRoomMember.setNick(valueJsonObj.get("nick").getAsString()); + } + if (valueJsonObj.has("avatar")) { + chatRoomMember.setAvatar(valueJsonObj.get("avatar").getAsString()); + } + if (valueJsonObj.has("gender")) { + roomQueueInfo.gender = valueJsonObj.get("gender").getAsInt(); + } + if (valueJsonObj.has("groupType")) { + roomQueueInfo.groupType = valueJsonObj.get("groupType").getAsInt(); + } + roomQueueInfo.mChatRoomMember = chatRoomMember; + } + AvRoomDataManager.get().mMicQueueMemberMap.put(Integer.valueOf(entry.key), roomQueueInfo); + } + } + } + return accounts; + } + + + /** + * 处理服务端坑位信息 + */ + @Nullable + private ObservableSource>> dealServerMicInfo(EnterChatRoomResultData enterChatRoomResultData) { + AvRoomDataManager.get().mEnterChatRoomResultData = enterChatRoomResultData; + if (enterChatRoomResultData == null) + return Observable.error(new Throwable(GET_ROOM_FROM_IMNET_ERROR)); + else { + final ChatRoomInfo roomInfo = enterChatRoomResultData.getRoomInfo(); + if (roomInfo == null) { + return Observable.error(new Throwable(GET_ROOM_FROM_IMNET_ERROR)); + } + AvRoomDataManager.get().mCurrentRoomInfo.onlineNum = roomInfo.getOnlineUserCount(); + Map extension = roomInfo.getExtension(); + if (extension != null) { + String roomInfoStr = (String) extension.get(Constants.KEY_CHAT_ROOM_INFO_ROOM); + if (!TextUtils.isEmpty(roomInfoStr)) { + RoomInfo extRoomInfo = mGson.fromJson(roomInfoStr, RoomInfo.class); + extRoomInfo.setRoomId(Long.valueOf(roomInfo.getRoomId())); + extRoomInfo.onlineNum = AvRoomDataManager.get().mCurrentRoomInfo.onlineNum; + //云信服务端信息 + AvRoomDataManager.get().mCurrentRoomInfo = extRoomInfo; + } + //获取云信麦序相关信息 + String roomMicStr = (String) extension.get(Constants.KEY_CHAT_ROOM_INFO_MIC); + if (!TextUtils.isEmpty(roomMicStr)) { + //清除魅力值(重新进房会触发退房,已经清除过了) + GiftValueMrg.get().clearObsever(); + //初始化所有坑位 + Map micMapStr = mGson.fromJson(roomMicStr, new TypeToken>() { + }.getType()); + for (Map.Entry entry : micMapStr.entrySet()) { + AvRoomDataManager.get().mMicQueueMemberMap.put(Integer.valueOf(entry.getKey()), + new RoomQueueInfo(mGson.fromJson(entry.getValue(), RoomMicInfo.class), null)); + } + return mAvRoomModel.queryRoomMicInfo(roomInfo.getRoomId()); + } + } + return Observable.error(new Throwable(GET_ROOM_FROM_IMNET_ERROR)); + } + } + + public void exitRoom() { + mAvRoomModel.exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + if (getMvpView() != null) { + getMvpView().exitRoom(data); + } + } + + @Override + public void onFail(int code, String error) { + + } + }); + } + + @SuppressLint("CheckResult") + public void requestRoomInfoFromService(String uId) { + if (TextUtils.isEmpty(uId)) { + return; + } + mAvRoomModel.requestRoomResult(uId, 0) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .doOnError(throwable -> { + if (getMvpView() != null) { + getMvpView().requestRoomInfoFailView(throwable); + } + }) + .doOnSuccess(roomResult -> { + if (roomResult == null) { + if (getMvpView() != null) { + getMvpView().requestRoomInfoFailView(new Throwable("网络错误")); + } + return; + } + if (roomResult.isSuccess()) { + RoomInfo data = roomResult.getData(); + if (data == null || data.getRoomId() == 0) { + if (getMvpView() != null) { + getMvpView().showFinishRoomView(); + } + //获取房间信息失败 发送log 到阿里 + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_ERROR, + LogProtocol.Topic.TOPIC_BUSINESS_LOG, + LogProtocol.Event.EVENT_ROOM_GET + ) + .append("targetUid", uId) + .append("uid", String.valueOf(AuthModel.get().getCurrentUid())) + .append("error", "{code:" + "" + " reason:" + " RoomInfo == null || RoomInfo.getRoomId() == 0" + "}")); + return; + } + // 如果当前是排麦模式,就自己去拉一次排麦列表 + if (AvRoomDataManager.get().isRoomInQueuingMicMode(data)) { + //noinspection ResultOfMethodCallIgnored + MicQueueModel.get() + .loadMicQueueList(data.getUid(), 1, Constants.PAGE_SIZE) + .subscribe((respQueuingMicListInfo, throwable) -> { + if (throwable == null) { + List queue = respQueuingMicListInfo.getQueue(); + if (queue != null) { + if (queue.size() > 0) { + EventBus.getDefault().post(new QueuingMicNotEmptyEvent()); + } + } + } + }); + } + if (getMvpView() != null) { + getMvpView().requestRoomInfoSuccessView(data); + } + + return; + } + //进房失败 + if (getMvpView() != null) { + getMvpView().requestRoomInfoFailView(RxHelper.createThrowable(roomResult)); + } + + //获取房间信息失败 发送log 到阿里 + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_ERROR, + LogProtocol.Topic.TOPIC_BUSINESS_LOG, + LogProtocol.Event.EVENT_ROOM_GET + ) + .append("targetUid", uId) + .append("uid", String.valueOf(AuthModel.get().getCurrentUid())) + .append("error", "{code:" + roomResult.getCode() + + " reason:" + RxHelper.getValidMessage(roomResult) + "}")); + + }) + .subscribe(); + } + + /** + * 获取活动信息 + */ + public void getActionDialog(int type) { + mAvRoomModel.getActionDialog(type, new CallBack() { + @Override + public void onSuccess(ActivityInfo data) { + if (getMvpView() != null) { + getMvpView().onGetActionDialog(data.getList()); + } + } + + @Override + public void onFail(int code, String error) { + if (getMvpView() != null) { + getMvpView().onGetActionDialogError(error); + } + } + }); + } + + /** + * 获取房间内固定成员列表 + */ + public void getNormalChatMember() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + long currentUid = AuthModel.get().getCurrentUid(); + mAvRoomModel.getNormalChatMember(String.valueOf(roomInfo.getRoomId()), currentUid); + } + + private void startGetOnlineMemberNumberJob() { + Observable.interval(1, 10, TimeUnit.SECONDS, Schedulers.from(ThreadPoolManager.instance().getScheduleExecutor())) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + mGetOnlineNumberDisposable = d; + } + + @Override + public void onNext(Long aLong) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + Log.e(TAG, "onNext: roomInfo in startGetOnlineMemberNumberJob: " + roomInfo); + Log.e(TAG, "onNext: has login in IM: " + AuthModel.get().isImLogin()); + Disposable subscribe = mAvRoomModel.startGetOnlineMemberNumberJob(roomInfo.getRoomId()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(AvRoomPresenter.this.bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new Consumer() { + @Override + public void accept(ChatRoomInfo chatRoomInfo) throws Exception { + if (chatRoomInfo == null) return; + int onlineUserCount = chatRoomInfo.getOnlineUserCount(); + if (onlineUserCount <= SuperAdminDataMrg.OFFSET_COUNT) { + //减去超管的人数 + onlineUserCount = onlineUserCount - SuperAdminDataMrg.get().getSAdminList().size(); + if (onlineUserCount < 0) { + onlineUserCount = 0; + } + } + if (AvRoomDataManager.get().mCurrentRoomInfo != null) + AvRoomDataManager.get().mCurrentRoomInfo.onlineNum = onlineUserCount; + if (getMvpView() != null) { + getMvpView().onRoomOnlineNumberSuccess(onlineUserCount); + } + SuperAdminDataMrg.get().updateList(onlineUserCount); + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + throwable.printStackTrace(); + } + }); + } + + @Override + public void onError(Throwable e) { + } + + @Override + public void onComplete() { + } + }); + + } + + public void getMonster() { + MonsterHuntingModel.get().getRoomMonsterList() + .compose(bindToLifecycle()) + .subscribe((monsterInfoServiceResult, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + // TODO: 16/04/2018 不知道为何,就是有异常 +// getMvpView().getMonsterInfoFail("发生异常"); + } else if (monsterInfoServiceResult.isSuccess()) { + MonsterInfo monsterInfo = monsterInfoServiceResult.getData(); + if (monsterInfo != null) { + getMvpView().getMonsterInfoSuccess(monsterInfo); + } + } else if (!monsterInfoServiceResult.isSuccess()) { + getMvpView().getMonsterInfoFail(monsterInfoServiceResult.getError()); + } + }); + } + + public void upAiMicroPhone(int micPosition, String uId) { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) return; + mAvRoomModel.upAiMicroPhone(micPosition, uId, String.valueOf(AvRoomDataManager.get().mCurrentRoomInfo.getRoomId()), + new CallBack() { + @Override + public void onSuccess(String data) { + Logger.i("用户%1$s上麦成功:%2$s", uId, data); + } + + @Override + public void onFail(int code, String error) { + Logger.i("用户%1$s上麦失败:%2$s----", uId, error); + } + }); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (mGetOnlineNumberDisposable != null) { + mGetOnlineNumberDisposable.dispose(); + mGetOnlineNumberDisposable = null; + } + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + startGetOnlineMemberNumberJob(); + } + + public void judgeIsLimitEnter() { + UserModel.get().getCurrentUserInfo() + .filter(UserInfo::isParentMode) + .flatMapSingle((Function>>) + userInfo -> AvRoomModel.get().getLimitRoomInfo()) + .doOnError(throwable -> { + if (throwable instanceof PmRoomLimitException) { + if (getMvpView() != null) { + getMvpView().recoverRoomMinWhenPmLimit(throwable); + } + } + }) + .subscribe(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/BaseRoomRankPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/BaseRoomRankPresenter.java new file mode 100644 index 000000000..b5bf69bae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/BaseRoomRankPresenter.java @@ -0,0 +1,72 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.avroom.adapter.RoomConsumerListAdapterTemp; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.ArrayList; +import java.util.List; + +public class BaseRoomRankPresenter extends BaseMvpPresenter { + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + } + + public List handleList(List dataInfoList) { + List list = new ArrayList<>(); + if (dataInfoList == null) { + dataInfoList = new ArrayList<>(); + } + + List topThree = new ArrayList<>(); + int count = 0; + while (count < 3 && dataInfoList.size() > 0) { + RoomContributeUserInfo info = dataInfoList.remove(0); + topThree.add(info); + count++; + } + + RoomRankMultiItem topItem = completeTopThree(topThree); + + list.add(topItem); + + if (dataInfoList.size() == 0) { + RoomRankMultiItem item = new RoomRankMultiItem(); + item.setItemType(RoomConsumerListAdapterTemp.TYPE_EMPTY); + list.add(item); + } else { + for (RoomContributeUserInfo info : dataInfoList) { + RoomRankMultiItem item = new RoomRankMultiItem(); + item.setData(info); + item.setItemType(RoomRankMultiItem.TYPE_LINEAR); + list.add(item); + } + } + + + return list; + + } + + public RoomRankMultiItem completeTopThree(List topThree) { + while (topThree.size() < 3) { + topThree.add(new RoomContributeUserInfo(true)); + } + RoomRankMultiItem topItem = new RoomRankMultiItem(); + topItem.setData(topThree); + topItem.setItemType(RoomContributeUserInfo.TYPE_GRID); + return topItem; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/CreatePKPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/CreatePKPresenter.java new file mode 100644 index 000000000..0422472e3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/CreatePKPresenter.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.yizhuan.erban.avroom.view.ICreatePKView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/12/28 + */ +public class CreatePKPresenter extends BaseMvpPresenter { + private int pkMode = -1; + private int pkVoteMode = -1; + private long pkDuration = -1; + + public int getPkMode() { + return pkMode; + } + + public void setPkMode(int pkMode) { + this.pkMode = pkMode; + } + + public int getPkVoteMode() { + return pkVoteMode; + } + + public void setPkVoteMode(int pkVoteMode) { + this.pkVoteMode = pkVoteMode; + } + + public long getPkDuration() { + return pkDuration; + } + + public void setPkDuration(long pkDuration) { + this.pkDuration = pkDuration; + } + + /** + * 创建 PK + * + * @param redTeamMember + * @param blueTeamMember + * @return + */ + public Single createPK(List redTeamMember, List blueTeamMember) { + if (pkMode == -1) { + return Single.error(new Throwable("请选择Pk 模式")); + } + if (pkVoteMode == -1) { + return Single.error(new Throwable("请选择PK的投票模式")); + } + if (pkDuration == -1) { + return Single.error(new Throwable("请选择PK的时间")); + } + + return PkModel.get().openPKMode( + + ) + .flatMap(new Function>() { + @Override + public SingleSource apply(String s) throws Exception { + return PkModel.get().createPK( + pkMode, + pkVoteMode, + pkDuration, + redTeamMember, + blueTeamMember + ) + ; + } + }); + } + + public Single closePkMode() { + return PkModel.get().closePKMode(); + } + + + public Single createPKAgain(List redTeamMember, List blueTeamMember) { + return PkModel.get().createPK( + pkMode, + pkVoteMode, + pkDuration, + redTeamMember, + blueTeamMember + ); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyPresenter.java new file mode 100644 index 000000000..9bc22ae87 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyPresenter.java @@ -0,0 +1,828 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.util.Log; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.util.Entry; +import com.orhanobut.logger.Logger; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.avroom.view.IHomePartyView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomInfoAttachment; +import com.yizhuan.xchat_android_core.kick.KickModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.model.MentoringRelationshipModel; +import com.yizhuan.xchat_android_core.miniworld.bean.MiniWorldInWorldInfo; +import com.yizhuan.xchat_android_core.miniworld.model.MiniWorldModel; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.bean.DragonBarInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.dragonball.DragonBallModel; +import com.yizhuan.xchat_android_core.room.exception.AntiSpamHitException; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_core.room.game.AiPlayEndEvent; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.HomePartyModel; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_core.super_admin.model.ISuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SaAttachmentFactory; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.BaseInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Consumer; + +import static com.yizhuan.xchat_android_core.manager.RoomEvent.DRAGON_BAR_CANCEL; +import static com.yizhuan.xchat_android_core.manager.RoomEvent.DRAGON_BAR_END; + + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public class HomePartyPresenter extends BaseMvpPresenter { + private final HomePartyModel mHomePartyMode; + private final AvRoomModel mAvRoomModel; + private final SuperAdminModel mSuperAdminModel; + /** + * 判断所坑服务端是否响应回来了 + */ + private boolean mIsLockMicPosResultSuccess = true; + private boolean mIsUnLockMicPosResultSuccess = true; + + private boolean isLeaveMode = false; + + public HomePartyPresenter() { + mHomePartyMode = new HomePartyModel(); + mAvRoomModel = AvRoomModel.get(); + mSuperAdminModel = new SuperAdminModel(); + } + + /** + * 麦坑点击处理,麦上没人的时候 + * + * @param micPosition 麦序位置 + * @param chatRoomMember 坑上的用户 + */ + public void microPhonePositionClick(final int micPosition, ChatRoomMember chatRoomMember) { + final RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + if (AvRoomDataManager.get().isRoomOwner(currentUid) || AvRoomDataManager.get().isRoomAdmin(currentUid) + || SuperAdminUtil.isSuperAdmin()) { + if (AvRoomDataManager.get().isRoomOwner(currentUid) && currentRoom.isLeaveMode()) { + SingleToastUtil.showToast("请先关闭离开模式"); + return; + } + onOwnerUpMicroClick(micPosition, Long.parseLong(currentUid)); + } else { + if (AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(micPosition).mRoomMicInfo.isMicLock()) { + if (AvRoomDataManager.get().isQueuingMicro()) { + String msg; + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + msg = "你已经在麦上啦"; + } else { + msg = "要排麦才可以上麦哦~"; + } + SingleToastUtil.showToast(msg); + } + return; + } + if (AvRoomDataManager.get().isQueuingMicro() && AvRoomDataManager.get().myIsInQueue) { + SingleToastUtil.showToast("取消报名才可以上麦哦!"); + return; + } + getMvpView().toUpMicroPhone(micPosition, currentUid, false); + + } + } + + private void onOwnerUpMicroClick(final int micPosition, final long currentUid) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(micPosition); + if (roomQueueInfo == null) return; + if (getMvpView() != null) + getMvpView().showOwnerClickDialog(roomQueueInfo.mRoomMicInfo, micPosition, currentUid); + } + + public void lockMicroPhone(int micPosition) { + if (!mIsLockMicPosResultSuccess) { + return; + } + mIsLockMicPosResultSuccess = false; + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(currentRoom.getUid()); + mHomePartyMode.lockMicroPhone(micPosition, currentUid, AuthModel.get().getTicket()) + .doOnSuccess(data -> { + Logger.i("用户%1$s锁坑成功: %2$s", String.valueOf(currentUid), data); + mIsLockMicPosResultSuccess = true; + }) + .doOnError(throwable -> { + Logger.i("用户%1$s锁坑失败: %2$s", String.valueOf(currentUid), + RxHelper.getNotEmptyError(throwable)); + mIsLockMicPosResultSuccess = true; + }) + .subscribe(); + } + + /** + * 坑位释放锁 + */ + public void unLockMicroPhone(int micPosition) { + if (!mIsUnLockMicPosResultSuccess) { + return; + } + mIsUnLockMicPosResultSuccess = false; + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(currentRoom.getUid()); + if (AvRoomDataManager.get().isRoomAdmin() || AvRoomDataManager.get().isRoomOwner(currentUid)) { + mHomePartyMode.unLockMicroPhone(micPosition, currentUid, AuthModel.get().getTicket()) + .subscribe(new Consumer() { + @Override + public void accept(String data) throws Exception { + Logger.i("用户%1$s解麦成功: %2$s", String.valueOf(currentUid), data); + mIsUnLockMicPosResultSuccess = true; + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + Logger.i("用户%1$s解麦失败: %2$s", String.valueOf(currentUid), throwable.getMessage()); + mIsUnLockMicPosResultSuccess = true; + } + }); + } + } + + /** + * 下麦 + * + * @param micPosition + * @param isKick 是否是主动的 + */ + public void downMicroPhone(int micPosition, final boolean isKick) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + final String currentUid = String.valueOf(AuthModel.get()); + mHomePartyMode.downMicroPhone(micPosition, new CallBack() { + @Override + public void onSuccess(String data) { + Logger.i("用户%1$s下麦成功:%2$s", currentUid, data); + if (!isKick) { + //被踢了 + if (getMvpView() != null) { + getMvpView().kickDownMicroPhoneSuccess(); + } + } + } + + @Override + public void onFail(int code, String error) { + Logger.i("用户%1$s下麦失败:%2$s----", currentUid, error); + } + }); + } + + /** + * 上麦 + * + * @param micPosition + * @param uId + * @param isInviteUpMic 是否是主动的,false:主动 + * @param isReconnect 是否需要清除礼物值,普通情况下上麦传false,断网重连传ture + */ + public void upMicroPhone(final int micPosition, final String uId, boolean isInviteUpMic, boolean isReconnect) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (!isInviteUpMic) { + if (roomInfo.isOpenKTV() && AvRoomDataManager.get().isOwnerOnMic()) { + if (getMvpView() != null) { + getMvpView().onKtvChangeMic(micPosition, uId, isInviteUpMic, roomInfo); + } + } else if (AvRoomDataManager.get().haveStartDragon) { + if (getMvpView() != null) { + getMvpView().onDragonBarChangeMic(micPosition, uId, isInviteUpMic, roomInfo); + } + } else if (AvRoomDataManager.get().isShowGiftValue() && AvRoomDataManager.get().isOwnerOnMic()) { + if (getMvpView() != null) { + getMvpView().onGiftValueChangeMic(micPosition, uId, isInviteUpMic, roomInfo); + } + } else { + upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo, isReconnect); + } + } else { + AvRoomDataManager.get().haveStartDragon = false; + upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo, isReconnect); + } + } + + public void upMicroPhone(final int micPosition, final String uId, boolean isInviteUpMic) { + upMicroPhone(micPosition, uId, isInviteUpMic, false); + } + + public void upMicroPhone(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo) { + upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo, false); + } + + public void upMicroPhone(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo, + boolean isReconnect) { + mHomePartyMode.upMicroPhone(micPosition, uId, String.valueOf(roomInfo.getRoomId()), + isInviteUpMic, new CallBack() { + @Override + public void onSuccess(String data) { + Logger.i("用户%1$s上麦成功:%2$s", uId, data); + if (!isReconnect) { + GiftValueMrg.get().requestUpMic(micPosition, uId); + } else { + GiftValueMrg.get().handleReconnect(true); + } + } + + @Override + public void onFail(int code, String error) { + Logger.i("用户%1$s上麦失败:%2$s----", uId, error); + } + }); + } + + /** + * 邀请用户上麦 + * + * @param micInfo 要邀请的用户 + * @param position 坑位 + */ + public void inviteMicroPhone(final BaseInfo micInfo, final int position) { + final long micUid = micInfo.getUid(); + if (AvRoomDataManager.get().isOnMic(micUid)) { + return; + } + //如果点击的就是自己,那这里就是自己上麦 + if (AvRoomDataManager.get().isOwner(micUid)) { + upMicroPhone(position, String.valueOf(micUid), true); + return; + } + mHomePartyMode.inviteMicroPhone(micInfo, position) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new BiConsumer() { + @Override + public void accept(ChatRoomMessage chatRoomMessage, + Throwable throwable) throws Exception { + if (throwable != null) { + Logger.i("邀请用户%d上麦失败!!!" + micUid); + } else + Logger.i("邀请用户%d上麦成功!!!" + micUid); + } + }); + } + + /** + * 获取固定成员(创建者,管理员,普通用户,受限用户) + */ + public void loadNormalMembers() { + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + mHomePartyMode.loadNormalMembers(String.valueOf(currentRoom.getRoomId()), 0, 500, + new CallBack>() { + @Override + public void onSuccess(List data) { + if (getMvpView() != null) { + getMvpView().resultLoadNormalMembers(data); + } + } + + @Override + public void onFail(int code, String error) { + + } + }); + } + + /** + * 开麦 + * + * @param micPosition + */ + public void openMicroPhone(int micPosition) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + mHomePartyMode.openMicroPhone(micPosition, roomInfo.getUid()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String data, String error) { + super.accept(data, error); + if (error != null) { + Logger.i("用户%1$s开麦失败: %2$s", String.valueOf(roomInfo.getUid()), error); + } else { + Logger.i("用户%1$s开麦成功: %2$s", String.valueOf(roomInfo.getUid()), data); + } + } + }); + } + + /** + * 闭麦 + * + * @param micPosition + */ + public void closeMicroPhone(int micPosition) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + mHomePartyMode.closeMicroPhone(micPosition, roomInfo.getUid()) + .doOnSuccess(data -> { + Logger.i("用户%1$s闭麦成功: %2$s", String.valueOf(roomInfo.getUid()), data); + }) + .doOnError(throwable -> { + Logger.i("用户%1$s闭麦失败: %2$s", String.valueOf(roomInfo.getUid()), + RxHelper.getNotEmptyError(throwable)); + }) + .subscribe(); + } + + public void roomOperate(int operate) { + mSuperAdminModel.roomOperate(operate) + .subscribe(); + } + + /*** + * 发送房间消息 + * @param message + */ + @SuppressLint("CheckResult") + public void sendTextMsg(String message) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null || TextUtils.isEmpty(message)) return; + IMNetEaseManager.get().sendTextMsg(roomInfo.getRoomId(), message) + .subscribe(new BiConsumer() { + @Override + public void accept(ChatRoomMessage chatRoomMessage, + Throwable throwable) throws Exception { + if (throwable != null) { + if (throwable instanceof AntiSpamHitException) { + Log.e("sendTextMsg", throwable.getMessage()); + } else { + Logger.i("发送房间信息失败:" + throwable.getMessage()); + } + } else { + getMvpView().onSendMsgSuccess(); + IMNetEaseManager.get().addMessagesImmediately(chatRoomMessage); + Logger.i("发送房间信息成功:" + chatRoomMessage); + } + } + }); + } + + @SuppressLint("CheckResult") + public void chatRoomReConnect(final RoomQueueInfo queueInfo) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + mHomePartyMode.queryRoomMicInfo(String.valueOf(roomInfo.getRoomId())) + .delay(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>>() { + @Override + public void accept(List> entries) throws Exception { + if (!ListUtils.isListEmpty(entries)) { + JsonParser jsonParser = new JsonParser(); + ChatRoomMember chatRoomMember; + for (Entry entry : entries) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(Integer.parseInt(entry.key)); + if (roomQueueInfo != null) { + JsonObject valueJsonObj = jsonParser.parse(entry.value).getAsJsonObject(); + if (valueJsonObj != null) { + chatRoomMember = new ChatRoomMember(); + if (valueJsonObj.has("uid")) { + int uid = valueJsonObj.get("uid").getAsInt(); + chatRoomMember.setAccount(String.valueOf(uid)); + } + if (valueJsonObj.has("nick")) { + chatRoomMember.setNick(valueJsonObj.get("nick").getAsString()); + } + if (valueJsonObj.has("avatar")) { + chatRoomMember.setAvatar(valueJsonObj.get("avatar").getAsString()); + } + if (valueJsonObj.has("gender")) { + roomQueueInfo.gender = valueJsonObj.get("gender").getAsInt(); + } + if (valueJsonObj.has("groupType")) { + roomQueueInfo.groupType = valueJsonObj.get("groupType").getAsInt(); + } + roomQueueInfo.mChatRoomMember = chatRoomMember; + } + AvRoomDataManager.get().addRoomQueueInfo(entry.key, roomQueueInfo); + } + } + } else { + //麦上都没有人 + AvRoomDataManager.get().resetMicMembers(); + } + if (getMvpView() != null) + getMvpView().chatRoomReConnectView(); + //之前在麦上 + if (queueInfo != null && queueInfo.mChatRoomMember != null && queueInfo.mRoomMicInfo != null) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByMicPosition(queueInfo.mRoomMicInfo.getPosition()); + //麦上没人 + String account = queueInfo.mChatRoomMember.getAccount(); + if (roomQueueInfo != null && (roomQueueInfo.mChatRoomMember == null || + Objects.equals(account, roomQueueInfo.mChatRoomMember.getAccount()))) { + roomQueueInfo.mChatRoomMember = null; + //断网重连,不要清除麦上的礼物值 + upMicroPhone(queueInfo.mRoomMicInfo.getPosition(), account, true, true); + } + } + IMNetEaseManager.get().mCacheRoomQueueInfo = null; + Logger.i("断网重连获取队列信息成功...." + entries); + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + throwable.printStackTrace(); + Logger.i("断网重连获取队列信息失败...."); + } + }); + } + + + public void userRoomIn() { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + long currentUid = AuthModel.get().getCurrentUid(); + mAvRoomModel.userRoomIn(String.valueOf(currentUid), roomInfo.getUid()) + .delay(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()).subscribe(); + } + + //isGiven上次是否异常退出 + public void sendDragonBar(FaceInfo faceInfo, String point, boolean isGiven) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + if (isGiven) { + final ChatRoomMessage message = getChatRoomMessage(roomInfo, getPointList(faceInfo, point), CustomAttachment.CUSTOM_MSG_DRAGON_BAR_START); + IMNetEaseManager.get().sendChatRoomMessage(message, false) + .subscribe((chatRoomMessage, throwable) -> { + parseDragonBar(chatRoomMessage); + }); + } else { + final ChatRoomMessage message1 = getChatRoomMessage(roomInfo, getPointList(faceInfo, point), CustomAttachment.CUSTOM_MSG_DRAGON_BAR_RUNAWAY); + IMNetEaseManager.get().sendChatRoomMessage(message1, false) + .subscribe((chatRoomMessage, throwable) -> { + parseDragonBar(chatRoomMessage); + IMNetEaseManager.get().addMessages(chatRoomMessage); + }); + } + } + + public void openDragonBar() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + // 普通表情 + final ChatRoomMessage message = getChatRoomMessage(roomInfo, AvRoomDataManager.get().dragons, CustomAttachment.CUSTOM_MSG_DRAGON_BAR_END); + IMNetEaseManager.get().sendChatRoomMessage(message, false) + .subscribe((chatRoomMessage, throwable) -> { + IMNetEaseManager.get().getChatRoomEventObservable(). + onNext(new RoomEvent().setEvent(DRAGON_BAR_END) + .setChatRoomMessage(chatRoomMessage)); + IMNetEaseManager.get().addMessages(chatRoomMessage); + }); + } + + public void cancelDragon() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + // 普通表情 + final ChatRoomMessage message = getChatRoomMessage(roomInfo, AvRoomDataManager.get().dragons, CustomAttachment.CUSTOM_MSG_DRAGON_BAR_CANCEL); + IMNetEaseManager.get().sendChatRoomMessage(message, false) + .subscribe((chatRoomMessage, throwable) -> { + IMNetEaseManager.get().getChatRoomEventObservable(). + onNext(new RoomEvent().setEvent(DRAGON_BAR_CANCEL) + .setChatRoomMessage(chatRoomMessage)); + IMNetEaseManager.get().addMessages(chatRoomMessage); + + }); + } + + @NonNull + private ChatRoomMessage getChatRoomMessage(RoomInfo roomInfo, List integers, int second) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + List faceReceiveInfos = new ArrayList<>(); + FaceReceiveInfo faceReceiveInfo = new FaceReceiveInfo(); + faceReceiveInfo.setNick(userInfo.getNick()); + faceReceiveInfo.setFaceId(Constants.DRAGON_BAR_ID); + faceReceiveInfo.setUid(userInfo.getUid()); + + faceReceiveInfo.setResultIndexes(integers); + faceReceiveInfos.add(faceReceiveInfo); + + // 发送云信信息给所有人 + FaceAttachment faceAttachment = + new FaceAttachment(CustomAttachment.CUSTOM_MSG_DRAGON_BAR, second); + faceAttachment.setUid(userInfo.getUid()); + faceAttachment.setFaceReceiveInfos(faceReceiveInfos); + + return ChatRoomMessageBuilder.createChatRoomCustomMessage( + // 聊天室id + roomInfo.getRoomId() + "", + // 自定义消息 + faceAttachment + ); + } + + private List getPointList(FaceInfo faceInfo, String point) { + List list = new ArrayList(); + String[] split = point.replace("[", "").replace("]", "").split(", "); + for (String s : split) { + list.add(Integer.valueOf(s) + faceInfo.getResultIndexStart()); + } + AvRoomDataManager.get().dragons = list; + return list; + } + + private void parseDragonBar(ChatRoomMessage chatRoomMessage) { + if (chatRoomMessage != null) { + if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment(); + // 显示表情在对应的位置 + if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_DRAGON_BAR) { + FaceAttachment faceAttachment = (FaceAttachment) attachment; + List faceReceiveInfos = faceAttachment.getFaceReceiveInfos(); + + if (faceReceiveInfos != null && faceReceiveInfos.size() > 0) { + // 显示动画 + IMNetEaseManager.get().getChatRoomEventObservable() + .onNext(new RoomEvent().setEvent(RoomEvent.DRAGON_BAR_SELF_START).setChatRoomMessage(chatRoomMessage)); + } + } + } + } + } + + public Single clearDragonBar() { + return DragonBallModel.get().clearDragonBar() + .compose(bindToLifecycle()) + .doOnError(throwable -> SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), throwable.getMessage())) + .doOnSuccess(s -> { + openDragonBar(); + AvRoomDataManager.get().haveStartDragon = false; + }); + } + + public Single getDragonBar(FaceInfo faceInfo) { + return DragonBallModel.get().getDragonBar() + .compose(bindToLifecycle()) + .doOnError(throwable -> SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), throwable.getMessage())) + .doOnSuccess(dragonBarInfo -> { + sendDragonBar(faceInfo, dragonBarInfo.getValue(), dragonBarInfo.isIsGen()); + AvRoomDataManager.get().haveStartDragon = true; + }); + } + + public void updateScreen(boolean isCloseScreen) { + String contentText; + if (isCloseScreen) { + ChatRoomMessage firstMsg = IMNetEaseManager.get().getFirstMessageContent(); + IMNetEaseManager.get().addCloseScreenMessages(firstMsg); + if (AvRoomDataManager.get().closeScreenBySAdmin()) { + contentText = "系统检测涉嫌违规,予以关闭公屏消息警告"; + } else { + contentText = "管理员已关闭聊天公屏"; + } + } else { + contentText = "管理员已开启聊天公屏"; + } + RoomInfoAttachment attachment = new RoomInfoAttachment(CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO, + CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_CLOSE_SCREEN); + ChatRoomMessage screenMsg = ChatRoomMessageBuilder.createChatRoomCustomMessage( + String.valueOf(AvRoomDataManager.get().getRoomId()), + attachment + ); + screenMsg.setContent(contentText); + IMNetEaseManager.get().addCloseScreenMessages(screenMsg); + } + + public void kickAi(AiPlayEndEvent aiPlayEndEvent) { + final Map reason = new HashMap<>(2); + reason.put("reason", "kick"); + if (AvRoomDataManager.get().isOnMic(aiPlayEndEvent.aiUid)) { + int micPosition = AvRoomDataManager.get().getMicPosition(aiPlayEndEvent.aiUid); + reason.put("micPosition", micPosition); + reason.put("account", aiPlayEndEvent.aiUid + ""); + IMNetEaseManager.get().downMicroPhoneBySdk(micPosition, null); + } + IMNetEaseManager.get().kickMemberFromRoomBySdk(AvRoomDataManager.get().getRoomId(), + aiPlayEndEvent.aiUid, reason).retry(3).subscribe(); + } + + @SuppressLint("CheckResult") + public void reportToServerMissionThree() { + MentoringRelationshipModel.get() + .reportMissionThree(AvRoomDataManager.get().getRoomUid(), AuthModel.get().getCurrentUid()) + .compose(bindUntilEvent(PresenterEvent.PAUSE)) + .subscribe((s, throwable) -> { + if (throwable == null) { + getMvpView().onMentoringCountingFinish(); + } else { + throwable.printStackTrace(); + } + }); + } + + /** + * 本地更新房主位信息或者关闭离线模式 + */ + @SuppressWarnings("CheckResult") + public void leaveModeCheck() { + isLeaveMode = AvRoomDataManager.get().isLeaveMode(); // 进房缓存离线模式状态 + + if (!AvRoomDataManager.get().isCpRoom() && !AvRoomDataManager.get().isOpenKTV()) { + RoomQueueInfo queueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(-1); + + // 新版管理员首次进房,如果房主位有人,并且房间是离开模式,需要调用接口关闭离开模式(提高关闭离开模式的几率) + if (AvRoomDataManager.get().isManager()) { + + if (queueInfo != null) { + ChatRoomMember chatRoomMember = queueInfo.mChatRoomMember; + if (chatRoomMember != null) { + closeLeaveMode(-1, null); + return; + } + + } + } + + // 第一次进房,离开模式下更新本地房主位ui +// UserModel.get().getUserInfo(AvRoomDataManager.get().getRoomUid()).subscribe((userInfo, throwable) -> { +// if (userInfo != null && AvRoomDataManager.get().mCurrentRoomInfo != null && AvRoomDataManager.get().mCurrentRoomInfo.isLeaveMode()) { +// IMNetEaseManager.get().sendLeaveModeEvent(userInfo.getNick(), userInfo.getGender(), userInfo.getAvatar()); +// } +// }); + + } + + } + + private RoomSettingModel mRoomSettingModel; + + public void closeLeaveMode(int micPosition, String account) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + int position = AvRoomDataManager.get().getMicPosition(AvRoomDataManager.get().getRoomUid()); + if (roomInfo != null && roomInfo.isLeaveMode() && micPosition == position) { + if (mRoomSettingModel == null) + mRoomSettingModel = new RoomSettingModel(); + + // 新版由管理员和房主位上麦用户共同调接口关闭离开模式(提高关闭离开模式成功率,降低接口调用频率); + if (AvRoomDataManager.get().isManager() || String.valueOf(AuthModel.get().getCurrentUid()).equals(account)) { + mRoomSettingModel.leaveModeClose(roomInfo.getUid()).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(String s) { + + if (AvRoomDataManager.get().isShowGiftValue()) + GiftValueMrg.get().requestDownMic(-1, String.valueOf(AuthModel.get().getCurrentUid())); + + } + }); + } + + } + + } + + public void updateLeaveMode() { + if (isLeaveMode == AvRoomDataManager.get().isLeaveMode()) + return; + + isLeaveMode = AvRoomDataManager.get().isLeaveMode(); + + if (!isLeaveMode && AvRoomDataManager.get().isShowGiftValue()) // 礼物值模式下关闭离开模式,本地清除礼物值 + GiftValueMrg.get().handleDownMic(-1, String.valueOf(AvRoomDataManager.get().getRoomUid())); + + } + + /** + * 检查是否关注了这个用户 + * + * @param uid + */ + @SuppressLint("CheckResult") + public void checkFollow(long uid) { + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), uid) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchAndExce()) + .subscribe(new BiConsumer() { + @Override + public void accept(Boolean aBoolean, Throwable throwable) throws Exception { + if (getMvpView() == null) { + return; + } + //如果没有关注 + if (!aBoolean) { + getMvpView().noFollow(); + } + } + }); + } + + /** + * 检查当前用户是否在小世界中 + * + * @param worldId + */ + @SuppressLint("CheckResult") + public void checkMiniWorld(long worldId) { + long uid = AuthModel.get().getCurrentUid(); + MiniWorldModel.getInstance().checkInWorld(worldId, uid) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchAndExce()) + .subscribe(new BiConsumer() { + @Override + public void accept(MiniWorldInWorldInfo miniWorldInWorldInfo, Throwable throwable) throws Exception { + if (getMvpView() == null) { + return; + } + if (throwable == null && miniWorldInWorldInfo != null && !miniWorldInWorldInfo.isInWorld()) { + getMvpView().notInWorld(miniWorldInWorldInfo); + } + } + }); + } + + /** + * 关注房主 + * @param position + * @param ownerUid + */ + public void followOwner(int position, long ownerUid) { + PraiseModel.get().praise(ownerUid,true).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if(getMvpView() == null){ + return; + } + if(throwable==null){ + getMvpView().onFollowSuccess(position); + }else{ + getMvpView().onFollowFail(throwable.getMessage()); + } + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyUserListPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyUserListPresenter.java new file mode 100644 index 000000000..02602eaa3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/HomePartyUserListPresenter.java @@ -0,0 +1,97 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.avroom.view.IHomePartyUserListView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_core.room.model.HomePartyUserListModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public class HomePartyUserListPresenter extends BaseMvpPresenter { + + private final HomePartyUserListModel mHomePartyUserListMode; + + public HomePartyUserListPresenter() { + mHomePartyUserListMode = new HomePartyUserListModel(); + } + + /** + * 分页获取房间成员:第一页包含队列成员,固定成员,游客50人,之后每一页获取游客50人 + * + * @param page 页数 + * @param time 固定成员列表用updateTime, + * 游客列表用进入enterTime, + * 填0会使用当前服务器最新时间开始查询,即第一页,单位毫秒 + */ + public void requestChatMemberByPage(final int page, long time, List oldList) { + mHomePartyUserListMode.getOnLinePageMembers(page, time, oldList, true) + .subscribe(onlineChatMembers -> { + Logger.i("第%1d页成员人数:%2d", page, onlineChatMembers.size()); + if (getMvpView() != null) { + getMvpView().onRequestChatMemberByPageSuccess(onlineChatMembers, page); + } + }, throwable -> { + throwable.printStackTrace(); + Logger.i("第%d页成员人数失败:%s", page, throwable.getMessage()); + if (getMvpView() != null) { + getMvpView().onRequestChatMemberByPageFail(throwable.getMessage(), page); + } + }); + } + + private boolean isRefreshIng; + + /** + * 成员进来刷新在线列表 + * + * @param account + * @param onlineChatMembers + */ + public void onMemberInRefreshData(String account, List onlineChatMembers, final int page) { + if (isRefreshIng) return; + isRefreshIng = true; + Single.timer(5, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .compose(this.bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(aLong -> { + isRefreshIng = false; + if (getMvpView() != null) + getMvpView().onMemberInRefresh(); + }, throwable -> isRefreshIng = false); + + + } + + public void onMemberDownUpMic(String account, boolean isUpMic, List dataList, + final int page) { + mHomePartyUserListMode.onMemberDownUpMic(account, isUpMic, dataList) + .subscribe(onlineChatMembers -> { + if (getMvpView() != null) + getMvpView().onRequestChatMemberByPageSuccess(onlineChatMembers, page); + }); + } + + + public void onUpdateMemberManager(String account, List dataList, + boolean isRemoveManager, final int page) { + mHomePartyUserListMode.onUpdateMemberManager(account, isRemoveManager, dataList) + .subscribe(onlineChatMembers -> { + if (getMvpView() != null) + getMvpView().onRequestChatMemberByPageSuccess(onlineChatMembers, page); + }); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RecordForPKPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RecordForPKPresenter.java new file mode 100644 index 000000000..730871f27 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RecordForPKPresenter.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.yizhuan.erban.avroom.view.IRecordForPKView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRecordInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKRecordListInfo; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/12/29 + */ +public class RecordForPKPresenter extends BaseMvpPresenter + implements LoadPageDataHelper.LoadData> { + + LoadPageDataHelper> loadPageDataHelper; + + public RecordForPKPresenter() { + loadPageDataHelper = new LoadPageDataHelper>(this); + } + + @Override + public Single> loadData(int curPage) { + RoomInfo currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoomInfo == null) { + return Single.error(new Throwable("没有当前房间信息")); + } + return PkModel.get().loadPKRecordList( + currentRoomInfo.getUid(), + curPage, + Constants.PAGE_SIZE + ) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(PKRecordListInfo pkRecordListInfo) throws Exception { + return Single.just(pkRecordListInfo.getRecords()); + } + }); + + } + + public Single> refreshData() { + return loadPageDataHelper.refreshData(); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomBlackPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomBlackPresenter.java new file mode 100644 index 000000000..6f28993be --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomBlackPresenter.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.avroom.view.IRoomBlackView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.room.model.RoomBaseModel; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; + +/** + *

+ * + * @author jiahui + * @date 2017/12/19 + */ +public class RoomBlackPresenter extends BaseMvpPresenter { + private final RoomBaseModel mRoomBaseModel; + + public RoomBlackPresenter() { + mRoomBaseModel = new RoomBaseModel(); + } + + public void queryBlackList(int limit) { + mRoomBaseModel.queryBlackList(limit) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>() { + @Override + public void accept(List chatRoomMemberList) throws Exception { + if (getMvpView() != null) + getMvpView().queryBlackListSuccess(chatRoomMemberList); + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + if (getMvpView() != null) + getMvpView().queryBlackListFail(); + } + }); + } + + /** + * 拉黑操作 + * + * @param roomId + * @param account + * @param mark true,拉黑,false:移除拉黑 + */ + public void markBlackList(long roomId, String account, final boolean mark) { + mRoomBaseModel.markBlackList(roomId, String.valueOf(account), mark, new CallBack() { + @Override + public void onSuccess(ChatRoomMember data) { + if (getMvpView() != null) + getMvpView().makeBlackListSuccess(data, mark); + } + + @Override + public void onFail(int code, String error) { + if (getMvpView() != null) + getMvpView().makeBlackListFail(code, error, mark); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomCharmRankingPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomCharmRankingPresenter.java new file mode 100644 index 000000000..920041470 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomCharmRankingPresenter.java @@ -0,0 +1,63 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.yizhuan.erban.avroom.view.IRoomCharmRankingListView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeDataInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomContributeUserInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_core.room.model.RoomCharmModel; +import com.yizhuan.xchat_android_core.room.model.inteface.IRoomCharmModel; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class RoomCharmRankingPresenter extends BaseRoomRankPresenter { + private IRoomCharmModel model; + + public RoomCharmRankingPresenter() { + this.model = RoomCharmModel.get(); + } + + public void getRoomCharmList(long uid, String type) { + model.getRoomCharmList( + String.valueOf(uid), + Constants.PAGE_START, + Constants.PAGE_SIZE, + type + ).compose(bindToLifecycle()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(ServiceResult roomContributeDataInfoServiceResult) { + List list = new ArrayList<>(); + if (roomContributeDataInfoServiceResult.isSuccess()){ + ArrayList dataInfoList = roomContributeDataInfoServiceResult.getData().getRankings(); + list = handleList(dataInfoList); + } + if (list == null || list.size() == 0) { + list = new ArrayList<>(); + list.add(completeTopThree(new ArrayList<>())); + } + if (getMvpView() != null) { + getMvpView().roomCharmListSuccess(list); + } + + } + + @Override + public void onError(Throwable e) { + if (getMvpView() != null) + getMvpView().roomCharListFail(e.getMessage()); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomContributeListPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomContributeListPresenter.java new file mode 100644 index 000000000..788595880 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomContributeListPresenter.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; + +import com.yizhuan.erban.avroom.view.IRoomContributeListView; +import com.yizhuan.xchat_android_core.room.model.RoomContributeListModel; + +/** + * Created by MadisonRong on 25/04/2018. + */ + +public class RoomContributeListPresenter extends BaseRoomRankPresenter { + + private RoomContributeListModel model; + + public RoomContributeListPresenter() { + this.model = RoomContributeListModel.get(); + } + + @SuppressLint("CheckResult") + public void getSingleRoomRanking(int page, String type) { + model.getSingleRoomRanking(page, type) + .subscribe((roomContributeDataInfoServiceResult, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + getMvpView().getSingleRakingFail(-1, "获取榜单出现异常"); + } else if (roomContributeDataInfoServiceResult != null && roomContributeDataInfoServiceResult.isSuccess()) { + getMvpView().getSingleRankingSuccess(roomContributeDataInfoServiceResult.getData()); + } else if (roomContributeDataInfoServiceResult != null && !roomContributeDataInfoServiceResult.isSuccess()) { + getMvpView().getSingleRakingFail(roomContributeDataInfoServiceResult.getCode(), + roomContributeDataInfoServiceResult.getMessage()); + } else { + getMvpView().getSingleRakingFail(-1, "获取榜单出现异常"); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomInvitePresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomInvitePresenter.java new file mode 100644 index 000000000..5f48e66d1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomInvitePresenter.java @@ -0,0 +1,91 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; +import android.util.SparseArray; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.avroom.view.IRoomInviteView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.model.RoomInviteModel; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; + +import java.util.List; +import java.util.ListIterator; +import java.util.Objects; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + *

+ * + * @author jiahui + * @date 2017/12/21 + */ +public class RoomInvitePresenter extends BaseMvpPresenter { + + private RoomInviteModel mRoomInviteModel; + + public RoomInvitePresenter() { + mRoomInviteModel = new RoomInviteModel(); + } + + /** + * 分页获取房间成员:第一页包含固定在线成员,游客50人,之后每一页获取游客50人 + * + * @param page 页数 + * @param time 固定成员列表用updateTime, + * 游客列表用进入enterTime, + * 填0会使用当前服务器最新时间开始查询,即第一页,单位毫秒 + */ + @SuppressLint("CheckResult") + public void requestChatMemberByPage(final int page, long time) { + mRoomInviteModel.getPageMembers(page, time) + .map(chatRoomMemberList -> { + SparseArray queueInfoSparseArray = AvRoomDataManager.get().mMicQueueMemberMap; + int size; + if (queueInfoSparseArray == null || (size = queueInfoSparseArray.size()) <= 0) { + return chatRoomMemberList; + } + //移除麦上人员 + ChatRoomMember chatRoomMember; + ListIterator iterator = chatRoomMemberList.listIterator(); + for (; iterator.hasNext(); ) { + chatRoomMember = iterator.next(); + //过滤超管 + if (SuperAdminUtil.isSuperAdmin(chatRoomMember)) { + iterator.remove(); + } else { + for (int i = 0; i < size; i++) { + RoomQueueInfo roomQueueInfo = queueInfoSparseArray.valueAt(i); + if (roomQueueInfo.mChatRoomMember != null + && Objects.equals(chatRoomMember.getAccount(), roomQueueInfo.mChatRoomMember.getAccount())) { + iterator.remove(); + } + } + } + } + return chatRoomMemberList; + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>() { + @Override + public void accept(List chatRoomMemberList) throws Exception { + if (getMvpView() != null) { + getMvpView().onRequestMemberByPageSuccess(chatRoomMemberList, page); + } + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + throwable.printStackTrace(); + if (getMvpView() != null) { + getMvpView().onRequestChatMemberByPageFail(throwable.getMessage(), page); + } + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomManagerPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomManagerPresenter.java new file mode 100644 index 000000000..bd6608d86 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomManagerPresenter.java @@ -0,0 +1,114 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; +import android.text.TextUtils; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.avroom.view.IRoomManagerView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.model.RoomBaseModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +/** + *

+ * + * @author jiahui + * @date 2017/12/19 + */ +public class RoomManagerPresenter extends BaseMvpPresenter { + + private final RoomBaseModel mRoomBaseModel; + + public RoomManagerPresenter() { + mRoomBaseModel = new RoomBaseModel(); + } + + @SuppressLint("CheckResult") + public void queryManagerList(int limit) { + mRoomBaseModel.queryManagerList(limit) + .observeOn(Schedulers.io()) + .flatMap((Function, SingleSource>>) chatRoomMembers -> { + List uids = new ArrayList<>(); + for (ChatRoomMember member : chatRoomMembers) { + if (member != null && !TextUtils.isEmpty(member.getAccount())) { + uids.add(member.getAccount()); + } + } + return Single.zip( + UserModel.get().loadUserInfoByUids(uids), + Single.just(chatRoomMembers), + (userInfos, paramList) -> { + Map map = new HashMap<>(); + for (UserInfo info : userInfos) { + if (info != null && info.isSuperAdmin()) { + map.put(String.valueOf(info.getUid()), true); + } + } + Iterator iterator = paramList.iterator(); + while (iterator.hasNext()) { + ChatRoomMember member = iterator.next(); + if (member != null + && !TextUtils.isEmpty(member.getAccount()) + && map.containsKey(member.getAccount())) { + iterator.remove(); + } + } + return paramList; + }); + }) + .observeOn(AndroidSchedulers.mainThread()) + .compose(this.bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(chatRoomMemberList -> { + AvRoomDataManager.get().mRoomManagerList = chatRoomMemberList; + if (getMvpView() != null) { + getMvpView().queryManagerListSuccess(chatRoomMemberList); + } + }, throwable -> { + if (getMvpView() != null) { + getMvpView().queryManagerListFail(); + } + }); + + } + + /** + * 设置管理员 + * + * @param roomId + * @param account + * @param mark true:设置管理员 ,false:移除管理员 + */ + public void markManagerList(long roomId, String account, boolean mark) { + mRoomBaseModel.markManagerList(roomId, account, mark, new CallBack() { + @Override + public void onSuccess(ChatRoomMember data) { + if (getMvpView() != null) { + getMvpView().markManagerListSuccess(data); + } + } + + @Override + public void onFail(int code, String error) { + if (getMvpView() != null) { + getMvpView().markManagerListFail(code, error); + } + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomRankHalfHourPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomRankHalfHourPresenter.java new file mode 100644 index 000000000..9fdb0f5c2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomRankHalfHourPresenter.java @@ -0,0 +1,104 @@ +package com.yizhuan.erban.avroom.presenter; + +import com.yizhuan.erban.avroom.adapter.RoomRankHalfHourListAdapter; +import com.yizhuan.erban.avroom.fragment.IRoomRankHalfHourView; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourDataInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankHalfHourRankInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_core.room.model.RoomRankModel; +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class RoomRankHalfHourPresenter extends AbstractMvpPresenter { + + public void getRankListInfo() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + RoomRankModel.get() + .getRoomRankHalfHourList(roomInfo.getUid()) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(RoomRankHalfHourDataInfo roomRankHalfHourDataInfo) { + if (roomRankHalfHourDataInfo != null) { + + if (mMvpView != null) { + if (roomRankHalfHourDataInfo.getMe() != null) { + mMvpView.showMeInfo(roomRankHalfHourDataInfo.getMe()); + } else + mMvpView.showMeInfo(null); + + transformData(roomRankHalfHourDataInfo.getRankVoList()); + } + + } else { + if (mMvpView != null) + mMvpView.loadDataFailure(); + } + } + + @Override + public void onError(Throwable e) { + if (mMvpView != null) + mMvpView.loadDataFailure(); + SingleToastUtil.showToast(e.getMessage()); + } + }); + } + } + + private void transformData(List dataInfoList) { + + if (dataInfoList != null) { + List top3rankInfo; + if (dataInfoList.size() >= 3) { + top3rankInfo = dataInfoList.subList(0, 3); + } else { + top3rankInfo = dataInfoList; + } + mMvpView.showTop3Info(top3rankInfo); + // 第四名开始以后的信息 + List otherRankInfo = new ArrayList<>(); + if (dataInfoList.size() > 3) { + + for (int i = 3; i < dataInfoList.size(); i++) { + RoomRankHalfHourRankInfo info = dataInfoList.get(i); + RoomRankMultiItem item = new RoomRankMultiItem(); + item.setItemType(RoomRankMultiItem.TYPE_LINEAR); + item.setData(info); + otherRankInfo.add(item); + + } + + } + +// RoomRankMultiItem item = new RoomRankMultiItem(); +// item.setItemType(RoomRankHalfHourListAdapter.TYPE_TIPS); +// otherRankInfo.add(item); + mMvpView.showRankListInfo(otherRankInfo); + + } else { + mMvpView.showTop3Info(null); + + List otherRankInfo = new ArrayList<>(); + RoomRankMultiItem item = new RoomRankMultiItem(); + item.setItemType(RoomRankMultiItem.TYPE_EMPTY); + otherRankInfo.add(item); + mMvpView.showRankListInfo(otherRankInfo); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomSettingPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomSettingPresenter.java new file mode 100644 index 000000000..0d571a346 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/RoomSettingPresenter.java @@ -0,0 +1,234 @@ +package com.yizhuan.erban.avroom.presenter; + + +import android.annotation.SuppressLint; + +import com.yizhuan.erban.avroom.view.IRoomSettingView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomSettingTabInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.GiftValueModel; +import com.yizhuan.xchat_android_core.room.model.MicQueueModel; +import com.yizhuan.xchat_android_core.room.model.RoomSettingModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import java.util.List; + +import io.reactivex.functions.BiConsumer; + +/** + *

+ * + * @author jiahui + * @date 2017/12/15 + */ +public class RoomSettingPresenter extends BaseMvpPresenter { + + private static final String TAG = "RoomSettingPresenter"; + + private final RoomSettingModel model; + + public RoomSettingPresenter() { + model = new RoomSettingModel(); + } + + @SuppressLint("CheckResult") + public void requestTagAll() { + model.requestTagAll(AuthModel.get().getTicket()) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List listServiceResult, + Throwable throwable) throws Exception { + IRoomSettingView roomSettingView = getMvpView(); + if (roomSettingView == null) return; + if (throwable != null) { + roomSettingView.onResultRequestTagAllFail(throwable.getMessage()); + } else { + roomSettingView.onResultRequestTagAllSuccess(listServiceResult); + } + } + }); + } + + public void requestRoomInfo(long uid) { + model.requestRoomInfoFromService(uid+"", new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + if (getMvpView() != null) { + getMvpView().reQuestRoomInfo(data); + } + } + + @Override + public void onFail(int code, String error) { + + } + }); + } + + @SuppressLint("CheckResult") + public void updateGiftEffect(RoomInfo roomInfo){ + IMNetEaseManager.get().updateGiftEffect(roomInfo.getRoomId()) + .subscribe((chatRoomMessage,throwable) -> { + if (!AvRoomDataManager.get().haveSelfChange) { + IMNetEaseManager.get().getChatRoomEventObservable().onNext(new RoomEvent() + .setEvent(RoomEvent.RECEIVE_MSG) + .setChatRoomMessage(chatRoomMessage)); + } + }); + } + + @SuppressLint("CheckResult") + public void updateAudiouality(RoomInfo roomInfo){ + IMNetEaseManager.get().updateAudiouality(roomInfo.getRoomId()) + .subscribe((chatRoomMessage,throwable) -> { + IMNetEaseManager.get().getChatRoomEventObservable().onNext(new RoomEvent() + .setEvent(RoomEvent.RECEIVE_MSG) + .setChatRoomMessage(chatRoomMessage)); + }); + } + + @SuppressLint("CheckResult") + public void openQueuingMicMode() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + MicQueueModel.get() + .openQueuingMicMode(roomInfo.getUid()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + getMvpView().onFailToToast(throwable.getMessage()); + } else { + getMvpView().onSuccessToFinish(); + } + }); + } + + @SuppressLint("CheckResult") + public void closeQueuingMicMode() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + MicQueueModel.get() + .closeQueuingMicMode(roomInfo.getUid()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + getMvpView().onFailToToast(throwable.getMessage()); + } else { + getMvpView().onSuccessToFinish(); + } + }); + } + + public void openRoomPureMode() { + updateRoomPureMode(true); + } + + public void closeRoomPureMode() { + updateRoomPureMode(false); + } + + public void leaveModeOpen(long roomUid) { + model.leaveModeOpen(roomUid).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.leaveModeOpenFail(error); + + } + + @Override + public void onSuccess(String s) { + if (mMvpView != null) + mMvpView.leaveModeOpenSuccess(); + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_OPEN_LEAVE_MODE, + "开启离开模式"); + updateRoomOwnerMic(); + + } + }); + + } + + public void leaveModeClose(long roomUid) { + model.leaveModeClose(roomUid).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.leaveModeCloseFail(error); + + } + + @Override + public void onSuccess(String s) { + if (mMvpView != null) + mMvpView.leaveModeCloseSuccess(); + + } + }); + + } + + @SuppressLint("CheckResult") + private void updateRoomPureMode(boolean isPureMode) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (AvRoomDataManager.get().isRoomOwner()) { + model.updateRoomPureModeForOwner(roomInfo.getTitle(), roomInfo.getRoomDesc(), + roomInfo.getIntroduction(), roomInfo.getRoomPwd(), roomInfo.getRoomTag(), + roomInfo.getTagId(), roomInfo.isHasAnimationEffect(), + roomInfo.getAudioQuality(), roomInfo.getLimitType(), isPureMode) + .compose(bindToLifecycle()) + .subscribe((roomInfo1, throwable) -> { + if (throwable == null) { + getMvpView().onUpdateRoomPureMode(roomInfo1); + } else { + getMvpView().onResultRequestTagAllFail(throwable.getMessage()); + } + }); + } else if (AvRoomDataManager.get().isRoomAdmin()) { + model.updateRoomPureMode(roomInfo.getUid(), roomInfo.getTitle(), roomInfo.getRoomDesc(), + roomInfo.getIntroduction(), roomInfo.getRoomPwd(), roomInfo.getRoomTag(), roomInfo.getTagId(), + roomInfo.isHasAnimationEffect(), roomInfo.getAudioQuality(), isPureMode) + .compose(bindToLifecycle()) + .subscribe((roomInfo1, throwable) -> { + if (throwable == null) { + getMvpView().onUpdateRoomPureMode(roomInfo1); + } else { + getMvpView().onResultRequestTagAllFail(throwable.getMessage()); + } + }); + } + } + + @SuppressWarnings("CheckResult") + private void updateRoomOwnerMic() { + RoomInfo roomInfo1 = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo1 == null) + return; + + UserModel.get().getUserInfo(roomInfo1.getUid()).subscribe((userInfo, throwable) -> { + if (userInfo != null) + IMNetEaseManager.get().leaveModeMessage(roomInfo1.getRoomId(), userInfo.getNick(), userInfo.getGender(), userInfo.getAvatar()).subscribe(); + }); + + if (roomInfo1.isShowGiftValue()) + GiftValueModel.get().upMic(AuthModel.get().getCurrentUid(), -1).subscribe(); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/MyRecommendCardActivity.java b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/MyRecommendCardActivity.java new file mode 100644 index 000000000..08a0410aa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/MyRecommendCardActivity.java @@ -0,0 +1,117 @@ +package com.yizhuan.erban.avroom.recommendcard; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.module_hall.hall.view.indicator.StatisticsIndicatorAdapter; +import com.yizhuan.erban.module_hall.income.presenter.IncomeStatisticsPresenter; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.room.recommendpos.bean.RcmdCardType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * 我的推荐位 + * Created by lvzebiao on 2019/1/30. + */ + +public class MyRecommendCardActivity extends BaseActivity { + + @BindView(R.id.view_pager) + ViewPager viewPager; + @BindView(R.id.indicator) + MagicIndicator indicator; + + private List fragmentList = new ArrayList<>(); + + public static void start(Context context) { + Intent intent = new Intent(context, MyRecommendCardActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_my_recommend_card); + ButterKnife.bind(this); + initTitleBar(R.string.my_recommend_position_text); + initIndicator(); + //未使用 + fragmentList.add(RecommendCardFragment.newInstance(RcmdCardType.UN_USE)); + //使用中 + fragmentList.add(RecommendCardFragment.newInstance(RcmdCardType.USING)); + //已使用 + fragmentList.add(RecommendCardFragment.newInstance(RcmdCardType.HAS_USED)); + //已失效 + fragmentList.add(RecommendCardFragment.newInstance(RcmdCardType.INVALID)); + viewPager.setAdapter(new CardPagerAdapter(getSupportFragmentManager())); + } + + @Override + public void initTitleBar(int title) { + super.initTitleBar(title); + if (mTitleBar != null) { + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_rcmd_help) { + @Override + public void performAction(View view) { + CommonWebViewActivity.start(context, UriProvider.JAVA_WEB_URL + + "/modules/recommend-card/help.html"); + } + }); + } + } + + private void initIndicator() { + List tagList = new ArrayList<>(); + tagList.add("未使用"); + tagList.add("使用中"); + tagList.add("已使用"); + tagList.add("已失效"); + + StatisticsIndicatorAdapter adapter = new StatisticsIndicatorAdapter(tagList, 0); + adapter.setOnItemSelectListener(position -> viewPager.setCurrentItem(position)); + CommonNavigator navigator = new CommonNavigator(this); + navigator.setAdapter(adapter); + navigator.setAdjustMode(true); + indicator.setNavigator(navigator); + ViewPagerHelper.bind(indicator, viewPager); + + } + + class CardPagerAdapter extends FragmentStatePagerAdapter { + + public CardPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardFragment.java new file mode 100644 index 000000000..0cfac3a11 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardFragment.java @@ -0,0 +1,131 @@ +package com.yizhuan.erban.avroom.recommendcard; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.base.list.BaseViewHolder; +import com.yizhuan.erban.base.list.CommonAdapter; +import com.yizhuan.erban.base.list.IRecyclerListener; +import com.yizhuan.erban.base.list.RefreshRecyclerView; +import com.yizhuan.xchat_android_core.web.bean.H5NotifyData; +import com.yizhuan.erban.ui.webview.event.H5NotifyClientEvent; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.HorizontalDecoration; +import com.yizhuan.xchat_android_core.room.recommendpos.RecommendCardModel; +import com.yizhuan.xchat_android_core.room.recommendpos.bean.RcmdCardType; +import com.yizhuan.xchat_android_core.room.recommendpos.bean.RecommendCard; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; +import io.reactivex.Single; + +/** + * 推荐位的fragment + * Created by lvzebiao on 2019/1/30. + */ + +public class RecommendCardFragment extends BaseFragment implements IRecyclerListener{ + + @BindView(R.id.refresh_recycler_view) + RefreshRecyclerView refreshRecyclerView; + Unbinder unbinder; + + private int cardType; + /**如果为ture,onResume的时候要刷新*/ + private boolean refreshWhenOnResume = false; + + public static RecommendCardFragment newInstance(int cardType) { + Bundle bundle = new Bundle(); + bundle.putInt(RcmdCardType.EXTRA_TYPE, cardType); + RecommendCardFragment fragment = new RecommendCardFragment(); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void initiate() { + if (getArguments() != null) { + cardType = getArguments().getInt(RcmdCardType.EXTRA_TYPE, RcmdCardType.INVALID); + } + refreshRecyclerView.addItemDecoration(new HorizontalDecoration(ScreenUtil.dip2px(5), false, true)); + refreshRecyclerView.setRecyclerListener(this, this); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = super.onCreateView(inflater, container, savedInstanceState); + unbinder = ButterKnife.bind(this, mView); + EventBus.getDefault().register(this); + return mView; + } + + @Override + public void onDestroyView() { + EventBus.getDefault().unregister(this); + super.onDestroyView(); + unbinder.unbind(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_recommend_card; + } + + @Override + public CommonAdapter createAdapter(Context context) { + return new RecommendCardListAdapter(R.layout.item_recommend_card, cardType); + } + + @Override + public RecyclerView.LayoutManager createLayoutManager() { + return new LinearLayoutManager(mContext); + } + + @Override + public Single> getSingle(int page, int size) { + return RecommendCardModel.get().getBagList(cardType, page, size); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRefreshData(H5NotifyClientEvent event) { + if (event.getData() == null) { + return; + } + H5NotifyData notifyData = H5NotifyData.jsonToBean(event.getData()); + if (notifyData == null) { + return; + } + if (notifyData.getType() == H5NotifyData.TYPE_REFRESH_RECOMMEND_POS_DATA) { + //未使用,和已使用界面需要刷新 || cardType == RcmdCardType.HAS_USED + if (cardType == RcmdCardType.UN_USE || cardType == RcmdCardType.HAS_USED) { + refreshWhenOnResume = true; + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (refreshWhenOnResume) { + refreshWhenOnResume = false; + refreshRecyclerView.onRefreshList(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardListAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardListAdapter.java new file mode 100644 index 000000000..08cc88c7a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/recommendcard/RecommendCardListAdapter.java @@ -0,0 +1,106 @@ +package com.yizhuan.erban.avroom.recommendcard; + +import android.content.Context; +import android.text.style.AbsoluteSizeSpan; +import android.view.View; + +import com.coorchice.library.SuperTextView; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.base.list.BaseViewHolder; +import com.yizhuan.erban.base.list.CommonAdapter; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.room.recommendpos.bean.RcmdCardType; +import com.yizhuan.xchat_android_core.room.recommendpos.bean.RecommendCard; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +/** + * 推荐卡列表 + * Created by lvzebiao on 2019/1/30. + */ + +public class RecommendCardListAdapter extends CommonAdapter { + + private int cardType; + + public RecommendCardListAdapter(int layoutId, int cardType) { + super(layoutId); + this.cardType = cardType; + } + + @Override + protected void convert(BaseViewHolder holder, RecommendCard item) { + holder.setText(R.id.tv_time_title, item.getCardName()); + + MessageView.SpannableBuilder builder = new MessageView.SpannableBuilder(null); + builder.append("X", new AbsoluteSizeSpan(ScreenUtil.sp2px(12))) + .append(String.valueOf(item.getCount())); + holder.setText(R.id.tv_card_count, builder.build()); + SuperTextView stv_card_op = holder.getView(R.id.stv_card_op); + Context context = stv_card_op.getContext(); + holder.setText(R.id.tv_card_valid_time, "使用时间 2019.01.13 20:00-21:00"); + StringBuilder validTimeBuild = new StringBuilder(); + //有效期格式 使用时间开始的格式 + String validEndFormat = "year.mon.day hour:min"; + String useEndFormat = "-hour:min"; + if (cardType == RcmdCardType.UN_USE) { + holder.setBackgroundRes(R.id.scl_container, R.drawable.bg_recommend_card_vaild); + holder.setVisible(R.id.iv_card_status, false); + holder.setGone(R.id.ll_valid_day_container, true); + //有效期 + holder.setText(R.id.tv_card_valid_days, item.getDays() + "天"); + stv_card_op.setVisibility(View.VISIBLE); + stv_card_op.setSolid(context.getResources().getColor(R.color.white)); + stv_card_op.setText("立即使用"); + stv_card_op.setClickable(true); + holder.setGone(R.id.view_white_line, false); + holder.setGone(R.id.tv_card_count, true); + validTimeBuild.append("有效期至 ") + .append(TimeUtils.getFormatTimeString(item.getValidEndTime(), validEndFormat)); + stv_card_op.setOnClickListener(v ->{ + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.h5_recommend_used, "使用推荐卡"); + UIHelper.showRecommendPosH5(context); + }); + } else if (cardType == RcmdCardType.USING) { + holder.setBackgroundRes(R.id.scl_container, R.drawable.bg_recommend_card_vaild); + holder.setVisible(R.id.iv_card_status, false); + stv_card_op.setVisibility(View.VISIBLE); + stv_card_op.setSolid(context.getResources().getColor(R.color.white_transparent_50)); + stv_card_op.setText("使用中"); + stv_card_op.setClickable(false); + holder.setGone(R.id.ll_valid_day_container, false); + holder.setGone(R.id.view_white_line, true); + holder.setGone(R.id.tv_card_count, false); + validTimeBuild.append("使用时间 ") + .append(TimeUtils.getFormatTimeString(item.getUseStartTime(), validEndFormat)) + .append(TimeUtils.getFormatTimeString(item.getUseEndTime(), useEndFormat)); + } else if (cardType == RcmdCardType.HAS_USED) { + holder.setBackgroundRes(R.id.scl_container, R.drawable.bg_recommend_card_invaild); + holder.setVisible(R.id.iv_card_status, true); + holder.setImageResource(R.id.iv_card_status, R.drawable.ic_card_has_used); + stv_card_op.setVisibility(View.GONE); + holder.setGone(R.id.ll_valid_day_container, false); + holder.setGone(R.id.view_white_line, true); + holder.setGone(R.id.tv_card_count, false); + validTimeBuild.append("使用时间 ") + .append(TimeUtils.getFormatTimeString(item.getUseStartTime(), validEndFormat)) + .append(TimeUtils.getFormatTimeString(item.getUseEndTime(), useEndFormat)); + } else { + holder.setBackgroundRes(R.id.scl_container, R.drawable.bg_recommend_card_invaild); + holder.setVisible(R.id.iv_card_status, true); + holder.setImageResource(R.id.iv_card_status, R.drawable.ic_card_invalid); + stv_card_op.setVisibility(View.GONE); + holder.setGone(R.id.ll_valid_day_container, false); + holder.setGone(R.id.view_white_line, true); + holder.setGone(R.id.tv_card_count, true); + validTimeBuild.append("有效期至 "); + validTimeBuild.append(TimeUtils.getFormatTimeString(item.getValidEndTime(), validEndFormat)); + } + holder.setText(R.id.tv_card_valid_time, validTimeBuild.toString()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IAvRoomView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IAvRoomView.java new file mode 100644 index 000000000..13d20adc5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IAvRoomView.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.avroom.view; + + +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/11 + */ +public interface IAvRoomView extends IMvpBaseView { + + void requestRoomInfoSuccessView(RoomInfo roomInfo); + + void requestRoomInfoFailView(Throwable throwable); + + /** + * 进去房间成功 + */ + void enterRoomSuccess(); + + /** + * 进入房间失败 + */ + void enterRoomFail(int code, String error); + + /** + * 显示结束直播界面 + */ + void showFinishRoomView(); + + /** + * 显示黑名单进入房间错误页面 + */ + void showBlackEnterRoomView(); + + /** + * 取消loading弹窗 + */ + void dismissLoadingDialog(); + + /** + * 获取活动信息成功 + */ + void onGetActionDialog(List actionDialogInfoList); + + /** + * 获取活动信息失败 + */ + void onGetActionDialogError(String error); + + /** + * 退出房间 + * + * @param currentRoomInfo + */ + void exitRoom(RoomInfo currentRoomInfo); + + /** + * 定时拉取人数成功 + * + * @param onlineNumber + */ + void onRoomOnlineNumberSuccess(int onlineNumber); + + /** + * 成功获取怪兽信息 + * @param monsterInfo + */ + void getMonsterInfoSuccess(MonsterInfo monsterInfo); + + /** + * 获取怪兽信息失败 + * @param error + */ + void getMonsterInfoFail(String error); + + /** + * 恢复最小化的时候 处理青少年时长限制 + * @param throwable - + */ + void recoverRoomMinWhenPmLimit(Throwable throwable); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/ICreatePKView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/ICreatePKView.java new file mode 100644 index 000000000..5cb091816 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/ICreatePKView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.avroom.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/12/28 + */ +public interface ICreatePKView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyUserListView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyUserListView.java new file mode 100644 index 000000000..09a6c6d09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyUserListView.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.avroom.view; + + + +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public interface IHomePartyUserListView extends IMvpBaseView { + void onRequestChatMemberByPageSuccess(List memberList, int page); + + void onRequestChatMemberByPageFail(String errorStr, int page); + + void onMemberInRefresh(); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyView.java new file mode 100644 index 000000000..043453d0d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IHomePartyView.java @@ -0,0 +1,106 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.miniworld.bean.MiniWorldInWorldInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + *

轰趴房View层

+ * + * @author jiahui + * @date 2017/12/8 + */ +public interface IHomePartyView extends IMvpBaseView { + + void resultLoadNormalMembers(List chatRoomMemberList); + + /** + * 点击麦上用户头像,显示操作对话框 + * + * @param buttonItemList + */ + void showMicAvatarClickDialog(List buttonItemList, String uid); + + /** + * 点击麦上头像,显示用户信息对话框 + * + * @param uId + */ + void showMicAvatarUserInfoDialog(String uId); + + /** + * 被踢下麦成功 + */ + void kickDownMicroPhoneSuccess(); + + /** + * 麦上没人点击坑位处理 + * + * @param roomMicInfo 坑位信息 + * @param micPosition + * @param currentUid + */ + void showOwnerClickDialog(RoomMicInfo roomMicInfo, int micPosition, long currentUid); + + //玩龙珠时换坑 + void onDragonBarChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo); + + /** + * 礼物值模式下换麦 + */ + void onGiftValueChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo); + + /** + * 断网重连回调 + */ + void chatRoomReConnectView(); + + void onKtvChangeMic(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo); + + void showToast(String msg); + + void onMentoringCountingFinish(); + + void onSendMsgSuccess(); + + /** + * 上麦请求 + * + * @param micPosition + * @param currentUid + * @param b + */ + void toUpMicroPhone(int micPosition, String currentUid, boolean b); + + /** + * 没有关注用户的监听 + */ + void noFollow(); + + /** + * 没有加入这个小世界 + * + * @param miniWorldInWorldInfo + */ + void notInWorld(@NotNull MiniWorldInWorldInfo miniWorldInWorldInfo); + + /** + * 关注成功 + * @param position + */ + void onFollowSuccess(int position); + + /** + * 关注失败 + * @param msg + */ + void onFollowFail(String msg); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatConsumeView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatConsumeView.java new file mode 100644 index 000000000..1b069c051 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatConsumeView.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.avroom.view; + + + +import com.yizhuan.xchat_android_core.room.queue.bean.RoomConsumeInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/24 + */ +public interface ILightChatConsumeView extends IMvpBaseView { + + void onGetRoomConsumeListSuccess(List roomConsumeInfos); + + void onGetRoomConsumeListFail(String error); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatOnlineView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatOnlineView.java new file mode 100644 index 000000000..0c1e46586 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatOnlineView.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.avroom.view; + +import android.util.SparseArray; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.ui.widget.ButtonItem; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/25 + */ +public interface ILightChatOnlineView extends IHomePartyUserListView { + /** + * 获取按钮相关操作集合 + * + * @param chatRoomMember 操作当前的成员 + * @param position 麦序 + * @return + */ + SparseArray getButtonItemList(ChatRoomMember chatRoomMember, int position); + + /** + * 显示列表点击对话框 + * + * @param buttonItemList + */ + void showItemClickDialog(List buttonItemList); + + /** + * 显示用户信息对话框 + * + * @param account + */ + void showUserInfoDialog(String account); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatRoomView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatRoomView.java new file mode 100644 index 000000000..7d683ecac --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/ILightChatRoomView.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.avroom.view; + + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + *

轻聊房

+ * + * @author jiahui + * @date 2017/12/24 + */ +public interface ILightChatRoomView extends IMvpBaseView { + /** + * 赞操作成功 + * + * @param type type:喜欢操作类型,1是喜欢,2是取消喜欢,必填 + * @param likedUid 被点赞人uid,必填 + */ + void praiseSuccess(int type, long likedUid); + + /** + * 赞操作失败 + * + * @param type type:喜欢操作类型,1是喜欢,2是取消喜欢,必填 + * @param likedUid 被点赞人uid,必填 + */ + void praiseFail(int type, long likedUid); + + /** 被踢下麦成功 */ + void kickDownMicroPhoneSuccess(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRecordForPKView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRecordForPKView.java new file mode 100644 index 000000000..015ef6f41 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRecordForPKView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.avroom.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/12/29 + */ +public interface IRecordForPKView extends IMvpBaseView { + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomBlackView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomBlackView.java new file mode 100644 index 000000000..2bcc8b5f7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomBlackView.java @@ -0,0 +1,43 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/19 + */ +public interface IRoomBlackView extends IMvpBaseView { + /** + * 获取黑名单列表成功 + * + * @param chatRoomMemberList + */ + void queryBlackListSuccess(List chatRoomMemberList); + + /** + * 获取黑名单列表失败 + */ + void queryBlackListFail(); + + /** + * 拉黑操作成功 + * + * @param chatRoomMember + * @param mark true,拉黑,false:移除拉黑 + */ + void makeBlackListSuccess(ChatRoomMember chatRoomMember, boolean mark); + + /** + * 拉黑操作失败 + * + * @param code + * @param error + * @param mark true,拉黑,false:移除拉黑 + */ + void makeBlackListFail(int code, String error, boolean mark); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomCharmRankingListView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomCharmRankingListView.java new file mode 100644 index 000000000..91a5476f6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomCharmRankingListView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.avroom.view; + +import com.yizhuan.xchat_android_core.room.bean.RoomRankMultiItem; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +public interface IRoomCharmRankingListView extends IMvpBaseView { + + void roomCharmListSuccess(List list); + void roomCharListFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomContributeListView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomContributeListView.java new file mode 100644 index 000000000..a888d8569 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomContributeListView.java @@ -0,0 +1,16 @@ +package com.yizhuan.erban.avroom.view; + + +import com.yizhuan.xchat_android_core.room.bean.RoomContributeDataInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * Created by MadisonRong on 25/04/2018. + */ + +public interface IRoomContributeListView extends IMvpBaseView { + + void getSingleRankingSuccess(RoomContributeDataInfo roomContributeDataInfo); + + void getSingleRakingFail(int errorCode, String errorMsg); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomInviteView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomInviteView.java new file mode 100644 index 000000000..17f129f4b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomInviteView.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/21 + */ +public interface IRoomInviteView extends IHomePartyUserListView { + + void onRequestMemberByPageSuccess(List memberList, int page); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomManagerView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomManagerView.java new file mode 100644 index 000000000..5bf3d1722 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomManagerView.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/19 + */ +public interface IRoomManagerView extends IRoomMemberView { + + void queryManagerListSuccess(List chatRoomMemberList); + + void queryManagerListFail(); + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomMemberView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomMemberView.java new file mode 100644 index 000000000..d275c185c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomMemberView.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + + +/** + *

+ * + * @author jiahui + * @date 2017/12/19 + */ +public interface IRoomMemberView extends IMvpBaseView { + /** + * 设置管理员成功 + * + * @param chatRoomMember + */ + void markManagerListSuccess(ChatRoomMember chatRoomMember); + + /** + * 设置管理员失败 + * + * @param code + * @param error + */ + void markManagerListFail(int code, String error); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomSettingView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomSettingView.java new file mode 100644 index 000000000..8710de340 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IRoomSettingView.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.avroom.view; + +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomSettingTabInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/15 + */ +public interface IRoomSettingView extends IMvpBaseView { + + void onResultRequestTagAllSuccess(List tabInfoList); + + void onResultRequestTagAllFail(String error); + + void updateRoomInfoSuccess(RoomInfo roomInfo); + + void reQuestRoomInfo(RoomInfo roomInfo); + + void updateRoomInfoFail(String error); + + void onSuccessToFinish(); + + void onFailToToast(String error); + + /** + * 更新房间纯净模式时使用 + */ + void onUpdateRoomPureMode(RoomInfo roomInfo); + + // 离开模式 + void leaveModeOpenSuccess(); + void leaveModeOpenFail(String msg); + void leaveModeCloseSuccess(); + void leaveModeCloseFail(String msg); +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/ActivityTimerView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/ActivityTimerView.java new file mode 100644 index 000000000..942d6034d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/ActivityTimerView.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.avroom.widget; + + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.room.activitytimer.TimerBean; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; + +/** + * create by lvzebiao @2020/2/24 + */ +public class ActivityTimerView extends LinearLayout { + + private TextView tvTime; + + private Disposable disposable; + + private TimerBean lastTimerBean; + + public ActivityTimerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + inflate(context, R.layout.view_activity_timer, this); + tvTime = findViewById(R.id.tv_time); + } + + public void start(TimerBean currTimerBean) { + //先判断两条消息时效 + if (lastTimerBean != null) { + if (currTimerBean.getRunawayTime() < lastTimerBean.getRunawayTime()) { + //说明新来的消息,实际上比上个消息还旧,则不读取,直接忽略 + return; + } + } + lastTimerBean = currTimerBean; + stop(); + long maxTime = currTimerBean.getLimitTime(); + setVisibility(GONE);//如果接口返回0,说明活动可能下架了,直接隐藏倒计时 + if (maxTime <= 1) { + return; + } + setVisibility(VISIBLE); + disposable = Observable.intervalRange(0, (maxTime + 1), 0, 1, TimeUnit.SECONDS) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(aLong -> { + + tvTime.setText((maxTime - aLong) + "秒"); + if (maxTime - aLong <= 0) { + setVisibility(GONE); + } + + }) + .subscribe(); + } + + private void stop() { + if (disposable != null) { + disposable.dispose(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + stop(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/BottomView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/BottomView.java new file mode 100644 index 000000000..1d7c7963f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/BottomView.java @@ -0,0 +1,326 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.BottomViewListenerWrapper; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMMessageManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +/** + * @author chenran + * @date 2017/7/26 + */ + +public class BottomView extends RelativeLayout implements View.OnClickListener { + + /** 有新功能,加1 */ + private static final int NEW_OPTION = 1; + private static final String SH_NEW_OPTION = "sh_new_option"; + + private BottomViewListenerWrapper wrapper; + private ImageView openMic; + private ImageView sendMsg; + private TextView sendMsgInput; + private LinearLayout llSendMsg; + private ImageView sendGift; + private ImageView sendMagic; + private ImageView sendFace; + + private ImageView remoteMute; + private LinearLayout faceLayout; + private LinearLayout micLayout; + // private ImageView ivRoomKtv; + private ImageView ivRoomGame; + private ImageView iconMicQueue; + private ImageView iconRoomMsg; + + public BottomView(Context context) { + super(context); + init(); + } + + public BottomView(Context context, AttributeSet attr) { + super(context, attr); + init(); + } + + public BottomView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(); + } + + private void init() { + inflate(getContext(), R.layout.layout_bottom_view, this); + openMic = findViewById(R.id.icon_room_open_mic); + sendMsg = findViewById(R.id.icon_room_send_msg); + sendMsgInput = findViewById(R.id.tv_room_send_msg_input); + llSendMsg = findViewById(R.id.ll_send_msg); + sendFace = findViewById(R.id.icon_room_face); + sendGift = findViewById(R.id.icon_room_send_gift); + sendMagic = findViewById(R.id.icon_room_send_magic); + remoteMute = findViewById(R.id.icon_room_open_remote_mic); + ivRoomGame = findViewById(R.id.icon_room_game); + faceLayout = findViewById(R.id.room_face_layout); + micLayout = findViewById(R.id.room_mic_layout); + + iconMicQueue = (ImageView) findViewById(R.id.icon_mic_queue); + + iconRoomMsg = findViewById(R.id.iv_room_message); + + openMic.setOnClickListener(this); + sendMsg.setOnClickListener(this); + sendMsgInput.setOnClickListener(this); + sendFace.setOnClickListener(this); + sendGift.setOnClickListener(this); + remoteMute.setOnClickListener(this); + sendMagic.setOnClickListener(this); +// ivRoomKtv.setOnClickListener(this); + ivRoomGame.setOnClickListener(this); + iconMicQueue.setOnClickListener(this); + iconRoomMsg.setOnClickListener(this); + + setMicBtnEnable(false); + setMicBtnOpen(false); + setQueuingMicButton(AvRoomDataManager.get().isQueuingMicro()); + setRoomMessageUnread(IMMessageManager.get().queryUnreadMsg()); + + if (SuperAdminUtil.isSuperAdmin()) { + sendGift.setVisibility(GONE); + sendMsgInput.setVisibility(GONE); + llSendMsg.setVisibility(GONE); + } + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + EventBus.getDefault().register(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + } + + /** + * 轻聊房没有魔法礼物 + * + * @param enable 允许与否 + */ + public void setMagicBtnEnable(boolean enable) { + if (enable) { + sendMagic.setVisibility(VISIBLE); + int newOption = (int) SharedPreferenceUtils.get(SH_NEW_OPTION, 0); + + if (newOption == NEW_OPTION) { + sendMagic.setImageResource(R.drawable.icon_send_magic); + } else { + sendMagic.setImageResource(R.drawable.icon_send_magic_new); + } + sendMagic.setClickable(true); + sendMagic.setOnClickListener(this); + } else { + sendMagic.setClickable(false); + sendMagic.setOnClickListener(null); + sendMagic.setVisibility(GONE); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveRecentContactChanged(List imMessages) { + setRoomMessageUnread(IMMessageManager.get().queryUnreadMsg()); + } + + public void setRoomMessageUnread(int count) { + iconRoomMsg.setImageResource(count > 0 ? R.drawable.ic_room_message_income : R.drawable.ic_room_message); + } + + public void setBottomViewListener(BottomViewListenerWrapper wrapper) { + this.wrapper = wrapper; + } + + public void setMicBtnEnable(boolean enable) { + if (enable) { + openMic.setClickable(true); + openMic.setOnClickListener(this); + } else { + openMic.setClickable(false); + openMic.setOnClickListener(null); + } + } + + public void setMicBtnOpen(boolean isOpen) { + if (isOpen) { + openMic.setImageResource(R.drawable.icon_room_open_mic); + } else { + openMic.setImageResource(R.drawable.icon_room_close_mic); + } + } + + public void setRemoteMuteOpen(boolean isOpen) { + if (isOpen) { + remoteMute.setImageResource(R.drawable.icon_remote_mute_close); + } else { + remoteMute.setImageResource(R.drawable.icon_remote_mute_open); + } + } + + public void showHomePartyUpMicBottom() { + faceLayout.setVisibility(VISIBLE); + micLayout.setVisibility(VISIBLE); + } + + public void showHomePartyDownMicBottom() { + faceLayout.setVisibility(GONE); + micLayout.setVisibility(GONE); + } + + public void showLightChatUpMicBottom() { + faceLayout.setVisibility(GONE); + micLayout.setVisibility(VISIBLE); + } + + public void showLightChatDownMicBottom() { + faceLayout.setVisibility(GONE); + micLayout.setVisibility(GONE); + } + + public void setQueuingMicButton(boolean isQueuingMicroMode) { + if (SuperAdminUtil.isSuperAdmin()) { + iconMicQueue.setVisibility(GONE); + return; + } + iconMicQueue.setVisibility(isQueuingMicroMode && !AvRoomDataManager.get().isCpRoom() ? VISIBLE : GONE); + } + + public void setQueuingMicButtonBackground(boolean isEmpty) { + iconMicQueue.setImageResource(isEmpty ? R.drawable.icon_room_mic_queue : + R.drawable.icon_room_mic_queue_not_empty); + } + + public void showGameBottom() { + if (MarketVerifyModel.get().isMarketChecking()) { + ivRoomGame.setVisibility(GONE); + } else { + ivRoomGame.setVisibility((AvRoomDataManager.get().isCpRoom() && AvRoomDataManager.get().isRoomOwner()) ? VISIBLE : GONE); + } + } + + public void setGameClose() { + ivRoomGame.setImageResource(R.drawable.icon_room_game_close); + } + + public void setGameOpen() { + ivRoomGame.setImageResource(R.drawable.icon_room_game); + } + + public void showKtvBottom(boolean isShow) { +// ivRoomKtv.setImageResource(isShow ? R.drawable.ic_ktv_select : R.drawable.icon_room_ktv_entrance); + boolean hasKTVPriv = false; + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + hasKTVPriv = roomInfo.hasKTVPriv; + } + // ivRoomKtv.setVisibility(((isShow || AvRoomDataManager.get().isManager()) && hasKTVPriv) ? VISIBLE : GONE); + } + + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.icon_room_open_mic: + if (wrapper != null) { + wrapper.onOpenMicBtnClick(); + } + break; + + case R.id.tv_room_send_msg_input: + case R.id.icon_room_send_msg: + if (wrapper != null) { + wrapper.onSendMsgBtnClick(); + } + break; + case R.id.icon_room_send_gift: + if (wrapper != null) { + wrapper.onSendGiftBtnClick(); + } + break; + case R.id.icon_room_face: + if (wrapper != null) { + wrapper.onSendFaceBtnClick(); + } + break; + + case R.id.icon_room_open_remote_mic: + if (wrapper != null) { + wrapper.onRemoteMuteBtnClick(); + } + break; + case R.id.icon_room_send_magic: + + int newOption = (int) SharedPreferenceUtils.get(SH_NEW_OPTION, 0); + if (newOption != NEW_OPTION) { + SharedPreferenceUtils.put(SH_NEW_OPTION, NEW_OPTION); + setMagicBtnEnable(true); + } + + if (wrapper != null) { + wrapper.onMoreBtnClick(); + } + break; +// case R.id.icon_room_ktv: +// if (wrapper != null) { +// wrapper.onTransformKTVClick(); +// } +// break; + case R.id.icon_mic_queue: + if (wrapper != null) { + wrapper.onMicQueueClick(); + } + break; + case R.id.icon_room_game: + if (wrapper != null) { + wrapper.onTransformGameClick(); + } + break; + case R.id.iv_room_message: + if (wrapper != null) { + wrapper.onRoomMessageClick(); + } + break; + default: + } + } + + public void showInputOrIcon(boolean isIcon) { + if (SuperAdminUtil.isSuperAdmin()) { + return; + } + sendMsgInput.setVisibility(isIcon ? GONE : VISIBLE); + llSendMsg.setVisibility(isIcon ? VISIBLE : GONE); + } + + public View getSendGiftView() { + return sendGift; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/EditRoomTitleDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/EditRoomTitleDialog.java new file mode 100644 index 000000000..09b9e6faf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/EditRoomTitleDialog.java @@ -0,0 +1,235 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; + + +/** + * 房间编辑dialog + * Created by huangmeng1 on 2018/8/14. + */ + +public class EditRoomTitleDialog extends AppCompatDialog { + /** + * 房间名字 + */ + public final static int TYPE_EDIT_NAME = 0; + /** + * 房间密码 + */ + public final static int TYPE_EDIT_PASSWORD = 1; + /** + * 房间描述 + */ + public final static int TYPE_EDIT_DESC = 2; + public final static int TYPE_EDIT_TEAM_NAME = 3; + public final static int TYPE_EDIT_TEAM_THEME = 4; + + private EditText etContent; + private TextView tvLimit; + private TextView tvTitle; + + private OnEditTitleListner onEditTitleListner; + + private OnCancelEditListner onCancelEditListner; + private Context context; + private String oldContent; + + + private int dialogType; + + private int maxLength = 0; + + public void setOnEditTitleListner(OnEditTitleListner onEditTitleListner) { + this.onEditTitleListner = onEditTitleListner; + } + + public void setOnCancelEditListner(OnCancelEditListner onCancelEditListner) { + this.onCancelEditListner = onCancelEditListner; + } + + public EditRoomTitleDialog(Context context, int dialogType, String oldContent) { + super(context, R.style.TranslucentNoTitle); + this.context = context; + this.dialogType = dialogType; + this.oldContent = oldContent; + } + + private String mCancelLabel; + public EditRoomTitleDialog(Context context, int dialogType, String oldContent, String cancelLabel) { + this(context, dialogType, oldContent); + this.mCancelLabel = cancelLabel; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_common_edit); + etContent = findViewById(R.id.et_content); + tvLimit = findViewById(R.id.tv_limit); + tvTitle = findViewById(R.id.tv_title); + + if (!TextUtils.isEmpty(oldContent)) { + etContent.setText(oldContent); + etContent.setSelection(oldContent.length()); + } + if (dialogType == TYPE_EDIT_PASSWORD) { + tvTitle.setText("房间密码"); + tvLimit.setVisibility(View.VISIBLE); + etContent.setInputType(InputType.TYPE_CLASS_NUMBER); + etContent.setHint("请输入房间密码"); + maxLength = 8; + etContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + setLimtText(); + } else if (dialogType == TYPE_EDIT_NAME){ + tvTitle.setText("房间名编辑"); + tvLimit.setVisibility(View.VISIBLE); + etContent.setHint("请输入房间名"); + maxLength = 15; + etContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + setLimtText(); + } else if (dialogType == TYPE_EDIT_DESC) { + tvTitle.setText("房间话题编辑"); + tvLimit.setVisibility(View.VISIBLE); + etContent.setHint("请输入房间话题"); + maxLength = 15; + etContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + setLimtText(); + } else if (dialogType == TYPE_EDIT_TEAM_NAME) { + tvTitle.setText("修改群聊名称"); + tvLimit.setVisibility(View.GONE); + etContent.setHint("请输入群聊名称"); + maxLength = 16; + etContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + setLimtText(); + + } else if (dialogType == TYPE_EDIT_TEAM_THEME) { + tvTitle.setText("修改派对名称"); + tvLimit.setVisibility(View.GONE); + etContent.setHint("请输入派对名称"); + maxLength = 16; + etContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + setLimtText(); + + } + + TextView tvCancel = findViewById(R.id.btn_cancel); + if (!TextUtils.isEmpty(mCancelLabel)) + tvCancel.setText("" + mCancelLabel); + tvCancel.setOnClickListener(v -> { + dismiss(); + + if (onCancelEditListner != null) { + onCancelEditListner.onEditTeamThemeListener(); + } + }); + + findViewById(R.id.btn_ok).setOnClickListener(v -> { + if (TextUtils.isEmpty(etContent.getText().toString())){ + SingleToastUtil.showToast("不能为空"); + return; + } + if (onEditTitleListner != null) { + dismiss(); + if (dialogType == TYPE_EDIT_PASSWORD){ + onEditTitleListner.onEditPwdListner(etContent.getText().toString()); + } else if (dialogType == TYPE_EDIT_NAME){ + onEditTitleListner.onEditTitleListner(etContent.getText().toString()); + } else if (dialogType == TYPE_EDIT_DESC) { + onEditTitleListner.onEditDescLisner(etContent.getText().toString()); + } else if (dialogType == TYPE_EDIT_TEAM_NAME) { + onEditTitleListner.onEditTeamNameListener(etContent.getText().toString()); + } else if (dialogType == TYPE_EDIT_TEAM_THEME) { + onEditTitleListner.onEditTeamThemeListener(etContent.getText().toString()); + } + } + }); + etContent.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + tvLimit.setText(s.length() + "/" + maxLength); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + setOnShowListener(new OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + etContent.requestFocus(); + etContent.setSelection(etContent.getText().toString().length()); + Single.timer(200, TimeUnit.MILLISECONDS) + .compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(Long aLong) throws Exception { + KeyBoardUtils.showDialogSoftInput(getContext()); + } + }); + + } + }); + setOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + KeyBoardUtils.hideDialogSoftInput(context); + } + }); + } + + public static abstract class OnEditTitleListner { + public void onEditTitleListner(String title) { + } + + public void onEditPwdListner(String title) { + } + + public void onEditDescLisner(String desc) { + } + public void onEditTeamThemeListener(String theme){ + } + public void onEditTeamNameListener(String name) { + } + } + + public static abstract class OnCancelEditListner { + public void onEditTeamThemeListener(){ + } + public void onEditTeamNameListener(String name) { + } + } + + private void setLimtText() { + tvLimit.setText(etContent.getText().toString().length() + "/" + maxLength); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/FixRoomTitleTextView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/FixRoomTitleTextView.java new file mode 100644 index 000000000..12e1aa4b5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/FixRoomTitleTextView.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.support.v7.widget.AppCompatTextView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * 尝试修复 https://bugly.qq.com/v2/crash-reporting/crashes/52320483a6/29504?pid=1 + *

+ * 不一定可行... + *

+ * create by lvzebiao @2019/7/16 + */ +public class FixRoomTitleTextView extends AppCompatTextView { + + public FixRoomTitleTextView(Context context) { + super(context); + } + + public FixRoomTitleTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FixRoomTitleTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + try { + return super.onTouchEvent(event); + } catch (Exception ex) { + ex.printStackTrace(); + } + return false; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/GalleryLayoutManager.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/GalleryLayoutManager.java new file mode 100644 index 000000000..f8b349ad8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/GalleryLayoutManager.java @@ -0,0 +1,1071 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.graphics.PointF; +import android.graphics.Rect; +import android.support.v7.widget.LinearSmoothScroller; +import android.support.v7.widget.LinearSnapHelper; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.util.Log; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.BuildConfig; +import com.yizhuan.erban.application.XChatApplication; + +import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE; + +/** + * A custom LayoutManager to build a {@link android.widget.Gallery} or a {@link android.support.v4.view.ViewPager}like {@link RecyclerView} and + * support both {@link GalleryLayoutManager#HORIZONTAL} and {@link GalleryLayoutManager#VERTICAL} scroll. + * Created by chensuilun on 2016/11/18. + */ +public class GalleryLayoutManager extends RecyclerView.LayoutManager implements RecyclerView.SmoothScroller.ScrollVectorProvider { + private static final String TAG = "GalleryLayoutManager"; + final static int LAYOUT_START = -1; + + final static int LAYOUT_END = 1; + + public static final int HORIZONTAL = OrientationHelper.HORIZONTAL; + + public static final int VERTICAL = OrientationHelper.VERTICAL; + + private int mFirstVisiblePosition = 0; + private int mLastVisiblePos = 0; + private int mInitialSelectedPosition = 0; + + int mCurSelectedPosition = -1; + + View mCurSelectedView; + /** + * Scroll state + */ + private State mState; + + private LinearSnapHelper mSnapHelper = new LinearSnapHelper(); + + private InnerScrollListener mInnerScrollListener = new InnerScrollListener(); + + private boolean mCallbackInFling = false; + + /** + * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL} + */ + private int mOrientation = HORIZONTAL; + + private OrientationHelper mHorizontalHelper; + private OrientationHelper mVerticalHelper; + + public GalleryLayoutManager(int orientation) { + mOrientation = orientation; + } + + public int getOrientation() { + return mOrientation; + } + + public int getCurSelectedPosition() { + return mCurSelectedPosition; + } + + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + if (mOrientation == VERTICAL) { + return new GalleryLayoutManager.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } else { + return new GalleryLayoutManager.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT); + } + } + + @Override + public RecyclerView.LayoutParams generateLayoutParams(Context c, AttributeSet attrs) { + return new LayoutParams(c, attrs); + } + + @Override + public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + if (lp instanceof ViewGroup.MarginLayoutParams) { + return new LayoutParams((ViewGroup.MarginLayoutParams) lp); + } else { + return new LayoutParams(lp); + } + } + + @Override + public boolean checkLayoutParams(RecyclerView.LayoutParams lp) { + return lp instanceof LayoutParams; + } + + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + if (XChatApplication.isDebug()) { + Log.d(TAG, "onLayoutChildren() called with: state = [" + state + "]"); + } + if (getItemCount() == 0) { + reset(); + detachAndScrapAttachedViews(recycler); + return; + } + if (state.isPreLayout()) { + return; + } + if (state.getItemCount() != 0 && !state.didStructureChange()) { + if (XChatApplication.isDebug()) { + Log.d(TAG, "onLayoutChildren: ignore extra layout step"); + } + return; + } + if (getChildCount() == 0 || state.didStructureChange()) { + reset(); + } + mInitialSelectedPosition = Math.min(Math.max(0, mInitialSelectedPosition), getItemCount() - 1); + detachAndScrapAttachedViews(recycler); + try { + firstFillCover(recycler, state, 0); + } catch (Exception e) { + } + } + + + private void reset() { + if (XChatApplication.isDebug()) { + Log.d(TAG, "reset: "); + } + if (mState != null) { + mState.mItemsFrames.clear(); + } + //when data set update keep the last selected position + if (mCurSelectedPosition != -1) { + mInitialSelectedPosition = mCurSelectedPosition; + } + mInitialSelectedPosition = Math.min(Math.max(0, mInitialSelectedPosition), getItemCount() - 1); + mFirstVisiblePosition = mInitialSelectedPosition; + mLastVisiblePos = mInitialSelectedPosition; + mCurSelectedPosition = -1; + if (mCurSelectedView != null) { + mCurSelectedView.setSelected(false); + mCurSelectedView = null; + } + } + + + private void firstFillCover(RecyclerView.Recycler recycler, RecyclerView.State state, int scrollDelta) { + if (mOrientation == HORIZONTAL) { + firstFillWithHorizontal(recycler, state); + } else { + firstFillWithVertical(recycler, state); + } + + if (XChatApplication.isDebug()) { + Log.d(TAG, "firstFillCover finish:first: " + mFirstVisiblePosition + ",last:" + mLastVisiblePos); + } + + if (mItemTransformer != null) { + View child; + for (int i = 0; i < getChildCount(); i++) { + child = getChildAt(i); + mItemTransformer.transformItem(this, child, calculateToCenterFraction(child, scrollDelta)); + } + } + mInnerScrollListener.onScrolled(mRecyclerView, 0, 0); + } + + /** + * Layout the item view witch position specified by {@link GalleryLayoutManager#mInitialSelectedPosition} first and then layout the other + * + * @param recycler + * @param state + */ + private void firstFillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.State state) { + detachAndScrapAttachedViews(recycler); + int leftEdge = getOrientationHelper().getStartAfterPadding(); + int rightEdge = getOrientationHelper().getEndAfterPadding(); + int startPosition = mInitialSelectedPosition; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int height = getVerticalSpace(); + int topOffset; + //layout the init position view + View scrap = recycler.getViewForPosition(mInitialSelectedPosition); + addView(scrap, 0); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + topOffset = (int) (getPaddingTop() + (height - scrapHeight) / 2.0f); + int left = (int) (getPaddingLeft() + (getHorizontalSpace() - scrapWidth) / 2.f); + scrapRect.set(left, topOffset, left + scrapWidth, topOffset + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + if (getState().mItemsFrames.get(startPosition) == null) { + getState().mItemsFrames.put(startPosition, scrapRect); + } else { + getState().mItemsFrames.get(startPosition).set(scrapRect); + } + mFirstVisiblePosition = mLastVisiblePos = startPosition; + int leftStartOffset = getDecoratedLeft(scrap); + int rightStartOffset = getDecoratedRight(scrap); + //fill left of center + fillLeft(recycler, mInitialSelectedPosition - 1, leftStartOffset, leftEdge); + //fill right of center + fillRight(recycler, mInitialSelectedPosition + 1, rightStartOffset, rightEdge); + } + + @Override + public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { + super.onItemsRemoved(recyclerView, positionStart, itemCount); + } + + /** + * Layout the item view witch position special by {@link GalleryLayoutManager#mInitialSelectedPosition} first and then layout the other + * + * @param recycler + * @param state + */ + private void firstFillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State state) { + detachAndScrapAttachedViews(recycler); + int topEdge = getOrientationHelper().getStartAfterPadding(); + int bottomEdge = getOrientationHelper().getEndAfterPadding(); + int startPosition = mInitialSelectedPosition; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int width = getHorizontalSpace(); + int leftOffset; + //layout the init position view + View scrap = recycler.getViewForPosition(mInitialSelectedPosition); + addView(scrap, 0); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + leftOffset = (int) (getPaddingLeft() + (width - scrapWidth) / 2.0f); + int top = (int) (getPaddingTop() + (getVerticalSpace() - scrapHeight) / 2.f); + scrapRect.set(leftOffset, top, leftOffset + scrapWidth, top + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + if (getState().mItemsFrames.get(startPosition) == null) { + getState().mItemsFrames.put(startPosition, scrapRect); + } else { + getState().mItemsFrames.get(startPosition).set(scrapRect); + } + mFirstVisiblePosition = mLastVisiblePos = startPosition; + int topStartOffset = getDecoratedTop(scrap); + int bottomStartOffset = getDecoratedBottom(scrap); + //fill left of center + fillTop(recycler, mInitialSelectedPosition - 1, topStartOffset, topEdge); + //fill right of center + fillBottom(recycler, mInitialSelectedPosition + 1, bottomStartOffset, bottomEdge); + } + + /** + * Fill left of the center view + * + * @param recycler + * @param startPosition start position to fill left + * @param startOffset layout start offset + * @param leftEdge + */ + private void fillLeft(RecyclerView.Recycler recycler, int startPosition, int startOffset, int leftEdge) { + View scrap; + int topOffset; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int height = getVerticalSpace(); + for (int i = startPosition; i >= 0 && startOffset > leftEdge; i--) { + scrap = recycler.getViewForPosition(i); + addView(scrap, 0); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + topOffset = (int) (getPaddingTop() + (height - scrapHeight) / 2.0f); + scrapRect.set(startOffset - scrapWidth, topOffset, startOffset, topOffset + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.left; + mFirstVisiblePosition = i; + if (getState().mItemsFrames.get(i) == null) { + getState().mItemsFrames.put(i, scrapRect); + } else { + getState().mItemsFrames.get(i).set(scrapRect); + } + } + } + + /** + * Fill right of the center view + * + * @param recycler + * @param startPosition start position to fill right + * @param startOffset layout start offset + * @param rightEdge + */ + private void fillRight(RecyclerView.Recycler recycler, int startPosition, int startOffset, int rightEdge) { + View scrap; + int topOffset; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int height = getVerticalSpace(); + for (int i = startPosition; i < getItemCount() && startOffset < rightEdge; i++) { + scrap = recycler.getViewForPosition(i); + addView(scrap); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + topOffset = (int) (getPaddingTop() + (height - scrapHeight) / 2.0f); + scrapRect.set(startOffset, topOffset, startOffset + scrapWidth, topOffset + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.right; + mLastVisiblePos = i; + if (getState().mItemsFrames.get(i) == null) { + getState().mItemsFrames.put(i, scrapRect); + } else { + getState().mItemsFrames.get(i).set(scrapRect); + } + } + } + + /** + * Fill top of the center view + * + * @param recycler + * @param startPosition start position to fill top + * @param startOffset layout start offset + * @param topEdge top edge of the RecycleView + */ + private void fillTop(RecyclerView.Recycler recycler, int startPosition, int startOffset, int topEdge) { + View scrap; + int leftOffset; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int width = getHorizontalSpace(); + for (int i = startPosition; i >= 0 && startOffset > topEdge; i--) { + scrap = recycler.getViewForPosition(i); + addView(scrap, 0); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + leftOffset = (int) (getPaddingLeft() + (width - scrapWidth) / 2.0f); + scrapRect.set(leftOffset, startOffset - scrapHeight, leftOffset + scrapWidth, startOffset); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.top; + mFirstVisiblePosition = i; + if (getState().mItemsFrames.get(i) == null) { + getState().mItemsFrames.put(i, scrapRect); + } else { + getState().mItemsFrames.get(i).set(scrapRect); + } + } + } + + /** + * Fill bottom of the center view + * + * @param recycler + * @param startPosition start position to fill bottom + * @param startOffset layout start offset + * @param bottomEdge bottom edge of the RecycleView + */ + private void fillBottom(RecyclerView.Recycler recycler, int startPosition, int startOffset, int bottomEdge) { + View scrap; + int leftOffset; + int scrapWidth, scrapHeight; + Rect scrapRect = new Rect(); + int width = getHorizontalSpace(); + for (int i = startPosition; i < getItemCount() && startOffset < bottomEdge; i++) { + scrap = recycler.getViewForPosition(i); + addView(scrap); + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + leftOffset = (int) (getPaddingLeft() + (width - scrapWidth) / 2.0f); + scrapRect.set(leftOffset, startOffset, leftOffset + scrapWidth, startOffset + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.bottom; + mLastVisiblePos = i; + if (getState().mItemsFrames.get(i) == null) { + getState().mItemsFrames.put(i, scrapRect); + } else { + getState().mItemsFrames.get(i).set(scrapRect); + } + } + } + + + private void fillCover(RecyclerView.Recycler recycler, RecyclerView.State state, int scrollDelta) { + if (getItemCount() == 0) { + return; + } + + if (mOrientation == HORIZONTAL) { + fillWithHorizontal(recycler, state, scrollDelta); + } else { + fillWithVertical(recycler, state, scrollDelta); + } + + + if (mItemTransformer != null) { + View child; + for (int i = 0; i < getChildCount(); i++) { + child = getChildAt(i); + mItemTransformer.transformItem(this, child, calculateToCenterFraction(child, scrollDelta)); + } + } + } + + private float calculateToCenterFraction(View child, float pendingOffset) { + int distance = calculateDistanceCenter(child, pendingOffset); + int childLength = mOrientation == GalleryLayoutManager.HORIZONTAL ? child.getWidth() : child.getHeight(); + + if (XChatApplication.isDebug()) { + Log.d(TAG, "calculateToCenterFraction: distance:" + distance + ",childLength:" + childLength); + } + return Math.max(-1.f, Math.min(1.f, distance * 1.f / childLength)); + } + + /** + * @param child + * @param pendingOffset child view will scroll by + * @return + */ + private int calculateDistanceCenter(View child, float pendingOffset) { + OrientationHelper orientationHelper = getOrientationHelper(); + int parentCenter = (orientationHelper.getEndAfterPadding() - orientationHelper.getStartAfterPadding()) / 2 + orientationHelper.getStartAfterPadding(); + if (mOrientation == GalleryLayoutManager.HORIZONTAL) { + return (int) (child.getWidth() / 2 - pendingOffset + child.getLeft() - parentCenter); + } else { + return (int) (child.getHeight() / 2 - pendingOffset + child.getTop() - parentCenter); + } + + } + + /** + * @param recycler + * @param state + * @param dy + */ + private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State state, int dy) { + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithVertical: dy:" + dy); + } + int topEdge = getOrientationHelper().getStartAfterPadding(); + int bottomEdge = getOrientationHelper().getEndAfterPadding(); + + //1.remove and recycle the view that disappear in screen + View child; + if (getChildCount() > 0) { + if (dy >= 0) { + //remove and recycle the top off screen view + int fixIndex = 0; + for (int i = 0; i < getChildCount(); i++) { + child = getChildAt(i + fixIndex); + if (getDecoratedBottom(child) - dy < topEdge) { + if (XChatApplication.isDebug()) { + Log.v(TAG, "fillWithVertical: removeAndRecycleView:" + getPosition(child) + ",bottom:" + getDecoratedBottom(child)); + } + removeAndRecycleView(child, recycler); + mFirstVisiblePosition++; + fixIndex--; + } else { + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithVertical: break:" + getPosition(child) + ",bottom:" + getDecoratedBottom(child)); + } + break; + } + } + } else { //dy<0 + //remove and recycle the bottom off screen view + for (int i = getChildCount() - 1; i >= 0; i--) { + child = getChildAt(i); + if (getDecoratedTop(child) - dy > bottomEdge) { + if (XChatApplication.isDebug()) { + Log.v(TAG, "fillWithVertical: removeAndRecycleView:" + getPosition(child)); + } + removeAndRecycleView(child, recycler); + mLastVisiblePos--; + } else { + break; + } + } + } + + } + int startPosition = mFirstVisiblePosition; + int startOffset = -1; + int scrapWidth, scrapHeight; + Rect scrapRect; + int width = getHorizontalSpace(); + int leftOffset; + View scrap; + //2.Add or reattach item view to fill screen + if (dy >= 0) { + if (getChildCount() != 0) { + View lastView = getChildAt(getChildCount() - 1); + startPosition = getPosition(lastView) + 1; + startOffset = getDecoratedBottom(lastView); + } + for (int i = startPosition; i < getItemCount() && startOffset < bottomEdge + dy; i++) { + scrapRect = getState().mItemsFrames.get(i); + scrap = recycler.getViewForPosition(i); + addView(scrap); + if (scrapRect == null) { + scrapRect = new Rect(); + getState().mItemsFrames.put(i, scrapRect); + } + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + leftOffset = (int) (getPaddingLeft() + (width - scrapWidth) / 2.0f); + if (startOffset == -1 && startPosition == 0) { + //layout the first position item in center + int top = (int) (getPaddingTop() + (getVerticalSpace() - scrapHeight) / 2.f); + scrapRect.set(leftOffset, top, leftOffset + scrapWidth, top + scrapHeight); + } else { + scrapRect.set(leftOffset, startOffset, leftOffset + scrapWidth, startOffset + scrapHeight); + } + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.bottom; + mLastVisiblePos = i; + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithVertical: add view:" + i + ",startOffset:" + startOffset + ",mLastVisiblePos:" + mLastVisiblePos + ",bottomEdge" + bottomEdge); + } + } + } else { + //dy<0 + if (getChildCount() > 0) { + View firstView = getChildAt(0); + startPosition = getPosition(firstView) - 1; //前一个View的position + startOffset = getDecoratedTop(firstView); + } + for (int i = startPosition; i >= 0 && startOffset > topEdge + dy; i--) { + scrapRect = getState().mItemsFrames.get(i); + scrap = recycler.getViewForPosition(i); + addView(scrap, 0); + if (scrapRect == null) { + scrapRect = new Rect(); + getState().mItemsFrames.put(i, scrapRect); + } + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + leftOffset = (int) (getPaddingLeft() + (width - scrapWidth) / 2.0f); + scrapRect.set(leftOffset, startOffset - scrapHeight, leftOffset + scrapWidth, startOffset); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.top; + mFirstVisiblePosition = i; + } + } + } + + + /** + * @param recycler + * @param state + */ + private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.State state, int dx) { + int leftEdge = getOrientationHelper().getStartAfterPadding(); + int rightEdge = getOrientationHelper().getEndAfterPadding(); + if (XChatApplication.isDebug()) { + Log.v(TAG, "fillWithHorizontal() called with: dx = [" + dx + "],leftEdge:" + leftEdge + ",rightEdge:" + rightEdge); + } + //1.remove and recycle the view that disappear in screen + View child; + if (getChildCount() > 0) { + if (dx >= 0) { + //remove and recycle the left off screen view + int fixIndex = 0; + for (int i = 0; i < getChildCount(); i++) { + child = getChildAt(i + fixIndex); + if (getDecoratedRight(child) - dx < leftEdge) { + removeAndRecycleView(child, recycler); + mFirstVisiblePosition++; + fixIndex--; + if (XChatApplication.isDebug()) { + Log.v(TAG, "fillWithHorizontal:removeAndRecycleView:" + getPosition(child) + " mFirstVisiblePosition change to:" + mFirstVisiblePosition); + } + } else { + break; + } + } + } else { //dx<0 + //remove and recycle the right off screen view + for (int i = getChildCount() - 1; i >= 0; i--) { + child = getChildAt(i); + if (getDecoratedLeft(child) - dx > rightEdge) { + removeAndRecycleView(child, recycler); + mLastVisiblePos--; + if (XChatApplication.isDebug()) { + Log.v(TAG, "fillWithHorizontal:removeAndRecycleView:" + getPosition(child) + "mLastVisiblePos change to:" + mLastVisiblePos); + } + } + } + } + + } + //2.Add or reattach item view to fill screen + int startPosition = mFirstVisiblePosition; + int startOffset = -1; + int scrapWidth, scrapHeight; + Rect scrapRect; + int height = getVerticalSpace(); + int topOffset; + View scrap; + if (dx >= 0) { + if (getChildCount() != 0) { + View lastView = getChildAt(getChildCount() - 1); + startPosition = getPosition(lastView) + 1; //start layout from next position item + startOffset = getDecoratedRight(lastView); + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithHorizontal:to right startPosition:" + startPosition + ",startOffset:" + startOffset + ",rightEdge:" + rightEdge); + } + } + for (int i = startPosition; i < getItemCount() && startOffset < rightEdge + dx; i++) { + scrapRect = getState().mItemsFrames.get(i); + scrap = recycler.getViewForPosition(i); + addView(scrap); + if (scrapRect == null) { + scrapRect = new Rect(); + getState().mItemsFrames.put(i, scrapRect); + } + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + topOffset = (int) (getPaddingTop() + (height - scrapHeight) / 2.0f); + if (startOffset == -1 && startPosition == 0) { + // layout the first position item in center + int left = (int) (getPaddingLeft() + (getHorizontalSpace() - scrapWidth) / 2.f); + scrapRect.set(left, topOffset, left + scrapWidth, topOffset + scrapHeight); + } else { + scrapRect.set(startOffset, topOffset, startOffset + scrapWidth, topOffset + scrapHeight); + } + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.right; + mLastVisiblePos = i; + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithHorizontal,layout:mLastVisiblePos: " + mLastVisiblePos); + } + } + } else { + //dx<0 + if (getChildCount() > 0) { + View firstView = getChildAt(0); + startPosition = getPosition(firstView) - 1; //start layout from previous position item + startOffset = getDecoratedLeft(firstView); + if (XChatApplication.isDebug()) { + Log.d(TAG, "fillWithHorizontal:to left startPosition:" + startPosition + ",startOffset:" + startOffset + ",leftEdge:" + leftEdge + ",child count:" + getChildCount()); + } + } + for (int i = startPosition; i >= 0 && startOffset > leftEdge + dx; i--) { + scrapRect = getState().mItemsFrames.get(i); + scrap = recycler.getViewForPosition(i); + addView(scrap, 0); + if (scrapRect == null) { + scrapRect = new Rect(); + getState().mItemsFrames.put(i, scrapRect); + } + measureChildWithMargins(scrap, 0, 0); + scrapWidth = getDecoratedMeasuredWidth(scrap); + scrapHeight = getDecoratedMeasuredHeight(scrap); + topOffset = (int) (getPaddingTop() + (height - scrapHeight) / 2.0f); + scrapRect.set(startOffset - scrapWidth, topOffset, startOffset, topOffset + scrapHeight); + layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom); + startOffset = scrapRect.left; + mFirstVisiblePosition = i; + } + } + } + + private int getHorizontalSpace() { + return getWidth() - getPaddingRight() - getPaddingLeft(); + } + + private int getVerticalSpace() { + return getHeight() - getPaddingBottom() - getPaddingTop(); + } + + public State getState() { + if (mState == null) { + mState = new State(); + } + return mState; + } + + private int calculateScrollDirectionForPosition(int position) { + if (getChildCount() == 0) { + return LAYOUT_START; + } + final int firstChildPos = mFirstVisiblePosition; + return position < firstChildPos ? LAYOUT_START : LAYOUT_END; + } + + @Override + public PointF computeScrollVectorForPosition(int targetPosition) { + final int direction = calculateScrollDirectionForPosition(targetPosition); + PointF outVector = new PointF(); + if (direction == 0) { + return null; + } + if (mOrientation == HORIZONTAL) { + outVector.x = direction; + outVector.y = 0; + } else { + outVector.x = 0; + outVector.y = direction; + } + return outVector; + } + + /** + * @author chensuilun + */ + class State { + /** + * Record all item view 's last position after last layout + */ + SparseArray mItemsFrames; + + /** + * RecycleView 's current scroll distance since first layout + */ + int mScrollDelta; + + public State() { + mItemsFrames = new SparseArray(); + mScrollDelta = 0; + } + } + + + @Override + public boolean canScrollHorizontally() { + return mOrientation == HORIZONTAL; + } + + + @Override + public boolean canScrollVertically() { + return mOrientation == VERTICAL; + } + + + @Override + public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { + // When dx is positive,finger fling from right to left(←),scrollX+ + if (getChildCount() == 0 || dx == 0) { + return 0; + } + int delta = -dx; + int parentCenter = (getOrientationHelper().getEndAfterPadding() - getOrientationHelper().getStartAfterPadding()) / 2 + getOrientationHelper().getStartAfterPadding(); + View child; + if (dx > 0) { + //If we've reached the last item, enforce limits + if (getPosition(getChildAt(getChildCount() - 1)) == getItemCount() - 1) { + child = getChildAt(getChildCount() - 1); + delta = -Math.max(0, Math.min(dx, (child.getRight() - child.getLeft()) / 2 + child.getLeft() - parentCenter)); + } + } else { + //If we've reached the first item, enforce limits + if (mFirstVisiblePosition == 0) { + child = getChildAt(0); + delta = -Math.min(0, Math.max(dx, ((child.getRight() - child.getLeft()) / 2 + child.getLeft()) - parentCenter)); + } + } + if (XChatApplication.isDebug()) { + Log.d(TAG, "scrollHorizontallyBy: dx:" + dx + ",fixed:" + delta); + } + getState().mScrollDelta = -delta; + fillCover(recycler, state, -delta); + offsetChildrenHorizontal(delta); + return -delta; + } + + @Override + public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { + if (getChildCount() == 0 || dy == 0) { + return 0; + } + int delta = -dy; + int parentCenter = (getOrientationHelper().getEndAfterPadding() - getOrientationHelper().getStartAfterPadding()) / 2 + getOrientationHelper().getStartAfterPadding(); + View child; + if (dy > 0) { + //If we've reached the last item, enforce limits + if (getPosition(getChildAt(getChildCount() - 1)) == getItemCount() - 1) { + child = getChildAt(getChildCount() - 1); + delta = -Math.max(0, Math.min(dy, (getDecoratedBottom(child) - getDecoratedTop(child)) / 2 + getDecoratedTop(child) - parentCenter)); + } + } else { + //If we've reached the first item, enforce limits + if (mFirstVisiblePosition == 0) { + child = getChildAt(0); + delta = -Math.min(0, Math.max(dy, (getDecoratedBottom(child) - getDecoratedTop(child)) / 2 + getDecoratedTop(child) - parentCenter)); + } + } + if (XChatApplication.isDebug()) { + Log.d(TAG, "scrollVerticallyBy: dy:" + dy + ",fixed:" + delta); + } + getState().mScrollDelta = -delta; + fillCover(recycler, state, -delta); + offsetChildrenVertical(delta); + return -delta; + } + + public OrientationHelper getOrientationHelper() { + if (mOrientation == HORIZONTAL) { + if (mHorizontalHelper == null) { + mHorizontalHelper = OrientationHelper.createHorizontalHelper(this); + } + return mHorizontalHelper; + } else { + if (mVerticalHelper == null) { + mVerticalHelper = OrientationHelper.createVerticalHelper(this); + } + return mVerticalHelper; + } + } + + /** + * @author chensuilun + */ + public static class LayoutParams extends RecyclerView.LayoutParams { + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + + public LayoutParams(int width, int height) { + super(width, height); + } + + public LayoutParams(ViewGroup.MarginLayoutParams source) { + super(source); + } + + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + + public LayoutParams(RecyclerView.LayoutParams source) { + super(source); + } + } + + + private ItemTransformer mItemTransformer; + + + public void setItemTransformer(ItemTransformer itemTransformer) { + mItemTransformer = itemTransformer; + } + + /** + * A ItemTransformer is invoked whenever a attached item is scrolled. + * This offers an opportunity for the application to apply a custom transformation + * to the item views using animation properties. + */ + public interface ItemTransformer { + + /** + * Apply a property transformation to the given item. + * + * @param layoutManager Current LayoutManager + * @param item Apply the transformation to this item + * @param fraction of page relative to the current front-and-center position of the pager. + * 0 is front and center. 1 is one full + * page position to the right, and -1 is one page position to the left. + */ + void transformItem(GalleryLayoutManager layoutManager, View item, float fraction); + } + + /** + * Listen for changes to the selected item + * + * @author chensuilun + */ + public interface OnItemSelectedListener { + /** + * @param recyclerView The RecyclerView which item view belong to. + * @param item The current selected view + * @param position The current selected view's position + */ + void onItemSelected(RecyclerView recyclerView, View item, int position); + } + + private OnItemSelectedListener mOnItemSelectedListener; + + public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) { + mOnItemSelectedListener = onItemSelectedListener; + } + + public void attach(RecyclerView recyclerView) { + this.attach(recyclerView, -1); + } + + /** + * @param recyclerView + * @param selectedPosition + */ + public void attach(RecyclerView recyclerView, int selectedPosition) { + if (recyclerView == null) { + throw new IllegalArgumentException("The attach RecycleView must not null!!"); + } + mRecyclerView = recyclerView; + mInitialSelectedPosition = Math.max(0, selectedPosition); + recyclerView.setLayoutManager(this); + mSnapHelper.attachToRecyclerView(recyclerView); + recyclerView.addOnScrollListener(mInnerScrollListener); + } + + RecyclerView mRecyclerView; + + + public void setCallbackInFling(boolean callbackInFling) { + mCallbackInFling = callbackInFling; + } + + /** + * Inner Listener to listen for changes to the selected item + * + * @author chensuilun + */ + private class InnerScrollListener extends RecyclerView.OnScrollListener { + int mState; + boolean mCallbackOnIdle; + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + View snap = mSnapHelper.findSnapView(recyclerView.getLayoutManager()); + if (snap != null) { + int selectedPosition = recyclerView.getLayoutManager().getPosition(snap); + if (selectedPosition != mCurSelectedPosition) { + if (mCurSelectedView != null) { + mCurSelectedView.setSelected(false); + } + mCurSelectedView = snap; + mCurSelectedView.setSelected(true); + mCurSelectedPosition = selectedPosition; + if (!mCallbackInFling && mState != SCROLL_STATE_IDLE) { + if (XChatApplication.isDebug()) { + Log.v(TAG, "ignore selection change callback when fling "); + } + mCallbackOnIdle = true; + return; + } + if (mOnItemSelectedListener != null) { + mOnItemSelectedListener.onItemSelected(recyclerView, snap, mCurSelectedPosition); + } + } + } + if (XChatApplication.isDebug()) { + Log.v(TAG, "onScrolled: dx:" + dx + ",dy:" + dy); + } + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + mState = newState; + if (XChatApplication.isDebug()) { + Log.v(TAG, "onScrollStateChanged: " + newState); + } + if (mState == SCROLL_STATE_IDLE) { + View snap = mSnapHelper.findSnapView(recyclerView.getLayoutManager()); + if (snap != null) { + int selectedPosition = recyclerView.getLayoutManager().getPosition(snap); + if (selectedPosition != mCurSelectedPosition) { + if (mCurSelectedView != null) { + mCurSelectedView.setSelected(false); + } + mCurSelectedView = snap; + mCurSelectedView.setSelected(true); + mCurSelectedPosition = selectedPosition; + if (mOnItemSelectedListener != null) { + mOnItemSelectedListener.onItemSelected(recyclerView, snap, mCurSelectedPosition); + } + } else if (!mCallbackInFling && mOnItemSelectedListener != null && mCallbackOnIdle) { + mCallbackOnIdle = false; + mOnItemSelectedListener.onItemSelected(recyclerView, snap, mCurSelectedPosition); + } + } else { + Log.e(TAG, "onScrollStateChanged: snap null"); + } + } + } + } + + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + GallerySmoothScroller linearSmoothScroller = new GallerySmoothScroller(recyclerView.getContext()); + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + } + + /** + * Implement to support {@link GalleryLayoutManager#smoothScrollToPosition(RecyclerView, RecyclerView.State, int)} + */ + private class GallerySmoothScroller extends LinearSmoothScroller { + + public GallerySmoothScroller(Context context) { + super(context); + } + + /** + * Calculates the horizontal scroll amount necessary to make the given view in center of the RecycleView + * + * @param view The view which we want to make in center of the RecycleView + * @return The horizontal scroll amount necessary to make the view in center of the RecycleView + */ + public int calculateDxToMakeCentral(View view) { + final RecyclerView.LayoutManager layoutManager = getLayoutManager(); + if (layoutManager == null || !layoutManager.canScrollHorizontally()) { + return 0; + } + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); + final int left = layoutManager.getDecoratedLeft(view) - params.leftMargin; + final int right = layoutManager.getDecoratedRight(view) + params.rightMargin; + final int start = layoutManager.getPaddingLeft(); + final int end = layoutManager.getWidth() - layoutManager.getPaddingRight(); + final int childCenter = left + (int) ((right - left) / 2.0f); + final int containerCenter = (int) ((end - start) / 2.f); + return containerCenter - childCenter; + } + + /** + * Calculates the vertical scroll amount necessary to make the given view in center of the RecycleView + * + * @param view The view which we want to make in center of the RecycleView + * @return The vertical scroll amount necessary to make the view in center of the RecycleView + */ + public int calculateDyToMakeCentral(View view) { + final RecyclerView.LayoutManager layoutManager = getLayoutManager(); + if (layoutManager == null || !layoutManager.canScrollVertically()) { + return 0; + } + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) + view.getLayoutParams(); + final int top = layoutManager.getDecoratedTop(view) - params.topMargin; + final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin; + final int start = layoutManager.getPaddingTop(); + final int end = layoutManager.getHeight() - layoutManager.getPaddingBottom(); + final int childCenter = top + (int) ((bottom - top) / 2.0f); + final int containerCenter = (int) ((end - start) / 2.f); + return containerCenter - childCenter; + } + + + @Override + protected void onTargetFound(View targetView, RecyclerView.State state, Action action) { + final int dx = calculateDxToMakeCentral(targetView); + final int dy = calculateDyToMakeCentral(targetView); + final int distance = (int) Math.sqrt(dx * dx + dy * dy); + final int time = calculateTimeForDeceleration(distance); + if (time > 0) { + action.update(-dx, -dy, time, mDecelerateInterpolator); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftEffectView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftEffectView.java new file mode 100644 index 000000000..9aa99106d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftEffectView.java @@ -0,0 +1,274 @@ +package com.yizhuan.erban.avroom.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Point; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.LinearInterpolator; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftEffectInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiver; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_library.utils.ResolutionUtils; + +import org.jetbrains.annotations.NotNull; + +import java.lang.ref.WeakReference; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * @author chenran + * @date 2017/10/8 + */ + +public class GiftEffectView extends RelativeLayout implements SVGACallback { + private RelativeLayout container; + private SVGAImageView svgaImageView; + private View svgaBg; + private ImageView giftLightBg; + private CircleImageView giftImg; + private ImageView imgBg; + private CircleImageView benefactorAvatar; + private CircleImageView receiverAvatar; + private TextView benefactorNick; + private TextView receiverNick; + private TextView giftNumber; + private TextView giftName; + private GiftEffectListener giftEffectListener; + private EffectHandler effectHandler; + private boolean isAnim; + + + public interface GiftEffectListener { + void onGiftEffectEnd(); + } + + public boolean isAnim() { + return isAnim; + } + + public GiftEffectView(Context context) { + super(context); + init(); + } + + public GiftEffectView(Context context, AttributeSet attr) { + super(context, attr); + init(); + } + + public GiftEffectView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(); + } + + public void setGiftEffectListener(GiftEffectListener giftEffectListener) { + this.giftEffectListener = giftEffectListener; + } + + private void init() { + LayoutInflater.from(getContext()).inflate(R.layout.layout_gift_effect, this, true); + effectHandler = new EffectHandler(this); + container = (RelativeLayout) findViewById(R.id.container); + imgBg = (ImageView) findViewById(R.id.img_bg); + giftLightBg = (ImageView) findViewById(R.id.gift_light_bg); + giftImg = (CircleImageView) findViewById(R.id.gift_img); + benefactorAvatar = (CircleImageView) findViewById(R.id.benefactor_avatar); + receiverAvatar = (CircleImageView) findViewById(R.id.receiver_avatar); + benefactorNick = (TextView) findViewById(R.id.benefactor_nick); + receiverNick = (TextView) findViewById(R.id.receiver_nick); + giftNumber = (TextView) findViewById(R.id.gift_number); + giftName = (TextView) findViewById(R.id.gift_name); + svgaImageView = (SVGAImageView) findViewById(R.id.svga_imageview); + svgaImageView.setCallback(this); + svgaImageView.setClearsAfterStop(true); + svgaImageView.setLoops(1); + svgaBg = findViewById(R.id.svga_imageview_bg); + } + + public void startGiftEffect(GiftEffectInfo giftEffectInfo) { + this.isAnim = true; + GiftInfo giftInfo = GiftModel.get().findGiftInfoById(giftEffectInfo.getGiftId()); + if (giftInfo==null || TextUtils.isEmpty(giftInfo.getGiftUrl())){ + giftInfo = giftEffectInfo.getGift(); + } + if (giftInfo != null) { + ImageLoadUtils.loadImage(benefactorAvatar.getContext(), giftEffectInfo.getAvatar(), benefactorAvatar); + ImageLoadUtils.loadImage(giftImg.getContext(), giftInfo.getGiftUrl(), giftImg); + benefactorNick.setText(giftEffectInfo.getNick()); + giftNumber.setText("X" + giftEffectInfo.getGiftNum()); + giftName.setText(giftInfo.getGiftName()); + container.setVisibility(VISIBLE); + + if (giftEffectInfo.getGiftReceiveType() == GiftEffectInfo.GIFT_RECEIVE_TYPE_SINGLE) { + GiftReceiver giftReceiver = giftEffectInfo.getTargetUsers().get(0); + ImageLoadUtils.loadAvatar(receiverAvatar.getContext(), giftReceiver.getAvatar(), receiverAvatar); + receiverNick.setText(giftReceiver.getNick()); + } else if (giftEffectInfo.getGiftReceiveType() == GiftEffectInfo.GIFT_RECEIVE_TYPE_ALL) { + receiverAvatar.setImageResource(R.mipmap.app_logo); + receiverNick.setText("全麦"); + } else if (giftEffectInfo.getGiftReceiveType() == GiftEffectInfo.GIFT_RECEIVE_TYPE_MULTI) { + receiverAvatar.setImageResource(R.mipmap.app_logo); + StringBuilder sb = new StringBuilder(); + for (GiftReceiver targetUser : giftEffectInfo.getTargetUsers()) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByAccount(targetUser.getUid() + ""); + if (roomQueueInfo == null) continue; + sb.append(roomQueueInfo.mRoomMicInfo.getPosition() + 1).append("麦").append(","); + } + if (sb.length() > 0) { + sb.replace(sb.lastIndexOf(","), sb.length(), ""); + } + receiverNick.setText(sb.toString()); + } + + Animation operatingAnim = AnimationUtils.loadAnimation(getContext(), R.anim.light_bg_rotate_anim); + LinearInterpolator lin = new LinearInterpolator(); + operatingAnim.setInterpolator(lin); + giftLightBg.setAnimation(operatingAnim); + + final Point center = new Point(); + center.x = ResolutionUtils.getScreenWidth(getContext()) / 2; + ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(container, "translationX", -UIUtil.dip2px(getContext(), 400), center.x - container.getWidth() / 2).setDuration(500); + objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator.start(); + + ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(container, "alpha", 0.0F, 1.0F).setDuration(500); + objectAnimator1.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator1.start(); + + int totalCoin = giftInfo.getGoldPrice() * giftEffectInfo.getGiftNum() * giftEffectInfo.getTargetUsers().size(); + if (totalCoin >= 520 && totalCoin < 4999) { + imgBg.setImageResource(R.drawable.icon_gift_effect_bg_1); + } else if (totalCoin >= 4999 && totalCoin < 9999) { + imgBg.setImageResource(R.drawable.icon_gift_effect_bg_2); + } else if (totalCoin >= 9999) { + imgBg.setImageResource(R.drawable.icon_gift_effect_bg_3); + } + + effectHandler.sendEmptyMessageDelayed(0, 6000); + + if (giftInfo.isHasVggPic() && !StringUtil.isEmpty(giftInfo.getVggUrl())) { + try { + drawSvgaEffect(giftInfo.getVggUrl()); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + } + } + + private void drawSvgaEffect(String url) throws MalformedURLException { + if (! AvRoomDataManager.get().mIsNeedGiftEffect) return; + SVGAParser parser = new SVGAParser(getContext()); + parser.parse(new URL(url), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity videoItem) { + SVGADrawable drawable = new SVGADrawable(videoItem); + svgaImageView.setImageDrawable(drawable); + svgaImageView.startAnimation(); + svgaBg.setVisibility(VISIBLE); + ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(svgaBg, "alpha", 0.0F, 2.0F).setDuration(800); + objectAnimator1.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator1.start(); + } + + @Override + public void onError() { + + } + }); + + } + + private void deleteAnim() { + ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(container, "translationX", container.getX(), ResolutionUtils.getScreenWidth(getContext())).setDuration(500); + objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator.start(); + + ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(container, "alpha", 1.0F, 0.0F).setDuration(500); + objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (giftEffectListener != null) { + isAnim = false; + giftEffectListener.onGiftEffectEnd(); + } + } + }); + objectAnimator1.start(); + } + + private static class EffectHandler extends Handler { + private WeakReference mReference; + + EffectHandler(GiftEffectView giftEffectView) { + mReference = new WeakReference<>(giftEffectView); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (mReference != null) { + final GiftEffectView giftEffectView = mReference.get(); + if (giftEffectView != null) { + if (msg.what == 0) { + giftEffectView.deleteAnim(); + } + } + } + } + } + + public void release() { + effectHandler.removeMessages(0); + } + + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + svgaBg.setVisibility(GONE); + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftV2View.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftV2View.java new file mode 100644 index 000000000..e42239705 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftV2View.java @@ -0,0 +1,851 @@ +package com.yizhuan.erban.avroom.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.Keyframe; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; +import android.app.Activity; +import android.content.Context; +import android.graphics.Path; +import android.graphics.PathMeasure; +import android.graphics.Point; +import android.os.Build; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.BuildConfig; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftEffectInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftMultiReceiverInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiveInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiver; +import com.yizhuan.xchat_android_core.gift.bean.MultiGiftReceiveInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicReceivedInfo; +import com.yizhuan.xchat_android_core.magic.bean.MultiMagicReceivedInfo; +import com.yizhuan.xchat_android_core.magic.ObjectPool; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterAttackInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.bean.GiftValueCommonUpdate; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.ResolutionUtils; + +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Objects; +import java.util.Random; + + +/** + * 礼物特效布局 + * + * @author xiaoyu + */ + +public class GiftV2View extends FrameLayout implements GiftEffectView.GiftEffectListener { + private static final String TAG = GiftV2View.class.getSimpleName(); + private GiftEffectView giftEffectView; + private SVGAImageView mMagicExplodeView; + private int giftWidth; + private int giftHeight; + private SVGAParser mSVGAParser; + private List giftEffectInfoList; + private List mMagicReceivedInfos; + private HashMap mSVGAVideoEntityMap; + private UiHandler handler; + private boolean dettached = false; + + private Context context; + private int mScreenWidth; + private int mScreenHeight; + private int mGiftSendY; + private Keyframe[] keyScale; + private Keyframe[] keyTrans; + private SvgaObjectPool mMagicViewPool; + private volatile Hashtable currentAnimationMap = new Hashtable<>(); + + + public GiftV2View(Context context) { + this(context, null); + } + + public GiftV2View(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public GiftV2View(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(context); + } + + private void init(Context context) { + this.context = context; + mSVGAParser = new SVGAParser(context); + mSVGAVideoEntityMap = new HashMap<>(20); + LayoutInflater.from(getContext()).inflate(R.layout.layout_gift_v2_view, this, true); + mScreenWidth = ResolutionUtils.getScreenWidth(getContext()); + mScreenHeight = ResolutionUtils.getScreenHeight(getContext()); + mGiftSendY = UIUtil.dip2px(context, 90); + giftWidth = UIUtil.dip2px(context, 80); + giftHeight = UIUtil.dip2px(context, 80); + + keyScale = new Keyframe[7]; + keyScale[0] = (Keyframe.ofFloat(0f, 1f)); + keyScale[1] = (Keyframe.ofFloat(0.1f, 1.3f)); + keyScale[2] = (Keyframe.ofFloat(0.2f, 1f)); + keyScale[3] = (Keyframe.ofFloat(0.3f, 1f)); + keyScale[4] = (Keyframe.ofFloat(0.5f, 2f)); + keyScale[5] = (Keyframe.ofFloat(0.8f, 2f)); + keyScale[6] = (Keyframe.ofFloat(1f, 1f)); + keyTrans = new Keyframe[3]; + keyTrans[0] = (Keyframe.ofFloat(0f, 0)); + keyTrans[1] = (Keyframe.ofFloat(0.2f, 0)); + keyTrans[2] = (Keyframe.ofFloat(0.3f, 0)); + + giftEffectInfoList = new ArrayList<>(); + mMagicReceivedInfos = new ArrayList<>(); + giftEffectView = findViewById(R.id.gift_effect_view); + mMagicExplodeView = findViewById(R.id.magic_explode_view); + giftEffectView.setGiftEffectListener(this); + handler = new UiHandler(this); + mMagicViewPool = new SvgaObjectPool(this); + } + + public void onReceiveMultiGiftMsg(MultiGiftReceiveInfo multiGiftReceiveInfo) { + if (multiGiftReceiveInfo != null) { + setVisibility(VISIBLE); + List targetUids = multiGiftReceiveInfo.getTargetUids(); + List giftReceiveInfos = new ArrayList<>(); + for (Long targetUid : targetUids) { + GiftReceiveInfo giftReceiveInfo = new GiftReceiveInfo(); + giftReceiveInfo.setUid(multiGiftReceiveInfo.getUid()); + giftReceiveInfo.setGiftNum(multiGiftReceiveInfo.getGiftNum()); + giftReceiveInfo.setTargetUid(targetUid); + giftReceiveInfo.setNick(multiGiftReceiveInfo.getNick()); + giftReceiveInfo.setGiftId(multiGiftReceiveInfo.getGiftId()); + giftReceiveInfo.setAvatar(multiGiftReceiveInfo.getAvatar()); + giftReceiveInfo.setGift(multiGiftReceiveInfo.getGift()); + //礼物值 + giftReceiveInfo.setGiftValueVos(multiGiftReceiveInfo.getGiftValueVos()); + giftReceiveInfo.setCurrentTime(multiGiftReceiveInfo.getCurrentTime()); + giftReceiveInfos.add(giftReceiveInfo); + } + drawGiftAnimation(giftReceiveInfos, GiftEffectInfo.GIFT_RECEIVE_TYPE_ALL); + } + } + + + private void drawMagicAnimation(List magicReceivedInfos) { + if (!AvRoomDataManager.get().mIsNeedGiftEffect) { + return; + } + + if (magicReceivedInfos.size() > 0) { + boolean needShowExplode = false; + MagicReceivedInfo explodeSvga = null; + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + // 算出是否需要显示爆炸动效 + for (MagicReceivedInfo magicReceivedInfo : magicReceivedInfos) { + boolean needShowExplodeEffect = magicReceivedInfo.isNeedShowExplodeEffect(); + if (needShowExplodeEffect) { + needShowExplode = true; + explodeSvga = magicReceivedInfo; + break; + } + } + + for (int i = 0; i < magicReceivedInfos.size(); i++) { + MagicReceivedInfo magicReceivedInfo = magicReceivedInfos.get(i); + SparseArray micViewPoint = AvRoomDataManager.get().mMicPointMap; + // 算出发送者和接受者的位置 + int senderPosition = AvRoomDataManager.get().getMicPosition(magicReceivedInfo.getUid()); + int receivePosition = AvRoomDataManager.get().getMicPosition(magicReceivedInfo.getTargetUid()); + + Point senderPoint = micViewPoint.get(senderPosition); + Point receivePoint = micViewPoint.get(receivePosition); + if (receivePoint == null) { //这种情况就是接收者已经不在麦上 + //礼物送到上面中间的位置 + receivePoint = new Point(UIUtil.getScreenWidth(context) / 2, + UIUtil.dip2px(context, 35)); + } + + drawMagicView(senderPoint, receivePoint, magicReceivedInfo); + + //totalCoin += giftInfo.getGoldPrice() * magicReceivedInfo.getGiftNum(); + } + if (needShowExplode && mMagicReceivedInfos.add(explodeSvga)) { + if (mMagicReceivedInfos.size() == 1 && !mMagicExplodeView.isAnimating()) { + Message msg = Message.obtain(); + msg.what = 1; + msg.obj = mMagicReceivedInfos.get(0); + handler.sendMessage(msg); + } + } + } + } + } + + private void drawMonsterAttackAnimation(List monsterAttackReceiveInfos, View monsterView) { + if (monsterAttackReceiveInfos.size() > 0) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + for (MonsterAttackInfo monsterAttackReceiveInfo : monsterAttackReceiveInfos) { + drawMonsterMagicView(monsterAttackReceiveInfo, monsterView); + } + } + } + } + + private void drawGiftAnimation(List giftReceiveInfos, int giftReceiveType) { + if (giftReceiveInfos.size() > 0) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + List targetUsers = new ArrayList<>(); + int totalCoin = 0; + + for (int i = 0; i < giftReceiveInfos.size(); i++) { + GiftReceiveInfo giftReceiveInfo = giftReceiveInfos.get(i); + SparseArray micViewPoint = AvRoomDataManager.get().mMicPointMap; + GiftInfo giftInfo = GiftModel.get().findGiftInfoById(giftReceiveInfo.getGiftId()); + if (giftInfo==null || TextUtils.isEmpty(giftInfo.getGiftUrl())){ + giftInfo = giftReceiveInfo.getGift(); + } + if (giftInfo == null) { + return; + } + // 算出发送者和接受者的位置 + int senderPosition = AvRoomDataManager.get().getMicPosition(giftReceiveInfo.getUid()); + int receivePosition = AvRoomDataManager.get().getMicPosition(giftReceiveInfo.getTargetUid()); + + // 离开模式给房主送礼 + if (roomInfo.isLeaveMode() && giftReceiveInfo.getTargetUid() == roomInfo.getUid()) + receivePosition = -1; + + Point senderPoint = micViewPoint.get(senderPosition); + Point receivePoint = micViewPoint.get(receivePosition); + if (receivePoint == null) { //这种情况就是接收者已经不在麦上 + //礼物送到上面中间的位置 + receivePoint = new Point(UIUtil.getScreenWidth(context) / 2, + UIUtil.dip2px(context, 35)); + } + giftReceiveInfo.setGift(giftInfo); + drawGiftView(senderPoint, receivePoint, giftReceiveInfo); + + totalCoin += giftInfo.getGoldPrice() * giftReceiveInfo.getGiftNum(); + + + GiftReceiver giftReceiver = new GiftReceiver(); + giftReceiver.setUid(giftReceiveInfo.getTargetUid()); + giftReceiver.setAvatar(giftReceiveInfo.getTargetAvatar()); + giftReceiver.setNick(giftReceiveInfo.getTargetNick()); + targetUsers.add(giftReceiver); + } + + if (totalCoin >= 520) { + Message msg = Message.obtain(); + msg.what = 0; + GiftReceiveInfo giftReceiveInfo = giftReceiveInfos.get(0); + GiftEffectInfo giftEffectInfo = new GiftEffectInfo(); + giftEffectInfo.setUid(giftReceiveInfo.getUid()); + giftEffectInfo.setNick(giftReceiveInfo.getNick()); + giftEffectInfo.setAvatar(giftReceiveInfo.getAvatar()); + giftEffectInfo.setGiftId(giftReceiveInfo.getGiftId()); + giftEffectInfo.setGiftNum(giftReceiveInfo.getGiftNum()); + giftEffectInfo.setGift(giftReceiveInfo.getGift()); + giftEffectInfo.setTargetUsers(targetUsers); + giftEffectInfo.setGiftReceiveType(giftReceiveType); + msg.obj = giftEffectInfo; + handler.sendMessageDelayed(msg, 200); + } + } + } + } + + public void onReceiveGiftToMultiMsg(GiftMultiReceiverInfo giftMultiReceiverInfo) { + if (giftMultiReceiverInfo != null) { + setVisibility(VISIBLE); + List targetUsers = giftMultiReceiverInfo.getTargetUsers(); + List giftReceiveInfos = new ArrayList<>(); + for (GiftReceiver targetUser : targetUsers) { + GiftReceiveInfo giftReceiveInfo = new GiftReceiveInfo(); + giftReceiveInfo.setUid(giftMultiReceiverInfo.getUid()); + giftReceiveInfo.setGiftNum(giftMultiReceiverInfo.getGiftNum()); + giftReceiveInfo.setTargetUid(targetUser.getUid()); + giftReceiveInfo.setNick(giftMultiReceiverInfo.getNick()); + giftReceiveInfo.setGiftId(giftMultiReceiverInfo.getGiftId()); + giftReceiveInfo.setAvatar(giftMultiReceiverInfo.getAvatar()); + giftReceiveInfo.setGift(giftMultiReceiverInfo.getGift()); + //礼物值 + giftReceiveInfo.setGiftValueVos(giftMultiReceiverInfo.getGiftValueVos()); + giftReceiveInfo.setCurrentTime(giftMultiReceiverInfo.getCurrentTime()); + + giftReceiveInfos.add(giftReceiveInfo); + } + drawGiftAnimation(giftReceiveInfos, GiftEffectInfo.GIFT_RECEIVE_TYPE_MULTI); + } + } + + private static class UiHandler extends Handler { + private WeakReference mReference; + + UiHandler(GiftV2View giftV2View) { + this.mReference = new WeakReference<>(giftV2View); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + GiftV2View giftV2View = mReference.get(); + if (giftV2View == null) return; + Activity activity = (Activity) giftV2View.context; + if (activity == null || activity.isDestroyed()) return; + if (msg.what == 0) { + // 播放礼物动效 + GiftEffectInfo giftEffectInfo = (GiftEffectInfo) msg.obj; + if (giftEffectInfo != null) { + giftV2View.drawGiftEffect(giftEffectInfo); + } + } else if (msg.what == 1) { + // 播放魔法svga + if (msg.obj == null) return; + MagicReceivedInfo explodeSvga = (MagicReceivedInfo) msg.obj; + String animationUrl = giftV2View.getValidExplodeAnimationUrl(explodeSvga.getMagicId(), + explodeSvga.getExplodeAnim()); + if (TextUtils.isEmpty(animationUrl)) return; + giftV2View.startSvgaAnimation(animationUrl, new SimpleParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + GiftV2View giftV2View = mReference.get(); + if (giftV2View == null) return; + giftV2View.cacheSvgaVideoItem(animationUrl, svgaVideoEntity); + SVGAImageView imageView = giftV2View.mMagicExplodeView; + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + imageView.setLoops(1); + imageView.setImageDrawable(drawable); + imageView.setClearsAfterStop(true); + imageView.startAnimation(); + imageView.setCallback(new SimpleSvgaCallback(giftV2View) { + @Override + public void onFinished() { + GiftV2View giftV2View = mReference.get(); + if (giftV2View == null) return; + // 移除上一次播放的爆炸特效 + giftV2View.mMagicReceivedInfos.remove(0); + int size = giftV2View.mMagicReceivedInfos.size(); + if (size > 0) { + Message message = Message.obtain(); + message.what = 1; + message.obj = giftV2View.mMagicReceivedInfos.get(0); + sendMessage(message); + } + } + }); + } + }); + } + } + } + + private boolean isCenter(MagicReceivedInfo magicReceivedInfo) { + int magicId = magicReceivedInfo.getMagicId(); + MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicId); + if (magicInfo == null) return magicReceivedInfo.getPosition() == MagicInfo.POS_CENTER; + return magicInfo.getPosition() == MagicInfo.POS_CENTER; + } + +// private boolean isCenter(MonsterAttackReceiveInfo monsterAttackReceiveInfo) { +// int magicId = Integer.parseInt(monsterAttackReceiveInfo.getMagicId()); +// MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicId); +// if (magicInfo == null) return monsterAttackReceiveInfo.getPosition() == MagicInfo.POS_CENTER; +// return magicInfo.getPosition() == MagicInfo.POS_CENTER; +// } + + private String getValidPathAnimationUrl(int magicId, String url) { + if (!TextUtils.isEmpty(url)) return url; + MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicId); + if (magicInfo == null) return ""; + return magicInfo.getPathAnim(); + } + + private String getValidExplodeAnimationUrl(int magicId, String url) { + if (XChatApplication.isDebug() && TextUtils.isEmpty(url)) + return "https://img.erbanyy.com/FpjaLK6_69udWlC_T6P5rmpaWlvT"; + if (!TextUtils.isEmpty(url)) return url; + MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicId); + if (magicInfo == null) return ""; + return magicInfo.getExplodeAnim(); + } + + public void onReceiveGiftMsg(GiftReceiveInfo giftReceiveInfo) { + List giftReceiveInfos = new ArrayList<>(); + giftReceiveInfos.add(giftReceiveInfo); + drawGiftAnimation(giftReceiveInfos, GiftEffectInfo.GIFT_RECEIVE_TYPE_SINGLE); + } + + public void onReceiveMagicMsg(MagicReceivedInfo magicReceivedInfo) { + List magicReceivedInfos = new ArrayList<>(); + magicReceivedInfos.add(magicReceivedInfo); + drawMagicAnimation(magicReceivedInfos); + } + + public void onReceiveMonsterAttackMsg(MonsterAttackInfo monsterAttackReceiveInfo, View monsterView) { + drawMonsterMagicView(monsterAttackReceiveInfo, monsterView); +// List monsterAttackReceiveInfos = new ArrayList<>(); +// monsterAttackReceiveInfos.add(monsterAttackReceiveInfo); +// drawMonsterAttackAnimation(monsterAttackReceiveInfos, monsterView); + } + + public void onReceiveMultiMagicMsg(MultiMagicReceivedInfo multiMagicReceivedInfo) { + if (multiMagicReceivedInfo != null) { + setVisibility(VISIBLE); + List targetUids = multiMagicReceivedInfo.getTargetUids(); + List magicReceivedInfos = new ArrayList<>(); + for (Long targetUid : targetUids) { + MagicReceivedInfo magicReceivedInfo = new MagicReceivedInfo(); + magicReceivedInfo.setUid(multiMagicReceivedInfo.getUid()); + magicReceivedInfo.setNumber(multiMagicReceivedInfo.getNumber()); + magicReceivedInfo.setTargetUid(targetUid); + magicReceivedInfo.setNick(multiMagicReceivedInfo.getNick()); + magicReceivedInfo.setMagicId(multiMagicReceivedInfo.getMagicId()); + magicReceivedInfo.setAvatar(multiMagicReceivedInfo.getAvatar()); + // 兼容旧版魔法面板无最新魔法的问题 + magicReceivedInfo.setPathAnim(multiMagicReceivedInfo.getPathAnim()); + magicReceivedInfo.setExplodeAnim(multiMagicReceivedInfo.getExplodeAnim()); + magicReceivedInfo.setNeedShowExplodeEffect(multiMagicReceivedInfo.isNeedShowExplode()); + magicReceivedInfo.setPosition(multiMagicReceivedInfo.getPosition()); + + magicReceivedInfo.setGiftValueVos(multiMagicReceivedInfo.getGiftValueVos()); + magicReceivedInfo.setCurrentTime(multiMagicReceivedInfo.getCurrentTime()); + magicReceivedInfos.add(magicReceivedInfo); + } + drawMagicAnimation(magicReceivedInfos); + } + } + + private void drawGiftEffect(GiftEffectInfo giftEffectInfo) { + giftEffectInfoList.add(giftEffectInfo); + if (!giftEffectView.isAnim()) { + giftEffectView.startGiftEffect(giftEffectInfo); + giftEffectInfoList.remove(0); + } + } + + /** + * 打怪兽时使用的动画效果 + * @param monsterAttackReceiveInfo + * @param monsterView + */ + private void drawMonsterMagicView(MonsterAttackInfo monsterAttackReceiveInfo, View monsterView) { + Point senderPoint = null; + if (Objects.equals(Long.valueOf(monsterAttackReceiveInfo.getUid()), AuthModel.get().getCurrentUid())) { + senderPoint = new Point(mScreenWidth - giftWidth, mScreenHeight - UIUtil.dip2px(context, 50)); + } else { + senderPoint = new Point(new Random().nextInt(mScreenWidth), mScreenHeight); + } + SVGAImageView imageView = mMagicViewPool.borrowGiftObject(senderPoint); + imageView.setVisibility(GONE); + ImageLoadUtils.loadImage(context, monsterAttackReceiveInfo.getMagicIcon(), imageView); + int[] location = new int[2]; + monsterView.getLocationInWindow(location); + int x = (location[0] + monsterView.getWidth() / 2) - giftWidth / 2; + int y = (location[1] + monsterView.getHeight() / 2) - giftHeight / 2; + Point receivePoint = new Point(x, y); + + Path path = getBezierCurvePath(senderPoint, receivePoint, false); + ValueAnimator pathAnimator; + // 当前版本小于21,需要 + if (Build.VERSION_CODES.LOLLIPOP > Build.VERSION.SDK_INT) { + pathAnimator = ObjectAnimator.ofFloat(0.0f, 1.0f); + pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + float[] point = new float[2]; + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float val = animation.getAnimatedFraction(); + PathMeasure pathMeasure = new PathMeasure(path, false); + pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null); + imageView.setTranslationX(point[0]); + imageView.setTranslationY(point[1]); + } + }); + } else { + pathAnimator = ObjectAnimator.ofFloat(imageView, View.TRANSLATION_X, View.TRANSLATION_Y, path); + } + pathAnimator.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationStart(Animator animation) { + imageView.setVisibility(VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + mMagicViewPool.returnObject(imageView); + currentAnimationMap.remove(monsterAttackReceiveInfo.getSequence()); + IMNetEaseManager.get().getChatRoomEventObservable().onNext(new RoomEvent() + .setEvent(RoomEvent.MONSTER_HUNTING_ANIMATION_FINISHED) + .setMonsterAttackReceiveInfo(monsterAttackReceiveInfo)); + } + }); + pathAnimator.setDuration(1000); + currentAnimationMap.put(monsterAttackReceiveInfo.getSequence(), monsterAttackReceiveInfo); + if (currentAnimationMap.size() >= 10) { + postDelayed(pathAnimator::start, 500); + } else { + pathAnimator.start(); + } + } + + private void drawMagicView(Point senderPoint, Point receivePoint, MagicReceivedInfo magicReceivedInfo) { + if (! AvRoomDataManager.get().mIsNeedGiftEffect) return; + + if (senderPoint == null) + senderPoint = new Point(mScreenWidth - giftWidth, mScreenHeight - UIUtil.dip2px(context, 50)); + SVGAImageView imageView = mMagicViewPool.borrowMagicObject(senderPoint); + String animationUrl = getValidPathAnimationUrl(magicReceivedInfo.getMagicId(), + magicReceivedInfo.getPathAnim()); + if (TextUtils.isEmpty(animationUrl)) return; + startSvgaAnimation(animationUrl, new SimpleParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + cacheSvgaVideoItem(animationUrl, svgaVideoEntity); + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + imageView.setLoops(1); + imageView.setImageDrawable(drawable); + imageView.setClearsAfterStop(true); + imageView.startAnimation(); + imageView.setCallback(new SimpleSvgaCallback(GiftV2View.this, imageView)); + } + + @Override + public void onError() { + super.onError(); + } + }); + + Path path = getBezierCurvePath(senderPoint, receivePoint, isCenter(magicReceivedInfo)); + ValueAnimator pathAnimator; + // 当前版本小于21,需要 + if (Build.VERSION_CODES.LOLLIPOP > Build.VERSION.SDK_INT) { + pathAnimator = ObjectAnimator.ofFloat(0.0f, 1.0f); + pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + float[] point = new float[2]; + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float val = animation.getAnimatedFraction(); + PathMeasure pathMeasure = new PathMeasure(path, false); + pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null); + imageView.setTranslationX(point[0]); + imageView.setTranslationY(point[1]); + } + }); + } else { + pathAnimator = ObjectAnimator.ofFloat(imageView, View.TRANSLATION_X, View.TRANSLATION_Y, path); + } + pathAnimator.setDuration(1000); + pathAnimator.start(); + } + + private void startSvgaAnimation(String animation, SimpleParseCompletion parseCompletion) { + try { + SVGAVideoEntity svgaVideoEntity = popSvgaVideoItem(animation); + if (svgaVideoEntity != null) { + System.out.println(TAG + ", 用缓存!"); + parseCompletion.onComplete(svgaVideoEntity); + } else { + System.out.println(TAG + ", 用io!"); + URL url = new URL(animation); + mSVGAParser.parse(url, parseCompletion); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void drawGiftView(Point senderPoint, Point receivePoint, GiftReceiveInfo giftReceiveInfo) { + if (!AvRoomDataManager.get().mIsNeedGiftEffect) { + return; + } + if (giftReceiveInfo == null) { + return; + } + GiftInfo giftInfo = giftReceiveInfo.getGift(); + if (giftInfo == null) { + return; + } + final Point center = new Point(); + center.x = context.getResources().getDisplayMetrics().widthPixels / 2; + center.y = context.getResources().getDisplayMetrics().heightPixels / 2; + if (senderPoint == null) { + senderPoint = new Point(mScreenWidth / 2 - giftWidth / 2, UIUtil.dip2px(context, 25)); + } + SVGAImageView imageView = mMagicViewPool.borrowGiftObject(senderPoint); + ImageLoadUtils.loadImage(context, giftInfo.getGiftUrl(), imageView); + + Keyframe keyTransX3 = (Keyframe.ofFloat(0.5f, center.x - senderPoint.x - giftWidth / 2)); + Keyframe keyTransX4 = (Keyframe.ofFloat(0.8f, center.x - senderPoint.x - giftWidth / 2)); + Keyframe keyTransX5 = (Keyframe.ofFloat(1f, receivePoint.x - senderPoint.x)); + + Keyframe keyTransY3 = (Keyframe.ofFloat(0.5f, center.y - senderPoint.y - giftHeight / 2)); + Keyframe keyTransY4 = (Keyframe.ofFloat(0.8f, center.y - senderPoint.y - giftHeight / 2)); + Keyframe keyTransY5 = (Keyframe.ofFloat(1f, receivePoint.y - senderPoint.y)); + + PropertyValuesHolder p0 = PropertyValuesHolder.ofKeyframe("translationX", keyTrans[0], keyTrans[1], keyTrans[2], keyTransX3, keyTransX4, keyTransX5); + PropertyValuesHolder p1 = PropertyValuesHolder.ofKeyframe("translationY", keyTrans[0], keyTrans[1], keyTrans[2], keyTransY3, keyTransY4, keyTransY5); + PropertyValuesHolder p2 = PropertyValuesHolder.ofKeyframe("scaleX", keyScale); + PropertyValuesHolder p3 = PropertyValuesHolder.ofKeyframe("scaleY", keyScale); + ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, p2, p3, p1, p0); + objectAnimator.setDuration(3200); + objectAnimator.start(); + objectAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mMagicViewPool.returnObject(imageView); + } + }); + } + + private Path getBezierCurvePath(Point sendPoint, Point receivePoint, boolean center) { + Point endPoint = new Point(receivePoint.x - sendPoint.x, receivePoint.y - sendPoint.y); + Point control = new Point(endPoint.x / 2, -(sendPoint.y + receivePoint.y) / 2 - new Random().nextInt(200)); + Path path = new Path(); + path.moveTo(0, 0); + float v1 = new Random().nextFloat(); + int pos = new Random().nextInt(50); + pos = v1 > 0.5F ? pos : -pos; + pos = center ? 0 : pos; + path.quadTo(control.x, control.y, endPoint.x + pos, endPoint.y + pos); + return path; + } + + public void release() { + dettached = true; + giftEffectInfoList.clear(); + giftEffectView.release(); + handler.removeCallbacksAndMessages(null); + handler.removeMessages(0); + mMagicExplodeView.stopAnimation(); + mMagicExplodeView.clearAnimation(); + mMagicViewPool.shutdown(); + } + + + @Override + public void onGiftEffectEnd() { + if (giftEffectInfoList != null && giftEffectInfoList.size() > 0) { + giftEffectView.startGiftEffect(giftEffectInfoList.get(0)); + giftEffectInfoList.remove(0); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + release(); + System.out.println(TAG + "onDetachedFromWindow: " + dettached); + } + + private static class SimpleSvgaCallback implements SVGACallback { + private SVGAImageView mImageView; + private WeakReference mReference; + + + SimpleSvgaCallback(GiftV2View giftV2View) { + mReference = new WeakReference<>(giftV2View); + } + + SimpleSvgaCallback(GiftV2View giftV2View, SVGAImageView imageView) { + mReference = new WeakReference<>(giftV2View); + this.mImageView = imageView; + } + + @Override + public void onPause() { + GiftV2View giftV2View = mReference.get(); + if (giftV2View == null) return; + if (mImageView == null) return; + mImageView.stopAnimation(true); + giftV2View.mMagicViewPool.returnObject(mImageView); +// ViewParent parent = this.mImageView.getParent(); +// if (parent != null && parent instanceof ViewGroup) { +// ((ViewGroup) parent).removeView(mImageView); +// } + } + + @Override + public void onFinished() { + GiftV2View giftV2View = mReference.get(); + if (giftV2View == null) return; + if (mImageView == null) return; + mImageView.stopAnimation(true); + giftV2View.mMagicViewPool.returnObject(mImageView); +// ViewParent parent = this.mImageView.getParent(); +// if (parent != null && parent instanceof ViewGroup) { +// ((ViewGroup) parent).removeViewInLayout(mImageView); +// } + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + } + + private SVGAVideoEntity popSvgaVideoItem(String url) { + return mSVGAVideoEntityMap.get(url); + } + + private void cacheSvgaVideoItem(String url, SVGAVideoEntity videoEntity) { + mSVGAVideoEntityMap.put(url, videoEntity); + } + + + private static class SimpleParseCompletion implements SVGAParser.ParseCompletion { + + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + + } + + @Override + public void onError() { + + } + } + + private static class SvgaObjectPool extends ObjectPool { + private WeakReference mReference; + + SvgaObjectPool(GiftV2View giftV2View) { + super(); + mReference = new WeakReference<>(giftV2View); + } + + private SVGAImageView cleanView(SVGAImageView imageView) { + imageView.setBackground(null); + imageView.setImageDrawable(null); + imageView.clearAnimation(); + imageView.setTranslationX(0); + imageView.setTranslationY(0); + imageView.setAlpha(1F); + imageView.setScaleX(1F); + imageView.setScaleY(1F); + imageView.setClearsAfterStop(true); + imageView.setCallback(null); + imageView.setVisibility(GONE); + return imageView; + } + + /** + * 返回一个礼物的imageView + * + * @param senderPoint - + * @return - + */ + SVGAImageView borrowGiftObject(Point senderPoint) { + GiftV2View parent = mReference.get(); + if (parent == null) return null; + SVGAImageView imageView = cleanView(super.borrowObject()); + LayoutParams params = new LayoutParams(parent.giftWidth, parent.giftHeight); + imageView.setLayoutParams(params); + params.leftMargin = senderPoint.x; + params.topMargin = senderPoint.y; + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + if (parent.indexOfChild(imageView) == -1) + parent.addView(imageView); + imageView.setVisibility(VISIBLE); + return imageView; + } + + /** + * 返回一个魔法的imageView + * + * @param senderPoint - + * @return - + */ + SVGAImageView borrowMagicObject(Point senderPoint) { + GiftV2View parent = mReference.get(); + if (parent == null) return null; + SVGAImageView imageView = cleanView(super.borrowObject()); + LayoutParams params = new LayoutParams(parent.giftWidth, parent.giftHeight); + imageView.setLayoutParams(params); + params.leftMargin = senderPoint.x; + params.topMargin = senderPoint.y; + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + imageView.setScaleX(1.5F); + imageView.setScaleY(1.5F); + if (parent.indexOfChild(imageView) == -1) + parent.addView(imageView); + imageView.setVisibility(VISIBLE); + return imageView; + } + + @Override + public void returnObject(SVGAImageView object) { + GiftV2View parent = mReference.get(); + if (parent == null || object == null) return; + int index; + if ((index = parent.indexOfChild(object)) >= 0 && object.isAttachedToWindow() && !parent.dettached) { + Log.e(TAG, ", stopAgain: " + parent.getChildCount()); + // TODO: 2018/3/23 为什么activity会在onStop之后一段时间才调用onDestroy, bug bug bug !!!!! + Context context = parent.context; + if (context instanceof Activity) { + boolean hasWindowFocus = ((Activity) context).hasWindowFocus(); + if (hasWindowFocus) { + parent.removeViewAt(index); + } + } + } + Log.e(TAG, "returnObject: " + parent.dettached); + Log.e(TAG, "parent svga image view count: " + (parent.getChildCount() - 2)); + super.returnObject(cleanView(object)); + } + + /** + * 不用直接调用这个 + */ + @Override + protected SVGAImageView createObject() { + GiftV2View parent = mReference.get(); + if (parent == null) return null; + return new SVGAImageView(parent.context); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftView.java new file mode 100644 index 000000000..5e2672baa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/GiftView.java @@ -0,0 +1,195 @@ +package com.yizhuan.erban.avroom.widget; + +import android.animation.ObjectAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.RelativeLayout; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.gift.widget.CustormAnim; +import com.yizhuan.erban.ui.gift.widget.GiftControl; +import com.yizhuan.erban.ui.gift.widget.GiftFrameLayout; +import com.yizhuan.erban.ui.gift.widget.GiftDataInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiveInfo; + +import org.jetbrains.annotations.NotNull; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * @author chenran + * @date 2017/7/29 + */ + +public class GiftView extends RelativeLayout implements SVGACallback { + public static final int TYPE_ROOM = 0; + public static final int TYPE_PERSONAL = 1; + private GiftFrameLayout giftFrameLayout1; + private GiftFrameLayout giftFrameLayout2; + private GiftControl giftControl; + private GiftDataInfo giftDataInfo; + private int type; + private SVGAImageView svgaImageView; + private List giftInfos; + private boolean isSvgaAnimate; + private View svgaBg; + + public GiftView(Context context) { + super(context); + init(); + } + + public GiftView(Context context, AttributeSet attr) { + super(context, attr); + init(); + } + + public GiftView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(); + } + + private void init() { + LayoutInflater.from(getContext()).inflate(R.layout.layout_gift_view, this, true); + findView(); + } + + private void findView() { + giftFrameLayout1 = (GiftFrameLayout) findViewById(R.id.gift_layout_1); + giftFrameLayout2 = (GiftFrameLayout) findViewById(R.id.gift_layout_2); + giftControl = new GiftControl(); + giftInfos = new ArrayList<>(); + SparseArray giftLayoutList = new SparseArray<>(); + + giftLayoutList.append(0, giftFrameLayout1); + giftLayoutList.append(1, giftFrameLayout2); + giftControl.setGiftLayout(false, giftLayoutList) + .setCustormAnim(new CustormAnim()); + + svgaImageView = (SVGAImageView) findViewById(R.id.svga_imageview); + svgaImageView.setCallback(this); + svgaImageView.setClearsAfterStop(true); + svgaImageView.setLoops(1); + svgaBg = findViewById(R.id.svga_imageview_bg); + } + + public void onReceivePersonalGift(GiftReceiveInfo giftRecieveInfo) { + if (type != TYPE_PERSONAL) { + return; + } + showGift(giftRecieveInfo); + } + + public void onReceiveGiftMsg(GiftReceiveInfo giftReceiveInfo) { + if (type != TYPE_ROOM) { + return; + } + showGift(giftReceiveInfo); + } + + private void showGift(GiftReceiveInfo giftReceiveInfo) { + GiftInfo giftInfo = com.yizhuan.xchat_android_core.gift.GiftModel.get().findGiftInfoById(giftReceiveInfo.getGiftId()); + if (giftInfo != null) { + giftDataInfo = new GiftDataInfo(); + giftDataInfo.setGiftId(giftInfo.getGiftId() + "").setGiftName("送出" + giftInfo.getGiftName()).setGiftCount(1).setGiftPic(giftInfo.getGiftUrl()) + .setSendUserId(giftReceiveInfo.getUid() + "").setSendUserName(giftReceiveInfo.getNick()).setSendUserPic(giftReceiveInfo.getAvatar()).setSendGiftTime(System.currentTimeMillis()) + .setCurrentStart(false).setGiftGroup(giftReceiveInfo.getGiftNum()); + giftControl.loadGift(giftDataInfo); + + if (giftInfo.isHasEffect() && !StringUtil.isEmpty(giftInfo.getVggUrl())) { + addGiftEffectToList(giftInfo); + } + } + } + + public void setType(int type) { + this.type = type; + } + + private void addGiftEffectToList(GiftInfo giftInfo) { + giftInfos.add(giftInfo); + if (!isSvgaAnimate) { + try { + drawSvgaEffect(giftInfo.getVggUrl()); + + } catch (MalformedURLException e) { + e.printStackTrace(); + } + giftInfos.remove(0); + } + } + + private void drawNext() { + if (giftInfos != null && giftInfos.size() > 0) { + try { + drawSvgaEffect(giftInfos.get(0).getVggUrl()); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + giftInfos.remove(0); + } + } + + private void drawSvgaEffect(String url) throws MalformedURLException { + isSvgaAnimate = true; + SVGAParser parser = new SVGAParser(getContext()); + parser.parse(new URL(url), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity videoItem) { + SVGADrawable drawable = new SVGADrawable(videoItem); + svgaImageView.setImageDrawable(drawable); + svgaImageView.startAnimation(); + svgaBg.setVisibility(VISIBLE); + ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(svgaBg, "alpha", 0.0F, 2.0F).setDuration(800); + objectAnimator1.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator1.start(); + } + + @Override + public void onError() { + isSvgaAnimate = false; + } + }); + + } + + + public void release() { + } + + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + svgaBg.setVisibility(GONE); + isSvgaAnimate = false; + drawNext(); + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/MagicTextView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/MagicTextView.java new file mode 100644 index 000000000..b31b7c4ca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/MagicTextView.java @@ -0,0 +1,329 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Join; +import android.graphics.Paint.Style; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.util.Pair; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.WeakHashMap; + +/** + * 该自定义view是用于显示礼物数字的 + * + * Success is the sum of small efforts, repeated day in and day out. + * 成功就是日复一日那一点点小小努力的积累。 + * AndroidGroup:158423375 + * Author:Johnny + * AuthorQQ:956595454 + * AuthorWX:Qiang_it + * AuthorPhone:nothing + * Created by 2016/9/22. + */ +public class MagicTextView extends TextView { + + private ArrayList outerShadows; + private ArrayList innerShadows; + + private WeakHashMap> canvasStore; + + private Canvas tempCanvas; + private Bitmap tempBitmap; + + private Drawable foregroundDrawable; + + private float strokeWidth; + private Integer strokeColor; + private Join strokeJoin; + private float strokeMiter; + + private int[] lockedCompoundPadding; + private boolean frozen = false; + + public MagicTextView(Context context) { + super(context); + init(null); + } + public MagicTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs); + } + public MagicTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(attrs); + } + + public void init(AttributeSet attrs){ + outerShadows = new ArrayList(); + innerShadows = new ArrayList(); + if(canvasStore == null){ + canvasStore = new WeakHashMap>(); + } + + if(attrs != null){ + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MagicTextView); + + String typefaceName = a.getString( R.styleable.MagicTextView_typeface); + if(typefaceName != null) { + Typeface tf = Typeface.createFromAsset(getContext().getAssets(), String.format("fonts/%s.ttf", typefaceName)); + setTypeface(tf); + } + + if(a.hasValue(R.styleable.MagicTextView_foreground)){ + Drawable foreground = a.getDrawable(R.styleable.MagicTextView_foreground); + if(foreground != null){ + this.setForegroundDrawable(foreground); + }else{ + this.setTextColor(a.getColor(R.styleable.MagicTextView_foreground, 0xff000000)); + } + } + + if(a.hasValue(R.styleable.MagicTextView_innerShadowColor)){ + this.addInnerShadow(a.getFloat(R.styleable.MagicTextView_innerShadowRadius, 0), + a.getFloat(R.styleable.MagicTextView_innerShadowDx, 0), + a.getFloat(R.styleable.MagicTextView_innerShadowDy, 0), + a.getColor(R.styleable.MagicTextView_innerShadowColor, 0xff000000)); + } + + if(a.hasValue(R.styleable.MagicTextView_outerShadowColor)){ + this.addOuterShadow(a.getFloat(R.styleable.MagicTextView_outerShadowRadius, 0), + a.getFloat(R.styleable.MagicTextView_outerShadowDx, 0), + a.getFloat(R.styleable.MagicTextView_outerShadowDy, 0), + a.getColor(R.styleable.MagicTextView_outerShadowColor, 0xff000000)); + } + + if(a.hasValue(R.styleable.MagicTextView_mstrokeColor)){ + float strokeWidth = a.getFloat(R.styleable.MagicTextView_mstrokeWidth, 1); + int strokeColor = a.getColor(R.styleable.MagicTextView_mstrokeColor, 0xff000000); + float strokeMiter = a.getFloat(R.styleable.MagicTextView_mstrokeMiter, 10); + Join strokeJoin = null; + switch(a.getInt(R.styleable.MagicTextView_strokeJoinStyle, 0)){ + case(0): strokeJoin = Join.MITER; break; + case(1): strokeJoin = Join.BEVEL; break; + case(2): strokeJoin = Join.ROUND; break; + } + this.setStroke(strokeWidth, strokeColor, strokeJoin, strokeMiter); + } + } + } + + public void setStroke(float width, int color, Join join, float miter){ + strokeWidth = width; + strokeColor = color; + strokeJoin = join; + strokeMiter = miter; + } + + public void setStroke(float width, int color){ + setStroke(width, color, Join.MITER, 10); + } + + public void addOuterShadow(float r, float dx, float dy, int color){ + if(r == 0){ r = 0.0001f; } + outerShadows.add(new Shadow(r,dx,dy,color)); + } + + public void addInnerShadow(float r, float dx, float dy, int color){ + if(r == 0){ r = 0.0001f; } + innerShadows.add(new Shadow(r,dx,dy,color)); + } + + public void clearInnerShadows(){ + innerShadows.clear(); + } + + public void clearOuterShadows(){ + outerShadows.clear(); + } + + public void setForegroundDrawable(Drawable d){ + this.foregroundDrawable = d; + } + + public Drawable getForeground(){ + return this.foregroundDrawable == null ? this.foregroundDrawable : new ColorDrawable(this.getCurrentTextColor()); + } + + + @Override + public void onDraw(Canvas canvas){ + super.onDraw(canvas); + + freeze(); + Drawable restoreBackground = this.getBackground(); + Drawable[] restoreDrawables = this.getCompoundDrawables(); + int restoreColor = this.getCurrentTextColor(); + + this.setCompoundDrawables(null, null, null, null); + + for(Shadow shadow : outerShadows){ + this.setShadowLayer(shadow.r, shadow.dx, shadow.dy, shadow.color); + super.onDraw(canvas); + } + this.setShadowLayer(0,0,0,0); + this.setTextColor(restoreColor); + + if(this.foregroundDrawable != null && this.foregroundDrawable instanceof BitmapDrawable){ + generateTempCanvas(); + super.onDraw(tempCanvas); + Paint paint = ((BitmapDrawable) this.foregroundDrawable).getPaint(); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); + this.foregroundDrawable.setBounds(canvas.getClipBounds()); + this.foregroundDrawable.draw(tempCanvas); + canvas.drawBitmap(tempBitmap, 0, 0, null); + tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + } + + if(strokeColor != null){ + TextPaint paint = this.getPaint(); +// paint.setTextAlign(Paint.Align.CENTER); + paint.setStyle(Style.STROKE); + paint.setStrokeJoin(strokeJoin); + paint.setStrokeMiter(strokeMiter); + this.setTextColor(strokeColor); + paint.setStrokeWidth(strokeWidth); + super.onDraw(canvas); + paint.setStyle(Style.FILL); + this.setTextColor(restoreColor); + } + if(innerShadows.size() > 0){ + generateTempCanvas(); + TextPaint paint = this.getPaint(); + for(Shadow shadow : innerShadows){ + this.setTextColor(shadow.color); + super.onDraw(tempCanvas); + this.setTextColor(0xFF000000); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + paint.setMaskFilter(new BlurMaskFilter(shadow.r, BlurMaskFilter.Blur.NORMAL)); + + tempCanvas.save(); + tempCanvas.translate(shadow.dx, shadow.dy); + super.onDraw(tempCanvas); + tempCanvas.restore(); + canvas.drawBitmap(tempBitmap, 0, 0, null); + tempCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + paint.setXfermode(null); + paint.setMaskFilter(null); + this.setTextColor(restoreColor); + this.setShadowLayer(0,0,0,0); + } + } + if(restoreDrawables != null){ + this.setCompoundDrawablesWithIntrinsicBounds(restoreDrawables[0], restoreDrawables[1], restoreDrawables[2], restoreDrawables[3]); + } + this.setBackgroundDrawable(restoreBackground); + this.setTextColor(restoreColor); + unfreeze(); + } + + private void generateTempCanvas(){ + String key = String.format("%dx%d", getWidth(), getHeight()); + Pair stored = canvasStore.get(key); + if(stored != null){ + tempCanvas = stored.first; + tempBitmap = stored.second; + }else{ + tempCanvas = new Canvas(); + tempBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); + tempCanvas.setBitmap(tempBitmap); + canvasStore.put(key, new Pair(tempCanvas, tempBitmap)); + } + } + + public void freeze(){ + lockedCompoundPadding = new int[]{ + getCompoundPaddingLeft(), + getCompoundPaddingRight(), + getCompoundPaddingTop(), + getCompoundPaddingBottom() + }; + frozen = true; + } + + public void unfreeze(){ + frozen = false; + } + + + @Override + public void requestLayout(){ + if(!frozen) super.requestLayout(); + } + + @Override + public void postInvalidate(){ + if(!frozen) super.postInvalidate(); + } + + @Override + public void postInvalidate(int left, int top, int right, int bottom){ + if(!frozen) super.postInvalidate(left, top, right, bottom); + } + + @Override + public void invalidate(){ + if(!frozen) super.invalidate(); + } + + @Override + public void invalidate(Rect rect){ + if(!frozen) super.invalidate(rect); + } + + @Override + public void invalidate(int l, int t, int r, int b){ + if(!frozen) super.invalidate(l,t,r,b); + } + + @Override + public int getCompoundPaddingLeft(){ + return !frozen ? super.getCompoundPaddingLeft() : lockedCompoundPadding[0]; + } + + @Override + public int getCompoundPaddingRight(){ + return !frozen ? super.getCompoundPaddingRight() : lockedCompoundPadding[1]; + } + + @Override + public int getCompoundPaddingTop(){ + return !frozen ? super.getCompoundPaddingTop() : lockedCompoundPadding[2]; + } + + @Override + public int getCompoundPaddingBottom(){ + return !frozen ? super.getCompoundPaddingBottom() : lockedCompoundPadding[3]; + } + + public static class Shadow{ + float r; + float dx; + float dy; + int color; + public Shadow(float r, float dx, float dy, int color){ + this.r = r; + this.dx = dx; + this.dy = dy; + this.color = color; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java new file mode 100644 index 000000000..9b80a562b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java @@ -0,0 +1,2267 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.support.v4.content.res.ResourcesCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SimpleItemAnimator; +import android.text.Editable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.text.style.ForegroundColorSpan; +import android.text.style.UnderlineSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.uinfo.UserInfoHelper; +import com.netease.nim.uikit.common.ui.span.RadiusBackgroundSpan; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessageExtension; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomNotificationAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.NotificationType; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.orhanobut.logger.Logger; +import com.tongdaxing.erban.sadmin.utils.SaAttachmentToMsgUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.dialog.PKResultDialog; +import com.yizhuan.erban.avroom.game.PlayGameActivity; +import com.yizhuan.erban.common.widget.CustomImageSpan; +import com.yizhuan.erban.common.widget.OriginalDrawStatusClickSpan; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.event.OpenRoomIntroEvent; +import com.yizhuan.erban.ui.widget.DividerItemDecoration; +import com.yizhuan.erban.ui.widget.MyItemAnimator; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.attachmsg.RoomQueueMsgAttachment; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiveInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiver; +import com.yizhuan.xchat_android_core.im.custom.bean.AuctionAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarveUpGoldAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameRespondAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftBatchAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.JoinMiniWorldAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.JoinMiniWorldNoticeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MagicAllMicAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MagicAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MagicBatchAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MonsterHuntingResultAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MonsterStatusAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MultiGiftAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.MusicInfoAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomBoxPrizeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomFollowOwnerAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomNoticeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomTipAttachment; +import com.yizhuan.xchat_android_core.im.game.ImGameInfo; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.level.UserLevelResourceType; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicMultiReceiverInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicReceivedInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicReceiver; +import com.yizhuan.xchat_android_core.magic.bean.MultiMagicReceivedInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.miniworld.bean.MiniWorldInWorldInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingResult; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterProtocol; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomMessageViewNoticeInfo; +import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameRespondEvent; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.room.ktv.bean.MusicInfo; +import com.yizhuan.xchat_android_core.room.pk.attachment.RoomPkAttachment; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPKInvitedUpMicMember; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.queuing_mic.attachment.QueuingMicAttachment; +import com.yizhuan.xchat_android_core.room.queuing_mic.bean.QueuingMicInfo; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import lombok.Setter; + +/** + * 直播间消息界面 + * + * @author xiaoyu + */ +public class MessageView extends FrameLayout { + + private static final String TAG = "MessageView"; + + private final static int MAX_MESSAGE_SIZE = 2000;//公屏最多展示条数 + private final static int BLOCK_MAX_MESSAGE_SIZE = MAX_MESSAGE_SIZE * 3 / 2;//在查看消息停住的时候 最多消息条数. + private RecyclerView messageListView; + private TextView tvBottomTip; + private MessageAdapter mMessageAdapter; + private List chatRoomMessages = new LinkedList<>(); + private LinearLayoutManager layoutManger; + private Disposable disposable; + private int paddingWidth; + private int paddingHeight; + private int whiteColor; + private int greyColor; + private int roomTipNickColor; + private int roomTipColor; + private int badgeWidth; + private int badgeHeight; + private int sysIconHeight; + private int smallFace; + private int bigFace; + private int expLevelWidth; + private int expLevelHeight; + private int giftLength; + + private volatile boolean needAutoScroll = true;//是否自动滚动到底部 + + @Setter + private Consumer clickConsumer; + + @Setter + private OnAcceptClick onClickListener; + + @Setter + private OnClick onClick; + + private DialogManager mDialogManager; + private Disposable subscribe; + + public void setDialogManager(DialogManager dialogManager) { + mDialogManager = dialogManager; + } + + public MessageView(Context context) { + this(context, null); + } + + public MessageView(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public MessageView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(context); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + List tmpList = AvRoomDataManager.get().getChatRoomMessages(); + if (!ListUtils.isListEmpty(tmpList)) { + this.chatRoomMessages.addAll(tmpList); + } + messageListView.scrollToPosition(mMessageAdapter.getItemCount() - 1); + disposable = AvRoomDataManager.get().getChatRoomMsgProcessor() + .subscribe(chatRoomMessage -> onCurrentRoomReceiveNewMsg(chatRoomMessage)); + + subscribe = RxBus.get().toFlowable(GameRespondEvent.class) + .subscribe(gameRespondEvent -> { + if (gameRespondEvent.second == CustomAttachment.CUSTOM_MSG_GAME_RESPOND_ACCEPT) { + receiveCustomNotification(gameRespondEvent.imGameInfo); + } else if (gameRespondEvent.second == CustomAttachment.CUSTOM_MSG_GAME_RESPOND_CANCEL) { + updateGameItemStatus(gameRespondEvent.fromAcount); + } + }); + } + + @Override + protected void onDetachedFromWindow() { + disposable.dispose(); + subscribe.dispose(); + super.onDetachedFromWindow(); + } + + + private void init(Context context) { + whiteColor = ContextCompat.getColor(context, R.color.white); + greyColor = ContextCompat.getColor(context, R.color.white_transparent_50); + roomTipNickColor = ContextCompat.getColor(context, R.color.color_FFEA7F); + roomTipColor = ContextCompat.getColor(context, R.color.color_FFEA7F); + paddingWidth = Utils.dip2px(context, 11); + paddingHeight = Utils.dip2px(context, 6); + badgeWidth = Utils.dip2px(context, 15); + badgeHeight = Utils.dip2px(context, 15); + sysIconHeight = Utils.dip2px(context, 14); + smallFace = Utils.dip2px(context, 22); + bigFace = Utils.dip2px(context, 30); + //经验等级图片后台已经更换尺寸了,公屏同步下,尺寸是114:45 + expLevelHeight = Utils.dip2px(context, 15); + expLevelWidth = expLevelHeight * 114 / 45; + giftLength = Utils.dip2px(context, 35); + // 内容区域 + layoutManger = new LinearLayoutManager(context, OrientationHelper.VERTICAL, false); + FrameLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + messageListView = new RecyclerView(context); + messageListView.setLayoutParams(params); + messageListView.setFadingEdgeLength(60); + messageListView.setVerticalFadingEdgeEnabled(true); + messageListView.setOverScrollMode(OVER_SCROLL_NEVER); + messageListView.setHorizontalScrollBarEnabled(false); + addView(messageListView); + messageListView.setLayoutManager(layoutManger); + messageListView.addItemDecoration(new DividerItemDecoration(context, layoutManger.getOrientation(), 16, R.color.transparent)); + mMessageAdapter = new MessageAdapter(getContext()); + mMessageAdapter.setData(chatRoomMessages); + messageListView.setAdapter(mMessageAdapter); + messageListView.setItemAnimator(new MyItemAnimator()); + messageListView.getItemAnimator().setAddDuration(0); + messageListView.getItemAnimator().setChangeDuration(0); + messageListView.getItemAnimator().setMoveDuration(0); + messageListView.getItemAnimator().setRemoveDuration(0); + ((SimpleItemAnimator) messageListView.getItemAnimator()).setSupportsChangeAnimations(false); + + // 底部有新消息 + tvBottomTip = new TextView(context); + FrameLayout.LayoutParams params1 = new LayoutParams( + Utils.dip2px(context, 115F), Utils.dip2px(context, 27)); + params1.gravity = Gravity.BOTTOM; + params1.leftMargin = UIUtil.getScreenWidth(context) / 2 - UIUtil.dip2px(context, 115 / 2); + tvBottomTip.setBackgroundResource(R.drawable.bg_messge_view_bottom_tip); + tvBottomTip.setGravity(Gravity.CENTER); + tvBottomTip.setText(context.getString(R.string.message_view_bottom_tip)); + tvBottomTip.setTextColor(context.getResources().getColor(R.color.appColor)); + tvBottomTip.setLayoutParams(params1); + tvBottomTip.setVisibility(GONE); + tvBottomTip.setOnClickListener(v -> { + Logger.e(TAG, "mMessageAdapter.getItemCount()->" + mMessageAdapter.getItemCount()); + tvBottomTip.setVisibility(GONE); + needAutoScroll = true; + messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1); + }); + addView(tvBottomTip); + + messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + } + + @Override + public void onScrollStateChanged(final RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { +// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_DRAGGING"); + needAutoScroll = false; + } + if (newState == RecyclerView.SCROLL_STATE_IDLE) { +// Logger.e(TAG, "onScrollStateChanged: SCROLL_STATE_IDLE"); + + int lastVisibleItemPosition = layoutManger.findLastVisibleItemPosition(); + if (lastVisibleItemPosition == RecyclerView.NO_POSITION) { +// Logger.e(TAG, "lastCompletelyVisibleItemPosition : RecyclerView.NO_POSITION"); + needAutoScroll = true; + } +// Log.e(TAG, "lastVisibleItemPosition:" + lastVisibleItemPosition +// + " mMessageAdapter.getItemCount()-1:" + (recyclerView.getAdapter().getItemCount()-1) +// + " dis:"+ (lastVisibleItemPosition-(recyclerView.getAdapter().getItemCount()-1))); + if (lastVisibleItemPosition >= recyclerView.getAdapter().getItemCount() - 3) { + //最后一个显示出来了 +// Logger.e(TAG, "lastCompletelyVisibleItemPosition : 最后可见 "); + needAutoScroll = true; + tvBottomTip.setVisibility(GONE); + keepSizeUnderLimit(); + } else { +// Logger.e(TAG, "lastCompletelyVisibleItemPosition : 最后一个没看见"); +// needAutoScroll = false; + } + } + } + }); + + } + + + public void onCurrentRoomReceiveNewMsg(ChatRoomMessage messages) { + addMessages(messages); + + } + + public int addMessages(ChatRoomMessage msg) { + if (msg == null) return -1; + chatRoomMessages.add(msg); + //通知adapter 刷新 + mMessageAdapter.notifyItemInserted(mMessageAdapter.getItemCount() - 1); + showTipsOrScrollToBottom(); + return chatRoomMessages.size() - 1; + } + + private void keepSizeUnderLimit() { + while (chatRoomMessages.size() > MAX_MESSAGE_SIZE) { + Log.i("keepSizeUnderLimit", "size" + chatRoomMessages.size()); + chatRoomMessages.remove(0); + mMessageAdapter.notifyItemRemoved(0); + } + } + + private void showTipsOrScrollToBottom() { + if (!needAutoScroll) { + tvBottomTip.setVisibility(VISIBLE); + //超过某值后自动滚动下去 + if (mMessageAdapter.getItemCount() > BLOCK_MAX_MESSAGE_SIZE) { + messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1); + } + return; + } + messageListView.smoothScrollToPosition(mMessageAdapter.getItemCount() - 1); + } + + public void release() { + + } + + /** + * 修改关注状态 + * + * @param position + * @param b + */ + public void changeFollowStatus(int position, boolean b) { + ChatRoomMessage chatRoomMessage = chatRoomMessages.get(position); + if (!(chatRoomMessage.getAttachment() instanceof RoomFollowOwnerAttachment)) { + return; + } + RoomFollowOwnerAttachment roomFollowOwnerAttachment = (RoomFollowOwnerAttachment) chatRoomMessage.getAttachment(); + roomFollowOwnerAttachment.setFollow(true); + mMessageAdapter.notifyItemChanged(position); + + } + + /** + * 修改加入小世界的状态 + * + * @param position + * @param b + */ + public void changeJoinMiniWorldStatus(int position, boolean b) { + ChatRoomMessage chatRoomMessage = chatRoomMessages.get(position); + if (!(chatRoomMessage.getAttachment() instanceof JoinMiniWorldAttachment)) { + return; + } + JoinMiniWorldAttachment joinMiniWorldAttachment = (JoinMiniWorldAttachment) chatRoomMessage.getAttachment(); + joinMiniWorldAttachment.setJoined(true); + mMessageAdapter.notifyItemChanged(position); + } + + + private class MessageAdapter extends RecyclerView.Adapter implements OnClickListener { + + private Context mContext; + private List data; + + public MessageAdapter(Context mContext) { + this.mContext = mContext; + } + + public void setData(List data) { + this.data = data; + } + + @Override + public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MessageViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_item_chatrrom_msg, parent, false)); + } + + @Override + public void onBindViewHolder(MessageViewHolder holder, int position) { + convert(holder, data.get(position)); + } + + @Override + public int getItemCount() { + return data.size(); + } + + class MessageViewHolder extends RecyclerView.ViewHolder { + TextView tvContent; + + public MessageViewHolder(View itemView) { + super(itemView); + tvContent = itemView.findViewById(R.id.tv_content); + } + } + + + protected void convert(MessageViewHolder baseViewHolder, ChatRoomMessage chatRoomMessage) { + if (chatRoomMessage == null) return; + TextView tvContent = baseViewHolder.tvContent; + tvContent.setLineSpacing(0, 1); + tvContent.setTextColor(Color.WHITE); + tvContent.setOnClickListener(this); + tvContent.setTag(chatRoomMessage); + + try { +// String bubble = NobleUtil.getResource(NobleResourceType.KEY_BUBBLE, chatRoomMessage); + if (chatRoomMessage.getMsgType() == MsgTypeEnum.tip) { + // 清除聊天背景 + clearBackground(tvContent); + // 房间通告 + if ("礼物特效".equals(chatRoomMessage.getContent())) { + setUpdateGiftEffectMsg(tvContent); + } +// else if (chatRoomMessage.getContent().contains(IMNetEaseManager.ROOM_INTRO_TAG)) { +// tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.color_FFE96E)); +// tvContent.setText(chatRoomMessage.getContent()); +// } + else if (XChatConstants.ROOM_INTRODUCTION.equals(chatRoomMessage.getContent()) || chatRoomMessage.getContent().contains(IMNetEaseManager.ROOM_INTRO_TAG)) { + tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.white)); + tvContent.setText(chatRoomMessage.getContent()); + } else { +// tvContent.setTextColor(Color.WHITE); + tvContent.setTextColor(ContextCompat.getColor(mContext, R.color.appColor)); + tvContent.setText(chatRoomMessage.getContent()); + } + } else if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) { + // 清除聊天背景 + clearBackground(tvContent); + setMsgText(chatRoomMessage, tvContent); + // 设置贵族背景 +// NobleUtil.loadResource(mContext, bubble, tvContent); + setRoomMessageBackground(chatRoomMessage, tvContent); + } else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) { + // 清除聊天背景 + clearBackground(tvContent); + // 加上勋章 + setMsgNotification(chatRoomMessage, tvContent); + } else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment(); + int first = attachment.getFirst(); + int second = attachment.getSecond(); + if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_AUCTION) { + setMsgAuction(chatRoomMessage, tvContent, attachment); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_ROOM_TIP) { + // 清除聊天背景 + clearBackground(tvContent); + setMsgRoomTip(tvContent, (RoomTipAttachment) attachment, chatRoomMessage); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_GIFT) { + // 清除聊天背景 + clearBackground(tvContent); + // 加上勋章 + setMsgHeaderGift(tvContent, (GiftAttachment) attachment, chatRoomMessage); + // 设置贵族气泡 +// NobleUtil.loadResource(mContext, bubble, tvContent); + setRoomMessageBackground(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_MULTI_GIFT) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_MULTI_GIFT) { + // 加上勋章 + setMsgMultiGift(tvContent, (MultiGiftAttachment) attachment, chatRoomMessage); + } else if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_BATCH_SEND_GIFT) { + setMsgBatchGift(tvContent, (GiftBatchAttachment) attachment, chatRoomMessage); + } + // 设置贵族气泡 +// NobleUtil.loadResource(mContext, bubble, tvContent); + setRoomMessageBackground(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_FACE) { + tvContent.setLineSpacing(Utils.dip2px(mContext, 6), 1); + // 清除聊天背景 + clearBackground(tvContent); + // 加上勋章 + setMsgFace(tvContent, (FaceAttachment) attachment, chatRoomMessage); + // 设置贵族气泡 + List faceReceiveInfos = ((FaceAttachment) attachment).getFaceReceiveInfos(); + if (faceReceiveInfos.size() == 1 && chatRoomMessage.getFromAccount().equals(String.valueOf(faceReceiveInfos.get(0).getUid()))) +// NobleUtil.loadResource(mContext, bubble, tvContent); + setRoomMessageBackground(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MESS_HEAD_NOBLE) { + // 清除聊天背景 + clearBackground(tvContent); + // 开通或续费贵族通知 + setMsgNobleOpenOrRenewText(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_SEND_MAGIC) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_SINGLE_MAGIC) { + setSingleMagicMsg(tvContent, (MagicAttachment) attachment, chatRoomMessage); + } else if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_MULTI_MAGIC) { + setAllMicMagicMsg(tvContent, (MagicAllMicAttachment) attachment, chatRoomMessage); + } else if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_BATCH_SEND_MAGIC) { + setMsgBatchMagic(tvContent, (MagicBatchAttachment) attachment, chatRoomMessage); + } + // 设置贵族气泡 +// NobleUtil.loadResource(mContext, bubble, tvContent); + setRoomMessageBackground(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_QUEUE) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_QUEUE_INVITE || TextUtils.isEmpty(((RoomQueueMsgAttachment) attachment).handleNick)) { + if (AvRoomDataManager.get().isQueuingMicro()) { + setInviteUpMicMsg(tvContent, (RoomQueueMsgAttachment) attachment); + } else { + tvContent.setVisibility(GONE); + } + } else { + setKickMsg(tvContent, (RoomQueueMsgAttachment) attachment); + } + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_SUPER_ADMIN) { + //超管 + clearBackground(tvContent); + CharSequence charSequence = SaAttachmentToMsgUtil.formatSuperAdminInfo(attachment, + tvContent, greyColor, roomTipColor); + if (charSequence != null) { + tvContent.setText(charSequence); + } + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_KICK_MIC) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_KICK_ROOM) { + setKickRoomMsg(tvContent, (RoomQueueMsgAttachment) attachment); + } else if (second == CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_ADD_BLACK) { + setAddBlackMsg(tvContent, (RoomQueueMsgAttachment) attachment); + } + } else if (first == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_MONSTER_HUNTING) { + // 清除聊天背景 + clearBackground(tvContent); + switch (second) { + case CustomAttachment.CUSTOM_MSG_SUB_TYPE_MONSTER_HUNTING: + MonsterProtocol.DataBean dataBean = ((MonsterStatusAttachment) attachment).getDataBean(); + setMonsterNotifyMessage(tvContent, dataBean.getNotifyMessage()); + break; + + case CustomAttachment.CUSTOM_NOTI_SUB_GAME_RESULT: + MonsterHuntingResult result = ((MonsterHuntingResultAttachment) attachment).getResult(); + setMonsterNotifyMessage(tvContent, result.getMonster().getNotifyMessage()); + break; + } + } else if (first == CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_AUDIO) { + setUpdateAudioMsg(tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_GIFT) { + setUpdateGiftEffectMsg(tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_CLOSE_SCREEN) { + String content = chatRoomMessage.getContent(); + setUpdateScreenMsg(tvContent, content); + } else if (second == CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_NOTICE) { + setUpdateRoomPureModeMsg(tvContent, chatRoomMessage); + } + } else if (first == CustomAttachment.CUSTOM_MSG_DRAGON_BAR) { + // 清除聊天背景 + clearBackground(tvContent); + if (second == CustomAttachment.CUSTOM_MSG_DRAGON_BAR_END) { + setDragonBarMsg(chatRoomMessage, tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_DRAGON_BAR_CANCEL) { + setDragonBarCancelMsg(chatRoomMessage, tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_DRAGON_BAR_RUNAWAY) { + setDragonBarRunawayMsg(chatRoomMessage, tvContent); + } + } else if (first == CustomAttachment.CUSTOM_MSG_BOX) { + // 清除聊天背景 + clearBackground(tvContent); + setBoxMeMsg(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_KTV) { + clearBackground(tvContent); + setKtvMsg(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_QUEUING_MIC) { + // 清除聊天背景 + clearBackground(tvContent); + switch (second) { + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_NON_EMPTY: + break; + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_EMPTY: + break; + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_MODE_OPEN: + startQueuingMicModeMsg(tvContent); + break; + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_MODE_CLOSE: + stopQueuingMicModeMsg(tvContent); + break; + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_FREE_MIC_OPEN: + switchToFreeMicMsg(tvContent, chatRoomMessage); + break; + case CustomAttachment.CUSTOM_MSG_SUB_QUEUING_MIC_FREE_MIC_CLOSE: + switchToLockMicMsg(tvContent, chatRoomMessage); + break; + } + } else if (first == CustomAttachment.CUSTOM_MESS_HEAD_ROOM_PK) { + // 清除聊天背景 + clearBackground(tvContent); + switch (second) { + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_EMPTY: + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_NON_EMPTY: + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_MODE_OPEN: + openRoomPKModeMsg((RoomPkAttachment) attachment, tvContent); + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_MODE_CLOSE: + stopRoomPkModeMsg(tvContent); + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_MODE_START: + startRoomPk((RoomPkAttachment) attachment, tvContent); + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_RE_START: + restartRoomPKModeMsg((RoomPkAttachment) attachment, tvContent); + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_RESULT: + roomPkResult((RoomPkAttachment) attachment, tvContent); + break; + case CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_INVITE: + invitePK((RoomPkAttachment) attachment, tvContent); + break; + } + } else if (first == CustomAttachment.CUSTOM_MSG_GAME) { + clearBackground(tvContent); + try { + if (second == CustomAttachment.CUSTOM_MSG_GAME_OPEN) { + setGameOpenMsg(tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_GAME_CLOSE) { + setGameCloseMsg(tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_GAME_SELECT) { + setGameSelectedMsg(chatRoomMessage, tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_GAME_START) { + setGameEnterMsg(chatRoomMessage, tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_GAME_END) { + setGameResultMsg(chatRoomMessage, tvContent); + } else if (second == CustomAttachment.CUSTOM_MSG_GAME_AI_ENTER) { + setGameAiEnterMsg(chatRoomMessage, tvContent); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else if (first == CustomAttachment.CUSTOM_MSG_IM_GAME) { + clearBackground(tvContent); + try { + gameSponsorMsg(chatRoomMessage, tvContent); + } catch (Exception e) { + } + } else if (first == CustomAttachment.CUSTOM_MSG_GAME_RESPOND + && second == CustomAttachment.CUSTOM_MSG_GAME_RESPOND_ACCEPT) { + clearBackground(tvContent); + try { + gameRespondMsg(chatRoomMessage, tvContent); + } catch (Exception e) { + } + } else if (first == CustomAttachment.CUSTOM_MSG_SIGN_IN + && second == CustomAttachment.CUSTOM_MSG_SUB_CARVE_UP_GOLD_SECOND_LEVEL) { + //二级瓜分金币 + // 清除聊天背景 + clearBackground(tvContent); + setCarveUpGoldMsg(chatRoomMessage, tvContent); + } else if (first == CustomAttachment.CUSTOM_MSG_MINI_WORLD) { + switch (second) { + case CustomAttachment.CUSTOM_MSG_GROUP_CHAT_ROOM_JOIN_TIP: + setJoinMiniWorldTips(baseViewHolder.getAdapterPosition(), chatRoomMessage, tvContent); + break; + case CustomAttachment.CUSTOM_MSG_GROUP_ROOM_JOIN_NOTICE: + setJoinedMiniWorldNoticeMessage(baseViewHolder.getAdapterPosition(), chatRoomMessage, tvContent); + break; + case CustomAttachment.CUSTOM_MSG_ROOM_FOLLOW: + setRoomFollowOwner(baseViewHolder.getAdapterPosition(), chatRoomMessage, tvContent); + break; + default: + tvContent.setTextColor(Color.WHITE); + tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip)); + break; + } + } else { + tvContent.setTextColor(Color.WHITE); + tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip)); + } + + } + } catch (UnsupportedOperationException e) { + tvContent.setTextColor(Color.WHITE); + tvContent.setText(tvContent.getResources().getText(R.string.not_support_message_tip)); + } + } + + /** + * 提示已经加入的小世界的通知 + * + * @param adapterPosition + * @param chatRoomMessage + * @param tvContent + */ + private void setJoinedMiniWorldNoticeMessage(int adapterPosition, ChatRoomMessage chatRoomMessage, TextView tvContent) { + clearBackground(tvContent); + if (!(chatRoomMessage.getAttachment() instanceof JoinMiniWorldNoticeAttachment)) { + return; + } + JoinMiniWorldNoticeAttachment joinMiniWorldNoticeAttachment = (JoinMiniWorldNoticeAttachment) chatRoomMessage.getAttachment(); + String nick = TextUtils.isEmpty(joinMiniWorldNoticeAttachment.getNick()) ? "" : joinMiniWorldNoticeAttachment.getNick(); + String worldName = TextUtils.isEmpty(joinMiniWorldNoticeAttachment.getWorldName()) ? "" : joinMiniWorldNoticeAttachment.getWorldName(); + SpannableBuilder append = new SpannableBuilder(tvContent) + .append("欢迎") + .append(" " + nick + " ", new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + new UserInfoDialog(mContext, joinMiniWorldNoticeAttachment.getUid()).show(); + } + }, new ForegroundColorSpan(roomTipNickColor)) + .append("加入") + .append(" 【" + worldName + "】 ", new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (onClick != null) { + onClick.onJoinMiniWorldClick(adapterPosition); + } + } + }); + + tvContent.setText(append.build()); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * 提示加入小世界 + * + * @param adapterPosition + * @param chatRoomMessage + * @param tvContent + */ + private void setJoinMiniWorldTips(int adapterPosition, ChatRoomMessage chatRoomMessage, TextView tvContent) { + if (!(chatRoomMessage.getAttachment() instanceof JoinMiniWorldAttachment)) { + return; + } + tvContent.setTextColor(Color.WHITE); + JoinMiniWorldAttachment joinMiniWorldAttachment = (JoinMiniWorldAttachment) chatRoomMessage.getAttachment(); + MiniWorldInWorldInfo miniWorldInWorldInfo = joinMiniWorldAttachment.getMiniWorldInfo(); + if (miniWorldInWorldInfo == null) { + throw new UnsupportedOperationException(); + } + boolean joined = joinMiniWorldAttachment.isJoined(); + clearBackground(tvContent); + SpannableBuilder append = new SpannableBuilder(tvContent) + .append("欢迎进入") + .append(" 【" + miniWorldInWorldInfo.getWorldName() + "】 ", new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (onClick != null) { + onClick.onJoinMiniWorldClick(adapterPosition); + } + } + }) + .append(",加入小世界与小伙伴一起狂欢吧") + .append("加入", new RadiusBackgroundSpan(joined ? Color.parseColor("#4cFFFFFF") : ContextCompat.getColor(tvContent.getContext(), R.color.appColor), SizeUtils.dp2px(tvContent.getContext(), 8), joined ? Color.parseColor("#D8FFFFFF") : Color.WHITE, (int) (tvContent.getTextSize() - SizeUtils.sp2px(tvContent.getContext(), 2) - .5f), SizeUtils.dp2px(tvContent.getContext(), 8), SizeUtils.dp2px(tvContent.getContext(), 4)) + , joined ? null : new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (onClick != null) { + onClick.onJoinMiniWorldClick(adapterPosition); + } + } + }); + + tvContent.setText(append.build()); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * 房间公屏提示关注房主 + * + * @param chatRoomMessage + * @param tvContent + */ + private void setRoomFollowOwner(int position, ChatRoomMessage chatRoomMessage, TextView tvContent) { + if (!(chatRoomMessage.getAttachment() instanceof RoomFollowOwnerAttachment)) { + return; + } + tvContent.setTextColor(Color.WHITE); + RoomFollowOwnerAttachment roomFollowOwnerAttachment = (RoomFollowOwnerAttachment) chatRoomMessage.getAttachment(); + UserInfo userInfo = roomFollowOwnerAttachment.getUserInfo(); + String nick; + if (userInfo == null) { + nick = " "; + } else { + nick = userInfo.getNick(); + } + clearBackground(tvContent); + boolean follow = roomFollowOwnerAttachment.isFollow(); + SpannableBuilder append = new SpannableBuilder(tvContent) + .append("欢迎") + .append(" " + nick + " ", new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + SingleToastUtil.showToast("加入"); + new UserInfoDialog(mContext, userInfo.getUid()).show(); + } + }, new ForegroundColorSpan(roomTipNickColor)) + .append("关注房主不迷路哦") +// .append("关注", new RoundBackgroundSpan(tvContent.getContext(), ContextCompat.getColor(tvContent.getContext(), R.color.appColor), Color.WHITE, SizeUtils.dp2px(tvContent.getContext(), 8))) +// .append(follow ? "已关注" : "关注", +// new TagSpan(Color.WHITE, ContextCompat.getColor(tvContent.getContext(), follow ? R.color.gray7 : R.color.appColor), (int) tvContent.getTextSize(), SizeUtils.dp2px(tvContent.getContext(), 8)), +// follow ? null : new OriginalDrawStatusClickSpan() { +// @Override +// public void onClick(@NonNull View widget) { +// if (onClick != null) { +// onClick.onFollowClick(position); +// } +// } +// }); + .append(follow ? "已关注" : "关注", + new RadiusBackgroundSpan(follow ? Color.parseColor("#4cFFFFFF") : ContextCompat.getColor(tvContent.getContext(), R.color.appColor), SizeUtils.dp2px(tvContent.getContext(), 8), follow ? Color.parseColor("#D8FFFFFF") : Color.WHITE, (int) (tvContent.getTextSize() - SizeUtils.sp2px(tvContent.getContext(), 2) - .5f), SizeUtils.dp2px(tvContent.getContext(), 8), SizeUtils.dp2px(tvContent.getContext(), 4)), + follow ? null : new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (onClick != null) { + onClick.onFollowClick(position); + } + } + }); + tvContent.setText(append.build()); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void gameRespondMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + GameRespondAttachment attachment = (GameRespondAttachment) chatRoomMessage.getAttachment(); + + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(attachment.getImGameInfo().getNick(), new ForegroundColorSpan(roomTipColor)) + .append(" 已接受你的游戏邀请,游戏准备开始 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void gameSponsorMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + ImGameAttachment attachment = (ImGameAttachment) chatRoomMessage.getAttachment(); + SpannableBuilder text = null; + + if (chatRoomMessage.getFromAccount().equals(AuthModel.get().getCurrentUid() + "")) { + SpannableBuilder append = new SpannableBuilder(tvContent) + .append(" 你已发起 ", new ForegroundColorSpan(greyColor)) + .append("【" + attachment.getImGameInfo().getGameInfo().getGameName() + "】", new ForegroundColorSpan(roomTipColor)) + .append(" 游戏, 等待玩家加入(" + ImGameMode.TIME + "秒内有效)", new ForegroundColorSpan(greyColor)); + if (attachment.getImGameInfo().getStatus() == ImGameInfo.TIMEING) { + append.append(" 取消 ", new ForegroundColorSpan(Color.WHITE), new UnderlineSpan()); + } else if (attachment.getImGameInfo().getStatus() == ImGameInfo.ACCEPTED) { + append.append(" 已接受 ", new ForegroundColorSpan(greyColor)); + } else if (attachment.getImGameInfo().getStatus() == ImGameInfo.INVALID) { + append.append(" 已失效 ", new ForegroundColorSpan(greyColor)); + } + text = append; + } else { + SpannableBuilder append = new SpannableBuilder(tvContent) + .append(attachment.getImGameInfo().getNick(), new ForegroundColorSpan(roomTipColor)) + .append(" 发起 ", new ForegroundColorSpan(greyColor)) + .append("【" + attachment.getImGameInfo().getGameInfo().getGameName() + "】", new ForegroundColorSpan(roomTipColor)) + .append(" 游戏 ", new ForegroundColorSpan(greyColor)); + if (attachment.getImGameInfo().getStatus() == ImGameInfo.TIMEING) { + append.append(" 接受 ", new ForegroundColorSpan(Color.parseColor("#7EFFDC")), new UnderlineSpan()); + } else if (attachment.getImGameInfo().getStatus() == ImGameInfo.ACCEPTED) { + if (attachment.getImGameInfo().getAcceptUid() == AuthModel.get().getCurrentUid()) { + append.append(" 已接受 ", new ForegroundColorSpan(greyColor)); + } else { + append.append(" 观战 ", new ForegroundColorSpan(Color.parseColor("#7EFFDC")), new UnderlineSpan()); + } + } else if (attachment.getImGameInfo().getStatus() == ImGameInfo.INVALID) { + append.append(" 已失效 ", new ForegroundColorSpan(greyColor)); + } + text = append; + } + + tvContent.setText(text.build()); + } + + private void setGameAiEnterMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + GameAttachment attachment = (GameAttachment) chatRoomMessage.getAttachment(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(attachment.getGameInfo().nick, new ForegroundColorSpan(roomTipColor)) + .append(" 进入了房间 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setGameResultMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + GameAttachment attachment = (GameAttachment) chatRoomMessage.getAttachment(); + GameResultInfo.ResultBean gameResultInfo = attachment.getGameInfo().getGameResultInfo(); + GameModel.get().getGameInfoById(gameResultInfo.getGameId()). + subscribe(gameInfo -> { + if (gameResultInfo.getResultType().equals(GameResultInfo.NOT_DRAW)) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息:【" + gameInfo.getGameName() + "】", new ForegroundColorSpan(roomTipColor)) + .append("恭喜 ", new ForegroundColorSpan(greyColor)) + .append(gameResultInfo.getWinners().get(0).getName(), new ForegroundColorSpan(roomTipColor)) + .append("战胜 ", new ForegroundColorSpan(greyColor)) + .append(gameResultInfo.getFailers().get(0).getName(), new ForegroundColorSpan(roomTipColor)); + tvContent.setText(text.build()); + } else { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息:【" + gameInfo.getGameName() + "】", new ForegroundColorSpan(roomTipColor)) + .append("打成平手 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + }); + } + + private void setGameExitMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + + } + + private void setGameEnterMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + GameAttachment attachment = (GameAttachment) chatRoomMessage.getAttachment(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(attachment.getGameInfo().nick, new ForegroundColorSpan(roomTipColor)) + .append("加入 ", new ForegroundColorSpan(greyColor)) + .append(attachment.getGameInfo().getGameInfo().getGameName(), new ForegroundColorSpan(roomTipColor)) + .append("游戏 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setGameSelectedMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + GameAttachment attachment = (GameAttachment) chatRoomMessage.getAttachment(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(attachment.getGameInfo().nick, new ForegroundColorSpan(roomTipColor)) + .append("发起 ", new ForegroundColorSpan(greyColor)) + .append(attachment.getGameInfo().getGameInfo().getGameName(), new ForegroundColorSpan(roomTipColor)) + .append("游戏,赶紧来玩 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setGameOpenMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append("房主开启快玩模式,赶紧加入吧 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setGameCloseMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append("房主关闭快玩模式 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void invitePK(RoomPkAttachment attachment, TextView tvContent) { + Map micMemberMap = attachment.getRoomPKInvitedUpMicMemberMap(); + + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("房主/管理员邀请"); + boolean isHaveInTeam = false; + Iterator> iterator = micMemberMap.entrySet().iterator(); + while (iterator.hasNext()) { + RoomPKInvitedUpMicMember value = iterator.next().getValue(); + //没有队伍的不提示 + if (value.getGroupType() == PKTeamInfo.TEAM_NONE) { + continue; + } + + isHaveInTeam = true; + text.append(value.getNick(), new ForegroundColorSpan(roomTipColor), + new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(value.getUid()).subscribe(clickConsumer); + } + } + }) + .append("进入"); + if (value.getGroupType() == PKTeamInfo.TEAM_RED) { + text.append("红队", new ForegroundColorSpan(tvContent.getResources().getColor(R.color.color_FB3D74))) + .append(","); + } else if (value.getGroupType() == PKTeamInfo.TEAM_BLUE) { + text.append("蓝队", new ForegroundColorSpan(tvContent.getResources().getColor(R.color.color_3291FC))) + .append(","); + } else { + text.append("未知队伍", new ForegroundColorSpan(whiteColor)) + .append(","); + } + } + if (isHaveInTeam) { + Editable msg = text.builder; + msg.delete(msg.length() - 1, msg.length()); + tvContent.setText(msg); + tvContent.setOnClickListener(null); + + + } + } + + public void setRoomMessageBackground(ChatRoomMessage chatRoomMessage, View view) { + int level = 0; + try { + String levelStr = NobleUtil.getNobleLevel(chatRoomMessage); + if (TextUtils.isEmpty(levelStr)) return; + level = Integer.valueOf(levelStr); + if (level <= 0) { + return; + } + } catch (Exception e) { + return; + } + + Drawable drawable = null; + switch (level) { + case 4: + drawable = view.getResources().getDrawable(R.drawable.bg_room_message_noble_4); + break; + case 5: + drawable = view.getResources().getDrawable(R.drawable.bg_room_message_noble_5); + break; + case 6: + drawable = view.getResources().getDrawable(R.drawable.bg_room_message_noble_6); + break; + case 7: + drawable = view.getResources().getDrawable(R.drawable.bg_room_message_noble_7); + break; + default: + break; + } + if (drawable != null) { + view.setBackground(drawable); + view.setPadding(paddingWidth, paddingHeight, paddingWidth, paddingHeight); + } + } + + private void openRoomPKModeMsg(RoomPkAttachment attachment, TextView tvContent) { + RoomPkData roomPkData = attachment.getRoomPkData(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(String.format(Locale.getDefault(), "管理员发起房间PK,本次PK时间为 %s 秒,获得", + roomPkData.getDuration()), + new ForegroundColorSpan(whiteColor)); + switch (roomPkData.getVoteMode()) { + case RoomPkData.VOTE_MODE_GIFT: + text.append("礼物多", new ForegroundColorSpan(whiteColor)); + break; + + case RoomPkData.VOTE_MODE_PERSON: + text.append("送礼人数多", new ForegroundColorSpan(whiteColor)); + break; + } + text.append("的团队获胜", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void stopRoomPkModeMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员", new ForegroundColorSpan(whiteColor)) + .append("关闭了", new ForegroundColorSpan(greyColor)) + .append("房间 PK 模式", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void startRoomPk(RoomPkAttachment attachment, TextView textView) { + RoomPkData roomPkData = attachment.getRoomPkData(); + SpannableBuilder text = new SpannableBuilder(textView) + .append(String.format(Locale.getDefault(), + "PK开始啦!本次PK时间 %s 秒,快给喜欢的选手投票吧!", roomPkData.getDuration()), + new ForegroundColorSpan(greyColor)); + textView.setText(text.build()); + } + + private void restartRoomPKModeMsg(RoomPkAttachment attachment, TextView tvContent) { + RoomPkData roomPkData = attachment.getRoomPkData(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(String.format(Locale.getDefault(), "管理员重新开始房间PK,本次PK时间为 %s 秒,获得", + roomPkData.getDuration()), + new ForegroundColorSpan(whiteColor)); + switch (roomPkData.getVoteMode()) { + case RoomPkData.VOTE_MODE_GIFT: + text.append("礼物多", new ForegroundColorSpan(whiteColor)); + break; + + case RoomPkData.VOTE_MODE_PERSON: + text.append("送礼人数多", new ForegroundColorSpan(whiteColor)); + break; + } + text.append("的团队获胜", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void roomPkResult(RoomPkAttachment attachment, TextView textView) { + RoomPkData roomPkData = attachment.getRoomPkData(); + SpannableBuilder text = new SpannableBuilder(textView) + .append("本场PK结果:", new ForegroundColorSpan(whiteColor)); + Map teamMap = new HashMap<>(); + PKTeamInfo blueTeam = null; + PKTeamInfo redTeam = null; + if (roomPkData.getTeams() != null) { + for (PKTeamInfo roomPkTeam : roomPkData.getTeams()) { + teamMap.put(String.valueOf(roomPkTeam.getTeam()), roomPkTeam); + } + blueTeam = teamMap.get(String.valueOf(PKTeamInfo.TEAM_BLUE)); + redTeam = teamMap.get(String.valueOf(PKTeamInfo.TEAM_RED)); + } + switch (roomPkData.getResult()) { + case RoomPkData.PK_RESULT_DRAW: + text.append("平局!\n", new ForegroundColorSpan(whiteColor)); + if (blueTeam != null && redTeam != null) { + text.append(String.format(Locale.getDefault(), "PK值 %s : %s \n", + FormatUtils.formatToShortHalfUp(blueTeam.getScore()), + FormatUtils.formatToShortHalfUp(redTeam.getScore())), + new ForegroundColorSpan(whiteColor)); + + UserInfo redProtector = redTeam.getProtector(); + UserInfo blueProtector = blueTeam.getProtector(); + if (redProtector == null || redProtector.getUid() == 0 + || blueProtector == null || blueProtector.getUid() == 0) { + break; + } + text.append(String.format(Locale.getDefault(), "蓝队守护者:%s \n", blueProtector.getNick()), + new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), "蓝队守护值:%s \n", + FormatUtils.formatToShortHalfUp(blueTeam.getProtecScore())), + new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), "红队守护者:%s \n", redProtector.getNick()), + new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), "红队守护值:%s \n", + FormatUtils.formatToShortHalfUp(redTeam.getProtecScore())), + new ForegroundColorSpan(whiteColor)); + } + break; + + case PKTeamInfo.TEAM_BLUE: + text.append("蓝队胜利!\n", new ForegroundColorSpan(whiteColor)); + if (blueTeam != null && redTeam != null) { + text.append(String.format(Locale.getDefault(), "PK值 %s : %s \n", + FormatUtils.formatToShortHalfUp(blueTeam.getScore()), + FormatUtils.formatToShortHalfUp(redTeam.getScore())), + new ForegroundColorSpan(whiteColor)); + + UserInfo blueProtector = blueTeam.getProtector(); + if (blueProtector == null) { + break; + } + text.append(String.format(Locale.getDefault(), "胜方守护者:%s \n", blueProtector.getNick()), + new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), "胜方守护值:%s \n", + FormatUtils.formatToShortHalfUp(blueTeam.getProtecScore())), + new ForegroundColorSpan(whiteColor)); + } + break; + + case PKTeamInfo.TEAM_RED: + text.append("红队胜利!\n", new ForegroundColorSpan(whiteColor)); + if (blueTeam != null && redTeam != null) { + text.append(String.format(Locale.getDefault(), "PK值 %s : %s \n", + FormatUtils.formatToShortHalfUp(redTeam.getScore()), + FormatUtils.formatToShortHalfUp(blueTeam.getScore())), + new ForegroundColorSpan(whiteColor)); + + UserInfo redProtector = redTeam.getProtector(); + if (redProtector == null) { + break; + } + text.append(String.format(Locale.getDefault(), "红队守护者:%s \n", redProtector.getNick()), + new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), "红队守护值:%s \n", + FormatUtils.formatToShortHalfUp(redTeam.getProtecScore())), + new ForegroundColorSpan(whiteColor)); + } + break; + } + textView.setText(text.build()); + } + + private void startQueuingMicModeMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员", new ForegroundColorSpan(whiteColor)) + .append("开启了", new ForegroundColorSpan(greyColor)) + .append("排麦模式", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void stopQueuingMicModeMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员", new ForegroundColorSpan(whiteColor)) + .append("关闭了", new ForegroundColorSpan(greyColor)) + .append("排麦模式", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void switchToFreeMicMsg(TextView tvContent, ChatRoomMessage chatRoomMessage) { + QueuingMicAttachment attachment = (QueuingMicAttachment) chatRoomMessage.getAttachment(); + QueuingMicInfo queuingMicInfo = attachment.getQueuingMicInfo(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员设置", new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), " %d 麦", + JavaUtil.str2int(queuingMicInfo.getMicPos()) + 1), new ForegroundColorSpan(greyColor)) + .append("为自由麦", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void switchToLockMicMsg(TextView tvContent, ChatRoomMessage chatRoomMessage) { + QueuingMicAttachment attachment = (QueuingMicAttachment) chatRoomMessage.getAttachment(); + QueuingMicInfo queuingMicInfo = attachment.getQueuingMicInfo(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员关闭", new ForegroundColorSpan(whiteColor)) + .append(String.format(Locale.getDefault(), " %d 麦", + JavaUtil.str2int(queuingMicInfo.getMicPos()) + 1), new ForegroundColorSpan(greyColor)) + .append("自由麦", new ForegroundColorSpan(whiteColor)); + tvContent.setText(text.build()); + } + + private void setDragonBarRunawayMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(extension == null ? "我" : RegexUtil.getPrintableString(extension.getSenderNick()), new ForegroundColorSpan(Color.WHITE), + new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 之前在本房间由于不明原因退出交友匹配,此次匹配展示为上次数据", new ForegroundColorSpan(roomTipColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void setDragonBarCancelMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(extension == null ? "我" : RegexUtil.getPrintableString(extension.getSenderNick()), new ForegroundColorSpan(Color.WHITE), + new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 放弃本次匹配", new ForegroundColorSpan(roomTipColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void setDragonBarMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + try { + ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension(); + + FaceAttachment attachment = (FaceAttachment) chatRoomMessage.getAttachment(); + FaceReceiveInfo faceReceiveInfo = attachment.getFaceReceiveInfos().get(0); + FaceInfo faceInfoById = DynamicFaceModel.get().findFaceInfoById(faceReceiveInfo.getFaceId()); + String msg = ""; + for (Integer integer : faceReceiveInfo.getResultIndexes()) { + msg = msg + (integer + 1 - faceInfoById.getResultIndexStart()) + ","; + } + msg = msg.substring(0, msg.length() - 1); + // 内容 + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(extension == null ? "我" : RegexUtil.getPrintableString(extension.getSenderNick()), new ForegroundColorSpan(Color.WHITE), + new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 爱心值为 " + msg, new ForegroundColorSpan(roomTipColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } catch (Exception e) { + } + } + + private void setBoxMeMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + RoomBoxPrizeAttachment attachment = (RoomBoxPrizeAttachment) chatRoomMessage.getAttachment(); + // 内容 + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("厉害了 ", new ForegroundColorSpan(greyColor)) + .append(attachment.getNick() + " ", new ForegroundColorSpan(roomTipColor)) + .append(attachment.getBoxTypeStr()+" ", new ForegroundColorSpan(greyColor)) + .append(attachment.getPrizeName(), new ForegroundColorSpan(Color.WHITE)); + if (attachment.getPrizeNum() > 1) { + text.append(" x" + attachment.getPrizeNum() + " ", new ForegroundColorSpan(roomTipColor)); + } + tvContent.setText(text.build()); + } + + private void setUpdateAudioMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append("管理员开启高音质模式 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setUpdateGiftEffectMsg(TextView tvContent) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append("管理员已关闭房间内礼物特效,点击底部“更多”图标即可开启", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setUpdateScreenMsg(TextView tvContent, String contentText) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append(contentText, new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setUpdateRoomPureModeMsg(TextView tvContent, IMMessage message) { + RoomNoticeAttachment attachment = (RoomNoticeAttachment) message.getAttachment(); + RoomMessageViewNoticeInfo messageViewNoticeInfo = attachment.getRoomMessageViewNoticeInfo(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append(messageViewNoticeInfo.getTips(), new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setMonsterNotifyMessage(TextView tvContent, String notifyMessage) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(notifyMessage, new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.color_34D08B))); + tvContent.setText(text.build()); + } + + /** + * 排麦模式中,用户被管理员抱上麦 + * 格式:管理员/房主将{用户昵称}抱上麦 + * + * @param tvContent + * @param attachment + */ + private void setInviteUpMicMsg(TextView tvContent, RoomQueueMsgAttachment attachment) { + String targetNick = RegexUtil.getPrintableString(attachment.targetNick); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("管理员将 ", new ForegroundColorSpan(greyColor)) + .append(targetNick, new ForegroundColorSpan(roomTipColor)) + .append(" 抱上麦 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + private void setKickMsg(TextView tvContent, RoomQueueMsgAttachment attachment) { + String nick = RegexUtil.getPrintableString(attachment.handleNick); + String targetNick = RegexUtil.getPrintableString(attachment.targetNick); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(targetNick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(attachment.uid).subscribe(clickConsumer); + } + } + }) + .append(" 被 ", new ForegroundColorSpan(greyColor)) + .append(nick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(attachment.handleUid + "").subscribe(clickConsumer); + } + } + }) + .append(" 请下麦 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void setKickRoomMsg(TextView tvContent, RoomQueueMsgAttachment attachment) { + String nick = RegexUtil.getPrintableString(attachment.handleNick); + String targetNick = RegexUtil.getPrintableString(attachment.targetNick); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(targetNick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(attachment.uid).subscribe(clickConsumer); + } + } + }) + .append(" 被 ", new ForegroundColorSpan(greyColor)) + .append(nick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(attachment.handleUid + "").subscribe(clickConsumer); + } + } + }) + .append(" 请出房间 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void setAddBlackMsg(TextView tvContent, RoomQueueMsgAttachment attachment) { + String nick = RegexUtil.getPrintableString(attachment.handleNick); + String targetNick = RegexUtil.getPrintableString(attachment.targetNick); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(targetNick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null && !TextUtils.isEmpty(attachment.uid)) { + Single.just(attachment.uid).subscribe(clickConsumer); + } + } + }) + .append(" 被 ", new ForegroundColorSpan(greyColor)) + .append(nick, new ForegroundColorSpan(roomTipColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null && !TextUtils.isEmpty(attachment.uid)) { + Single.just(attachment.handleUid + "").subscribe(clickConsumer); + } + } + }) + .append(" 关进小黑屋 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + private void clearBackground(TextView textView) { + // 清除文字 + textView.setText(""); + // 清除聊天气泡 + textView.setBackgroundResource(R.drawable.shape_room_message_bg); + textView.setPadding(paddingWidth, paddingHeight, paddingWidth, paddingHeight); + } + + /** + * {badge}{level}xxx: 文字内容 + * + * @param chatRoomMessage - + * @param tvContent - + */ + private void setMsgText(ChatRoomMessage chatRoomMessage, TextView tvContent) { + ChatRoomMessageExtension extension = chatRoomMessage.getChatRoomMessageExtension(); + String userBadge = NobleUtil.getResource(NobleResourceType.KEY_BADGE, chatRoomMessage); + String userLevel = NobleUtil.getLevel(UserLevelResourceType.EXPER_URL, chatRoomMessage); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + boolean isOfficial = NobleUtil.getIsOfficial(UserInfo.IS_OFFICIAL, chatRoomMessage); + // LogUtil.e("mylog","是否新用户"+newUser); + // 内容 + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(isOfficial ? ResourcesCompat.getDrawable(getResources(), + R.mipmap.ic_user_official_13dp, null) : null, + badgeWidth, badgeHeight) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(NobleUtil.getLocalResourcePath(userBadge), badgeWidth, badgeHeight) + .append(userLevel, expLevelWidth, expLevelHeight) + .append(extension == null ? "我" : RegexUtil.getPrintableString(extension.getSenderNick()), new ForegroundColorSpan(greyColor)) + .append(":" + chatRoomMessage.getContent(), new ForegroundColorSpan(getResources().getColor(R.color.white))); + tvContent.setText(text.build()); + } + + /** + * 暂时已抛弃 + * + * @param chatRoomMessage - + * @param tvContent - + * @param attachment - + */ + private void setMsgAuction(ChatRoomMessage chatRoomMessage, TextView tvContent, CustomAttachment attachment) { + String senderNick = chatRoomMessage.getChatRoomMessageExtension().getSenderNick(); + senderNick = senderNick == null ? "" : senderNick; + AuctionAttachment auctionAttachment = (AuctionAttachment) attachment; + SpannableBuilder builder = new SpannableBuilder(tvContent); + if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_TYPE_AUCTION_START) { + builder.append("房主 开启了竞拍", new ForegroundColorSpan(roomTipNickColor)); + } else if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_TYPE_AUCTION_FINISH) { + if (auctionAttachment.getAuctionInfo().getCurMaxUid() > 0) { + senderNick = UserInfoHelper.getUserDisplayName(auctionAttachment.getAuctionInfo().getCurMaxUid() + ""); + String voiceActorNick = UserInfoHelper.getUserDisplayName(auctionAttachment.getAuctionInfo().getAuctUid() + ""); + builder.append(senderNick, new ForegroundColorSpan(roomTipNickColor)) + .append(" 以" + auctionAttachment.getAuctionInfo().getRivals().get(0).getAuctMoney() + "金币拍下 ") + .append(voiceActorNick, new ForegroundColorSpan(roomTipNickColor)); + } else + builder.append("房主 结束了竞拍,当前暂无人出价", new ForegroundColorSpan(roomTipNickColor)); + } else { + builder.append(senderNick, new ForegroundColorSpan(roomTipNickColor)) + .append(" 出价" + auctionAttachment.getAuctionInfo().getRivals().get(0).getAuctMoney() + "金币"); + } + tvContent.setText(builder.build()); + } + + /** + * xxx 分享了房间 + * xxx 关注了房主 + * + * @param tvContent - + * @param roomTipAttachment - + */ + private void setMsgRoomTip(TextView tvContent, RoomTipAttachment roomTipAttachment, ChatRoomMessage chatRoomMessage) { + if (TextUtils.isEmpty(roomTipAttachment.getNick())) roomTipAttachment.setNick(""); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(RegexUtil.getPrintableString(roomTipAttachment.getNick()), new ForegroundColorSpan(roomTipColor)) + .append(roomTipAttachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_TYPE_ROOM_TIP_SHARE_ROOM ? + " 分享了房间" : " 关注了房主", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + /** + * {badge}{level} xxx 出 运气表情 + *

+ * {badge}{level} xxx 出 + * 表情1 表情2 表情3 表情4 表情5 + * + * @param faceAttachment - + * @param chatRoomMessage - + */ + private void setMsgFace(TextView tvContent, FaceAttachment faceAttachment, ChatRoomMessage chatRoomMessage) { + SpannableBuilder builder = new SpannableBuilder(tvContent); + List faceReceiveInfos = faceAttachment.getFaceReceiveInfos(); + FaceReceiveInfo faceReceiveInfo; + FaceInfo faceInfo; + String logNick = null; + for (int i = 0; i < faceReceiveInfos.size(); i++) { + faceReceiveInfo = faceReceiveInfos.get(i); + faceInfo = DynamicFaceModel.get().findFaceInfoById(faceReceiveInfo.getFaceId()); + if (faceReceiveInfo.getResultIndexes() == null || + faceReceiveInfo.getResultIndexes().size() <= 0 || faceInfo == null) + continue; + String nick = RegexUtil.getPrintableString(faceReceiveInfo.getNick()); + logNick = nick; + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + builder.append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(greyColor)) + .append(": " + (faceReceiveInfo.getResultIndexes().size() > 1 ? "\n" : ""), new ForegroundColorSpan(greyColor)); + List resultIndexes = faceReceiveInfo.getResultIndexes(); + int width = bigFace, height = bigFace; + for (Integer index : resultIndexes) { + // 骰子 + if (faceInfo.getId() == 17 || "shaizi".equals(faceInfo.getENName())) + height = (int) (width / 1.36F); + // 纸牌 + if (faceInfo.getId() == 24 || "pukepai".equals(faceInfo.getENName())) { + width = smallFace; + height = (int) (width / 0.7F); + } + builder.append(faceInfo.getFacePath(index), width, height); + } + builder.append(faceReceiveInfos.size() - 1 != i ? "\n" : ""); + } + tvContent.setText(builder.build()); + } + + /** + * xxx 全麦送出 {礼物} X数量 + * + * @param tvContent - + * @param giftAttachment - + * @param chatRoomMessage - + */ + private void setMsgMultiGift(TextView tvContent, MultiGiftAttachment giftAttachment, ChatRoomMessage chatRoomMessage) { + GiftInfo giftInfo = giftAttachment.getMultiGiftReceiveInfo().getGift(); + String nick = RegexUtil.getPrintableString(giftAttachment.getMultiGiftReceiveInfo().getNick()); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 全麦送出 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(giftInfo == null ? "" : giftInfo.getGiftUrl(), giftLength, giftLength) + .append("X" + giftAttachment.getMultiGiftReceiveInfo().getGiftNum(), new ForegroundColorSpan(getResources().getColor(R.color.white))); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * xxx 送给xxx,xxx,xxx... {礼物} X数量 + * + * @param tvContent + * @param attachment + * @param chatRoomMessage + */ + private void setMsgBatchGift(TextView tvContent, GiftBatchAttachment attachment, ChatRoomMessage chatRoomMessage) { + GiftInfo giftInfo = attachment.getGiftMultiReceiverInfo().getGift(); + String nick = RegexUtil.getPrintableString(attachment.getGiftMultiReceiverInfo().getNick()); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 送给 ", new ForegroundColorSpan(getResources().getColor(R.color.white))); + + for (GiftReceiver targetUser : attachment.getGiftMultiReceiverInfo().getTargetUsers()) { + text.append(targetUser.getNick(), new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(targetUser.getUid() + "").subscribe(clickConsumer); + } + } + }) + .append(","); + } + Editable msg = text.builder; + msg.delete(msg.length() - 1, msg.length()); + text.append(giftInfo == null ? "" : giftInfo.getGiftUrl(), giftLength, giftLength) + .append(" X" + attachment.getGiftMultiReceiverInfo().getGiftNum(), new ForegroundColorSpan(getResources().getColor(R.color.white))); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * {badge}xxx给全麦施魔法{魔法} + * + * @param tvContent - + * @param magicAllMicAttachment - + * @param chatRoomMessage - + */ + private void setAllMicMagicMsg(TextView tvContent, MagicAllMicAttachment magicAllMicAttachment, ChatRoomMessage chatRoomMessage) { + MultiMagicReceivedInfo multiMagicReceivedInfo = magicAllMicAttachment.getMultiMagicReceivedInfo(); + if (multiMagicReceivedInfo == null) return; + MagicInfo magicInfo = MagicModel.get().getMagicInfo(multiMagicReceivedInfo.getMagicId()); + String nick = RegexUtil.getPrintableString(multiMagicReceivedInfo.getNick()); + boolean showEffect = multiMagicReceivedInfo.isNeedShowExplode(); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, chatRoomMessage.getFromAccount()); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 全麦施魔法 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(magicInfo == null ? "" : TextUtils.isEmpty(magicInfo.getIcon()) ? "" : magicInfo.getIcon(), giftLength, giftLength) + .append(showEffect ? " 并 " : "", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(showEffect ? " 触发暴击 " : "", new ForegroundColorSpan(roomTipNickColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + + /** + * xxx 送给xxx,xxx,xxx... {魔法} X数量 + * + * @param tvContent - + * @param magicBatchAttachment - + * @param chatRoomMessage - + */ + private void setMsgBatchMagic(TextView tvContent, MagicBatchAttachment magicBatchAttachment, ChatRoomMessage chatRoomMessage) { + MagicMultiReceiverInfo magicMultiReceiverInfo = magicBatchAttachment.getMagicMultiReceiverInfo(); + if (magicMultiReceiverInfo == null) { + return; + } + MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicMultiReceiverInfo.getMagicId()); + String nick = RegexUtil.getPrintableString(magicMultiReceiverInfo.getNick()); + boolean showEffect = magicMultiReceiverInfo.isNeedShowExplode(); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, chatRoomMessage.getFromAccount()); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 给 ", new ForegroundColorSpan(getResources().getColor(R.color.white))); + + for (MagicReceiver targetUser : magicMultiReceiverInfo.getTargetUsers()) { + text.append(targetUser.getNick(), new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(targetUser.getUid() + "").subscribe(clickConsumer); + } + } + }) + .append(","); + } + Editable msg = text.builder; + msg.delete(msg.length() - 1, msg.length()); + + text.append(" 施魔法 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(magicInfo == null ? "" : TextUtils.isEmpty(magicInfo.getIcon()) ? "" : magicInfo.getIcon(), giftLength, giftLength) + .append(" X" + magicMultiReceiverInfo.getNumber(), new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(showEffect ? " 并 " : "", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(showEffect ? " 触发暴击 " : "", new ForegroundColorSpan(roomTipNickColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + + } + + /** + * {badge}xxx给{badge}xxx施魔法{魔法} + * + * @param tvContent - + * @param magicAttachment - + * @param chatRoomMessage - + */ + private void setSingleMagicMsg(TextView tvContent, MagicAttachment magicAttachment, ChatRoomMessage chatRoomMessage) { + MagicReceivedInfo magicReceivedInfo = magicAttachment.getMagicReceivedInfo(); + if (magicReceivedInfo == null) return; + MagicInfo magicInfo = MagicModel.get().getMagicInfo(magicReceivedInfo.getMagicId()); + boolean showEffect = magicReceivedInfo.isNeedShowExplodeEffect(); + String nick = RegexUtil.getPrintableString(magicReceivedInfo.getNick()); + String targetNick = RegexUtil.getPrintableString(magicReceivedInfo.getTargetNick()); + boolean sendNewUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, chatRoomMessage.getFromAccount()); + boolean receiverNewUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, String.valueOf(magicReceivedInfo.getTargetUid())); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(sendNewUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 给 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(receiverNewUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(targetNick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(magicReceivedInfo.getTargetUid() + "").subscribe(clickConsumer); + } + } + }) + .append(" 施魔法 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(magicInfo == null ? "" : TextUtils.isEmpty(magicInfo.getIcon()) ? "" : magicInfo.getIcon(), giftLength, giftLength) + .append(showEffect ? " 并 " : "", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(showEffect ? " 触发暴击 " : "", new ForegroundColorSpan(roomTipNickColor)); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * {badge}xxx送给{badge}xxx {礼物} X数量 + * + * @param tvContent - + * @param giftAttachment - + * @param chatRoomMessage - + */ + private void setMsgHeaderGift(TextView tvContent, GiftAttachment giftAttachment, ChatRoomMessage chatRoomMessage) { + GiftReceiveInfo giftReceiveInfo = giftAttachment.getGiftReceiveInfo(); + if (giftReceiveInfo == null) return; + String nick = RegexUtil.getPrintableString(giftReceiveInfo.getNick()); + String targetNick = RegexUtil.getPrintableString(giftReceiveInfo.getTargetNick()); + boolean sendNewUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, chatRoomMessage.getFromAccount()); + boolean receiverNewUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage, String.valueOf(giftReceiveInfo.getTargetUid())); + String num = "X" + giftReceiveInfo.getGiftNum(); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(sendNewUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(nick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(chatRoomMessage.getFromAccount()).subscribe(clickConsumer); + } + } + }) + .append(" 送给 ", new ForegroundColorSpan(getResources().getColor(R.color.white))) + .append(receiverNewUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + .append(targetNick, new ForegroundColorSpan(roomTipNickColor), new OriginalDrawStatusClickSpan() { + + @Override + public void onClick(@NonNull View widget) { + if (clickConsumer != null) { + Single.just(giftReceiveInfo.getTargetUid() + "").subscribe(clickConsumer); + } + } + }) + .append(giftReceiveInfo.getGift() == null ? "" : giftReceiveInfo.getGift().getGiftUrl(), giftLength, giftLength) + .append(num, new ForegroundColorSpan(getResources().getColor(R.color.white))); + tvContent.setText(text.build()); + tvContent.setOnClickListener(null); + tvContent.setMovementMethod(new LinkMovementMethod()); + } + + /** + * {badge}xxx来了 + * + * @param chatRoomMessage - + * @param tvContent - + */ + private void setMsgNotification(ChatRoomMessage chatRoomMessage, TextView tvContent) { + ChatRoomNotificationAttachment attachment = (ChatRoomNotificationAttachment) chatRoomMessage.getAttachment(); + String senderNick = ""; + List nicks = attachment.getTargetNicks(); + if (nicks != null && nicks.size() > 0) + senderNick = RegexUtil.getPrintableString(attachment.getTargetNicks().get(0)); + if (attachment.getType() != NotificationType.ChatRoomMemberIn) return; + // 勋章 + //String userBadge = NobleUtil.getResource(NobleResourceType.KEY_BADGE, chatRoomMessage); + //String userLevel = NobleUtil.getLevel(UserLevelResourceType.EXPER_URL, chatRoomMessage); + boolean newUser = NobleUtil.getIsNewUser(UserInfo.IS_NEW_USER, chatRoomMessage); + boolean isOfficial = NobleUtil.getIsOfficial(UserInfo.IS_OFFICIAL, chatRoomMessage); + // 座驾 + String carName = NobleUtil.getCarName(CarInfo.CAR_NAME, chatRoomMessage); + carName = TextUtils.isEmpty(carName) ? "" : "\"" + carName + "\""; + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(isOfficial ? ResourcesCompat.getDrawable(getResources(), + R.mipmap.ic_user_official_13dp, null) : null, + badgeWidth, badgeHeight) + .append(newUser ? Constants.NEW_USER_ICON : "", badgeWidth, badgeHeight) + //2018.12.24 @测试 陈陈琳,进房不显示贵族勋章 +// .append(NobleUtil.getLocalResourcePath(userBadge), badgeWidth, badgeHeight) +// .append(userLevel, expLevelWidth, expLevelHeight) + .append(senderNick, new ForegroundColorSpan(roomTipColor)) + .append(TextUtils.isEmpty(carName) ? "" : " 驾着 ", new ForegroundColorSpan(greyColor)) + .append(carName, new ForegroundColorSpan(roomTipColor)) + .append(" 进入了房间 ", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + /** + * 恭喜 xxx 在房间内 续费/开通 "皇帝" + * + * @param chatRoomMessage - + * @param tvContent - + */ + private void setMsgNobleOpenOrRenewText(ChatRoomMessage chatRoomMessage, TextView tvContent) { + NobleAttachment attachment = (NobleAttachment) chatRoomMessage.getAttachment(); + NobleInfo nobleInfo = attachment.nobleInfo; + if (nobleInfo == null) return; + int first = attachment.getFirst(); + if (first != CustomAttachment.CUSTOM_MESS_HEAD_NOBLE) return; + int second = attachment.getSecond(); + if (second != CustomAttachment.CUSTOM_MESS_SUB_OPENNOBLE + && second != CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE) + return; + String senderNick = RegexUtil.getPrintableString(attachment.nick); + // 系统通知icon + Drawable icNotification = mContext.getResources().getDrawable(R.drawable.ic_system_notification); + int width = (int) (icNotification.getIntrinsicWidth() / (icNotification.getIntrinsicHeight() + 0.F) * sysIconHeight); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(icNotification, width, sysIconHeight) + .append(" 恭喜 ", new ForegroundColorSpan(greyColor)) + .append(senderNick, new ForegroundColorSpan(roomTipColor)) + .append(" 在房间内" + (second == CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE ? "续费" : "开通") + "\"", new ForegroundColorSpan(greyColor)) + .append(nobleInfo.getName(), new ForegroundColorSpan(roomTipColor)) + .append("\""); + tvContent.setText(text.build()); + } + + private void setKtvMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + + MusicInfoAttachment attachment = (MusicInfoAttachment) chatRoomMessage.getAttachment(); + MusicInfo musicInfo = attachment.getMusicInfo(); + if (musicInfo == null) return; + String tip = ""; + int second = attachment.getSecond(); + switch (second) { + case CustomAttachment.CUSTOM_MSG_SUB_KTV_ADD: + tip = " 点了一首 "; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_DELETE: + tip = " 删除了 "; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_SWITCH: + tip = " 切掉了 "; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_TOP: + tip = " 置顶了 "; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_FINISH: + tip = " 演唱结束,呱唧呱唧"; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_OPEN: + tip = " 房主或管理员开启了KTV模式"; + break; + case CustomAttachment.CUSTOM_MSG_SUB_KTV_CLOSE: + tip = " 房主或管理员关闭了KTV模式"; + break; + } + + //开启和关闭ktv模式的消息 + if (second == CustomAttachment.CUSTOM_MSG_SUB_KTV_OPEN || second == CustomAttachment.CUSTOM_MSG_SUB_KTV_CLOSE) { + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("消息: ", new ForegroundColorSpan(roomTipColor)) + .append(tip, new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + return; + } + // 内容 + String nick = TextUtils.isEmpty(musicInfo.getOperationNick()) ? + musicInfo.getUserNick() : musicInfo.getOperationNick(); + nick = RegexUtil.getPrintableString(nick); + SpannableBuilder text = new SpannableBuilder(tvContent) + .append(nick, + new ForegroundColorSpan(roomTipNickColor)) + .append(tip, new ForegroundColorSpan(greyColor)); + if (attachment.getSecond() != CustomAttachment.CUSTOM_MSG_SUB_KTV_FINISH) {//结束的消息不需要拼接歌曲名 + text.append(musicInfo.getMusicName()); + } + tvContent.setText(text.build()); + } + + /** + * 瓜分金币的消息,二级和三级都有 + * + * @param chatRoomMessage + * @param tvContent + */ + private void setCarveUpGoldMsg(ChatRoomMessage chatRoomMessage, TextView tvContent) { + if (!(chatRoomMessage.getAttachment() instanceof CarveUpGoldAttachment)) { + return; + } + CarveUpGoldAttachment attachment = (CarveUpGoldAttachment) chatRoomMessage.getAttachment(); + // 内容 + SpannableBuilder text = new SpannableBuilder(tvContent) + .append("【签到瓜分百万】哇塞,恭喜 ", new ForegroundColorSpan(greyColor)) + .append(attachment.getNick() + " ", new ForegroundColorSpan(roomTipColor)) + .append("签到获得 ", new ForegroundColorSpan(greyColor)) + .append(attachment.getGoldNum() + "金币", new ForegroundColorSpan(roomTipColor)) + .append("!", new ForegroundColorSpan(greyColor)); + tvContent.setText(text.build()); + } + + @Override + public void onClick(View v) { + String account = ""; + ChatRoomMessage chatRoomMessage = (ChatRoomMessage) v.getTag(); + if (chatRoomMessage.getMsgType() != MsgTypeEnum.tip) { + if (chatRoomMessage.getMsgType() == MsgTypeEnum.text) { + account = chatRoomMessage.getFromAccount(); + } else if (chatRoomMessage.getMsgType() == MsgTypeEnum.notification) { + account = chatRoomMessage.getFromAccount(); + } else if (chatRoomMessage.getMsgType() == MsgTypeEnum.custom) { + CustomAttachment attachment = (CustomAttachment) chatRoomMessage.getAttachment(); + if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_ROOM_TIP) { + account = ((RoomTipAttachment) attachment).getUid() + ""; + } else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_QUEUE) { + long handleUid = ((RoomQueueMsgAttachment) attachment).handleUid; + if (handleUid > 0) { + account = ((RoomQueueMsgAttachment) attachment).handleUid + ""; + } else { + //ios没用handleUid,导致iOS发的自定义消息,拿不到uid + account = chatRoomMessage.getFromAccount(); + } + } else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_HEADER_TYPE_MONSTER_HUNTING) { + switch (attachment.getSecond()) { + case CustomAttachment.CUSTOM_MSG_SUB_TYPE_MONSTER_HUNTING: + MonsterProtocol.DataBean dataBean = ((MonsterStatusAttachment) attachment).getDataBean(); + RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (!Objects.equals(mCurrentRoomInfo.getUid(), dataBean.getAppearRoomUid())) { + AVRoomActivity.start(getContext(), dataBean.getAppearRoomUid()); + } else { + SingleToastUtil.showToast("你已经在怪兽房间内"); + } + break; + + case CustomAttachment.CUSTOM_NOTI_SUB_GAME_RESULT: + MonsterHuntingResult result = ((MonsterHuntingResultAttachment) attachment).getResult(); + UIHelper.showMonsterResult(getContext(), String.valueOf(result.getMonster().getMonsterId())); + break; + } + } else if (attachment.getFirst() == CustomAttachment.CUSTOM_MESS_HEAD_ROOM_PK) { + if (attachment.getSecond() == CustomAttachment.CUSTOM_MESS_SUB_ROOM_PK_RESULT) { + PKResultDialog pkResultDialog = new PKResultDialog(getContext(), ((RoomPkAttachment) attachment).getRoomPkData()); + pkResultDialog.show(); + } + } else if (attachment.getFirst() == CustomAttachment.CUSTOM_MSG_IM_GAME) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast("玮哥提醒你:上班不要玩游戏"); + return; + } + ImGameInfo imGameInfo = ((ImGameAttachment) attachment).getImGameInfo(); + if (chatRoomMessage.getFromAccount().equals(AuthModel.get().getCurrentUid() + "") + && ImGameMode.get().isValid(imGameInfo)) { + ImGameMode.get().sendRoomGameCancelMsg(chatRoomMessage); + changeGameStatus(chatRoomMessage.getUuid(), ImGameInfo.INVALID); + } else if (!chatRoomMessage.getFromAccount().equals(AuthModel.get().getCurrentUid() + "") + && imGameInfo.getAcceptUid() != AuthModel.get().getCurrentUid() + && ((imGameInfo.getStartTime() + ImGameMode.TIME * 1000 > System.currentTimeMillis() + && imGameInfo.getStatus() == ImGameInfo.TIMEING) || (imGameInfo.getStatus() == ImGameInfo.ACCEPTED))) { + if (onClickListener != null) { + onClickListener.onAcceptGame(chatRoomMessage, imGameInfo); + } + } else if (imGameInfo.getStatus() == ImGameInfo.TIMEING + && imGameInfo.getStartTime() + ImGameMode.TIME * 1000 < System.currentTimeMillis()) { + SingleToastUtil.showToast("此邀请已失效"); + changeGameStatus(chatRoomMessage.getUuid(), ImGameInfo.INVALID); + } + } + } + if (TextUtils.isEmpty(account)) return; + if (clickConsumer != null) { + Single.just(account).subscribe(clickConsumer); + } + } else { + String content = chatRoomMessage.getContent(); + if (!TextUtils.isEmpty(content) && content.equals(XChatConstants.ROOM_INTRODUCTION)) +// RxBus.get().post(new OpenRoomIntroEvent()); + if (onClick != null) { + onClick.onShowRoomIntroduction(); + } + } + } + } + + + public static class SpannableBuilder { + private SpannableStringBuilder builder; + private TextView textView; + + public SpannableBuilder(TextView textView) { + builder = new SpannableStringBuilder(); + this.textView = textView; + } + + /** + * @param text 文字 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(CharSequence text) { + if (TextUtils.isEmpty(text)) return this; + builder.append(text); + return this; + } + + /** + * @param drawable -icon url + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder appendImg(String drawable) { + if (TextUtils.isEmpty(drawable)) return this; + int start = builder.length(); + builder.append("-"); + CustomImageSpan imageSpan = new CustomImageSpan(new ColorDrawable(Color.TRANSPARENT), textView, drawable); + builder.setSpan(imageSpan, start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return this; + } + + /** + * @param drawable -icon url + * @param width 宽 + * @param height 高 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(String drawable, int width, int height) { + if (TextUtils.isEmpty(drawable)) return this; + int start = builder.length(); + builder.append("-"); + CustomImageSpan imageSpan = new CustomImageSpan(new ColorDrawable(Color.TRANSPARENT), textView, drawable, width, height); + builder.setSpan(imageSpan, start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return this; + } + + /** + * @param drawable -icon + * @param width 宽 + * @param height 高 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(Drawable drawable, int width, int height) { + if (drawable == null) return this; + drawable.setBounds(0, 0, width, height); + int start = builder.length(); + builder.append("-"); + builder.setSpan(new CustomImageSpan(drawable), start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return this; + } + + /** + * @param text -文字 + * @param what -span类型 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(CharSequence text, Object what) { + if (TextUtils.isEmpty(text)) return this; + int start = builder.length(); + builder.append(text); + builder.setSpan(what, start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return this; + } + + /** + * 支持多个spannable 对同一段文字修改 + * + * @param text + * @param what + * @return + */ + public SpannableBuilder append(CharSequence text, Object... what) { + if (TextUtils.isEmpty(text)) return this; + int start = builder.length(); + builder.append(text); + for (int i = 0; i < what.length; i++) { + Object o = what[i]; + if (o == null) { + continue; + } + builder.setSpan(what[i], start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + return this; + } + + public SpannableStringBuilder build() { + return builder; + } + } + + public void clear() { + if (mMessageAdapter != null) { + chatRoomMessages.clear(); + mMessageAdapter.notifyDataSetChanged(); + } + if (tvBottomTip != null) { + needAutoScroll = true; + tvBottomTip.setVisibility(GONE); + } + } + + /** + * 处理接收游戏的通知 + * + * @param imGameInfo + */ + public void receiveCustomNotification(ImGameInfo imGameInfo) { + + if (imGameInfo.getStartUid() == AuthModel.get().getCurrentUid()) { + GameRespondAttachment attachment = new GameRespondAttachment(CustomAttachment.CUSTOM_MSG_GAME_RESPOND, CustomAttachment.CUSTOM_MSG_GAME_RESPOND_ACCEPT); + attachment.setImGameInfo(imGameInfo); + ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomCustomMessage( + // 聊天室id + AvRoomDataManager.get().getRoomId() + "", + attachment + ); + addMessages(message); + + PlayGameActivity.start(getContext(), imGameInfo.getGameUrl(), imGameInfo.getUuId()); + changeGameStatus(imGameInfo.getUuId(), imGameInfo.getStatus()); + } else { + changeGameStatus(imGameInfo.getUuId(), imGameInfo.getStatus()); + } + } + + /** + * 处理游戏取消的通知 + */ + private void updateGameItemStatus(String fromAccount) { + int size = chatRoomMessages.size(); + for (int i = size - 1; i >= (size > 100 ? size - 100 : 0); i--) { + ChatRoomMessage roomMessage = chatRoomMessages.get(i); + if (roomMessage.getAttachment() instanceof ImGameAttachment + && fromAccount.equals(roomMessage.getFromAccount())) { + ImGameInfo imGameInfo = ((ImGameAttachment) roomMessage.getAttachment()).getImGameInfo(); + imGameInfo.setStatus(ImGameInfo.INVALID); + ImGameAttachment attachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + attachment.setImGameInfo(imGameInfo); + + roomMessage.setAttachment(attachment); + + mMessageAdapter.notifyItemChanged(i); + } + } + } + + public void changeGameStatus(String uuid, int status) { + int size = chatRoomMessages.size(); + for (int i = size - 1; i >= 0; i--) { + if (chatRoomMessages.get(i).getUuid().equals(uuid)) { + ImGameAttachment attachment = (ImGameAttachment) chatRoomMessages.get(i).getAttachment(); + // chatRoomMessages.get(i).setFromAccount(AuthModel.get().getCurrentUid() + ""); + attachment.getImGameInfo().setStatus(status); + mMessageAdapter.notifyItemChanged(i); + break; + } + } + } + + public void setNeedAutoScroll(boolean needAutoScroll) { + this.needAutoScroll = needAutoScroll; + } + + public interface OnAcceptClick { + public void onAcceptGame(ChatRoomMessage chatRoomMessage, ImGameInfo imGameInfo); + + } + + public interface OnClick { + /** + * 点击关注 + * + * @param position + */ + void onFollowClick(int position); + + void onJoinMiniWorldClick(int position); + + /** + * 公屏查看公告 + */ + void onShowRoomIntroduction(); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java new file mode 100644 index 000000000..2440b4223 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java @@ -0,0 +1,489 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Point; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.BaseMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.CpMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.KtvMicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.MicroViewAdapter; +import com.yizhuan.erban.avroom.adapter.OnMicroItemClickListener; +import com.yizhuan.erban.avroom.ktv.KtvView; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.LayoutMicroViewBinding; +import com.yizhuan.erban.ui.anim.AnimFactory; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.manager.RtcEngineManager; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.event.ReceiveFaceEvent; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +import io.reactivex.disposables.Disposable; + +/** + * 上麦布局界面 + * + * @author xiaoyu + * @date 2017/12/20 + */ +public class MicroView extends RelativeLayout { + private static final String TAG = "MicroView"; + public RecyclerView recyclerView; + private SparseArray faceImageViews; + private SparseArray dragonBarImageViews; + + private int[] realPositions = {1, 5, 2, 6, 0, 3, 7, 4, 8}; + + private Context mContext; + private int giftWidth; + private int giftHeight; + + private Disposable subscribe; + + private KtvView ktvView; + private LayoutMicroViewBinding mBinding; + /**状态栏高度*/ + private int statusBarHeight = 0; + + public MicroView(Context context) { + this(context, null); + } + + public MicroView(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public MicroView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(context); + } + + private OnMicroItemClickListener onMicroItemClickListener; + + public void setOnMicroItemClickListener(OnMicroItemClickListener onMicroItemClickListener) { + this.onMicroItemClickListener = onMicroItemClickListener; + if (recyclerView != null && recyclerView.getAdapter() instanceof BaseMicroViewAdapter) { + ((BaseMicroViewAdapter) recyclerView.getAdapter()).setOnMicroItemClickListener(onMicroItemClickListener); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + EventBus.getDefault().register(this); + subMsg(); + /*mDisposable.add(CoreManager.getCore(IFaceCore.class).getChatRoomMsgFlowable() + .subscribe(this::onReceiveFace));*/ + } + + private void subMsg() { + subscribe = IMNetEaseManager.get() + .getChatRoomEventObservable().subscribe( + roomEvent -> onReceiveRoomEvent(roomEvent), + throwable -> subMsg()); + } + + @Override + protected void onDetachedFromWindow() { + EventBus.getDefault().unregister(this); + if (subscribe != null) { + subscribe.dispose(); + subscribe = null; + } + super.onDetachedFromWindow(); + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + if (roomEvent == null || roomEvent.getEvent() == RoomEvent.NONE) return; + switch (roomEvent.getEvent()) { + case RoomEvent.SPEAK_STATE_CHANGE: + onSpeakQueueUpdate(roomEvent.getMicPositionList()); + break; + case RoomEvent.DRAGON_BAR_START: + onDragonBarOpen((FaceAttachment) roomEvent.getChatRoomMessage().getAttachment(), true, false, false); + break; + case RoomEvent.DRAGON_BAR_SELF_START: + onDragonBarOpen((FaceAttachment) roomEvent.getChatRoomMessage().getAttachment(), true, true, false); + break; + case RoomEvent.DRAGON_BAR_END: + onDragonBarOpen((FaceAttachment) roomEvent.getChatRoomMessage().getAttachment(), false, true, true); + break; + case RoomEvent.DRAGON_BAR_CANCEL: + onDragonBarCancel((FaceAttachment) roomEvent.getChatRoomMessage().getAttachment()); + break; + default: + } + } + + private void onDragonBarCancel(FaceAttachment attachment) { + int position = AvRoomDataManager.get().getMicPosition(attachment.getUid()); + if (position < -1) return; + ImageView imageView = dragonBarImageViews.get(position); + if (imageView == null) return; + imageView.setImageDrawable(null); + imageView.clearAnimation(); + } + + private void onDragonBarOpen(FaceAttachment attachment, boolean needAnim, boolean needResult, boolean needGone) { + List faceReceiveInfos = attachment.getFaceReceiveInfos(); + if (faceReceiveInfos == null || faceReceiveInfos.size() <= 0) return; + faceAnima(faceReceiveInfos, true, needAnim, needResult, needGone); + } + + /** + * 根据位置获取想要的表情view的宽高 + */ + private int getFaceSize(int i) { + int dp; + if (isKtvMode) { + if (i == 4) {//ktv模式boss麦位置 + dp = 55; + } else { + dp = 45; + } + } else { + if (i == 0) {//普通模式boss麦位置 + dp = 65; + } else { + dp = 55; + } + } + //放大4/3倍 + return UIUtil.dip2px(mContext, dp * 4 / 3); + } + + public SparseArray setMicCenterPoint() { + SparseArray array = new SparseArray<>(9); + SparseArray centerPoints = new SparseArray<>(); + // 算出每一个麦位的位置 + int childCount = recyclerView.getChildCount(); + View child; + for (int i = 0; i < childCount; i++) { + child = recyclerView.getChildAt(i); + int position = getRealPosition(i); + int[] location = new int[2]; + // 找到头像 + View view = child.findViewById(R.id.micro_layout); + if (view != null) child = view; + child.getLocationInWindow(location); + int x = (location[0] + child.getWidth() / 2) - giftWidth / 2; + int y = (location[1] + child.getHeight() / 2) - giftHeight / 2; + //修复礼物落点偏下的问题,减去状态栏高度,沉浸式版本开始的bug + //原因:是因为这个位置计算出来是屏幕最开始0开始的 + //但是giftV2View的位置,是相对于状态栏高度开始的 + y = y - statusBarHeight; + // 放置表情占位image view + int faceSize = getFaceSize(i); + if (array.get(position - 1) == null) { + LayoutParams params = new LayoutParams(faceSize, faceSize); + child.getLocationInWindow(location); + int[] containerLocation = new int[2]; + this.getLocationInWindow(containerLocation); + params.leftMargin = ((location[0] - containerLocation[0] + child.getWidth() / 2) - faceSize / 2); + params.topMargin = ((location[1] - containerLocation[1] + child.getHeight() / 2) - faceSize / 2); + ImageView face = new ImageView(mContext); + face.setLayoutParams(params); + array.put(position - 1, face); + addView(face); + } + Point point = new Point(x, y); + centerPoints.put(position - 1, point); + } + AvRoomDataManager.get().mMicPointMap = centerPoints; + return array; + } + + public BaseMicroViewAdapter getAdapter() { + return (BaseMicroViewAdapter) recyclerView.getAdapter(); + } + + private void init(final Context context) { + this.mContext = context; + inflate(mContext, R.layout.layout_micro_view, this); + mBinding = DataBindingUtil.bind(findViewById(R.id.container)); + recyclerView = findViewById(R.id.recycler_view); + if (AvRoomDataManager.get().isCpRoom()) { + bindAdapter(new CpMicroViewAdapter(mContext)); + } else { + bindAdapter(new MicroViewAdapter(mContext)); + } + ktvView = findViewById(R.id.view_ktv); + ViewGroup.LayoutParams ktvParam = ktvView.getLayoutParams(); + ktvParam.height = (UIUtil.getScreenWidth(context) - UIUtil.dip2px(context, 24)) * 198 / 352; + +// recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { +// @Override +// public void onGlobalLayout() { +// recyclerView.postDelayed(() -> { +// dragonBarImageViews = setMicCenterPoint(); +// faceImageViews = setMicCenterPoint(); +// }, 500); +// recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); +// } +// }); +// +// MicroViewAdapter adapter = new MicroViewAdapter(mContext); +// adapter.bindToRecyclerView(recyclerView); + + giftWidth = UIUtil.dip2px(mContext, 80); + giftHeight = UIUtil.dip2px(mContext, 80); + + faceImageViews = new SparseArray<>(9); + dragonBarImageViews = new SparseArray<>(9); + + mBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); + + statusBarHeight = TitleBar.getStatusBarHeight(); + + } + + public void updateRoomInfo() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + + mBinding.setRoomInfo(roomInfo); + mBinding.setKtvModel(roomInfo.isOpenKTV); + + if (!TextUtils.isEmpty(roomInfo.getRoomDesc())) { + mBinding.tvRoomDesc.setText(RegexUtil.getPrintableString(roomInfo.getRoomDesc())); + } else { + if (AvRoomDataManager.get().isManager()) { + mBinding.tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_manager_edit_desc)); + } else { + mBinding.tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_no_desc)); + } + } + if (AvRoomDataManager.get().isManager()) { + mBinding.ivRoomCanEdit.setVisibility(VISIBLE); + } else { + mBinding.ivRoomCanEdit.setVisibility(GONE); + } + mBinding.tvRoomType.setText(roomInfo.getRoomTag()); + } + + public void onSpeakQueueUpdate(List positions) { + int count = recyclerView.getChildCount(); + for (int i = 0; i < positions.size(); i++) { + int pos = positions.get(i) + 1; + if (pos >= count) continue; + + View speakState = recyclerView.getChildAt(getWavePosition(pos)).findViewById(R.id.iv_halo); + if (speakState != null) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(positions.get(i)); + if (roomQueueInfo == null) continue; + String halo = (String) NobleUtil.getResource(NobleResourceType.KEY_HALO, roomQueueInfo.mChatRoomMember); + //光圈的起始位置应该是头像边界,终止位置是头饰边界,头像:头饰=3:4 + AnimFactory.getSpeakingAnimation(mContext, speakState.getWidth(), speakState.getHeight(), + NobleUtil.getColor(halo), speakState.getWidth() * 3 / 4) + .subscribe((animationDrawable, throwable) -> { + boolean isNeedSetBackground = false; + if (speakState.getBackground() != null) { + if (speakState.getBackground() instanceof AnimationDrawable) { + AnimationDrawable oldAnimationDrawable = (AnimationDrawable) speakState.getBackground(); + //因为设置了setOneShot属性,这里判断动画是否完成。 + if (oldAnimationDrawable.getCurrent() == + oldAnimationDrawable.getFrame(oldAnimationDrawable.getNumberOfFrames() - 1)) { + isNeedSetBackground = true; + } + } else { + isNeedSetBackground = true; + } + } else { + isNeedSetBackground = true; + } + if (isNeedSetBackground && animationDrawable != null) { + speakState.setBackground(animationDrawable); + animationDrawable.start(); + } + }); + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveFace(ReceiveFaceEvent event) { + List faceReceiveInfos = event.getFaceReceiveInfos(); + if (faceReceiveInfos == null || faceReceiveInfos.size() <= 0) return; + faceAnima(faceReceiveInfos, false, true, true, true); + } + + public void release() { + // 移除麦上的所有成员还有说话的光晕 + for (int i = 0; i < recyclerView.getChildCount(); i++) { + View child = recyclerView.getChildAt(i); + RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(child); + if (holder instanceof BaseMicroViewAdapter.NormalMicroViewHolder) { + ((BaseMicroViewAdapter.NormalMicroViewHolder) holder).clear(); + } + } + //key 是从[-1, 7],9个key + // 移除所有的表情动画 + for (int i = -1; i < faceImageViews.size() - 1; i++) { + ImageView imageView = faceImageViews.get(i); + if (imageView == null) continue; + imageView.setImageDrawable(null); + imageView.clearAnimation(); + } + // 移除龙珠的动画 + for (int i = -1; i < dragonBarImageViews.size() - 1; i++) { + ImageView imageView = dragonBarImageViews.get(i); + if (imageView == null) continue; + imageView.setImageDrawable(null); + imageView.clearAnimation(); + } + } + + //开始表情动画和龙珠动画 + private void faceAnima(List faceReceiveInfos, boolean isDragon, boolean needAnim, boolean needResult, boolean needGone) { + for (FaceReceiveInfo faceReceiveInfo : faceReceiveInfos) { + int position = AvRoomDataManager.get().getMicPosition(faceReceiveInfo.getUid()); + if (position < -1) continue; + ImageView imageView; + if (isDragon) { + imageView = dragonBarImageViews.get(position); + } else { + imageView = faceImageViews.get(position); + } + if (imageView == null) continue; + AnimFactory.getFaceAnimation(faceReceiveInfo, mContext, imageView.getWidth(), imageView.getHeight(), needAnim, needResult, needGone) + .subscribe((animationDrawable, throwable) -> { + if (animationDrawable != null) { + Drawable drawable = imageView.getDrawable(); + if (drawable != null && drawable instanceof AnimationDrawable) { + ((AnimationDrawable) drawable).stop(); + imageView.clearAnimation(); + } + imageView.setImageDrawable(animationDrawable); + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + animationDrawable.setOneShot(true); + animationDrawable.start(); + } + }); + } + } + + private boolean isKtvMode; + + public void openKtvMode() { + isKtvMode = true; + mBinding.setKtvModel(isKtvMode); + ktvView.setVisibility(VISIBLE); + //修复成员刚进房间,变ktv模式后,关闭按钮没出现的问题 + ktvView.updateCloseBtnNoSong(); + if (!AvRoomDataManager.get().isCpRoom()) { + bindAdapter(new KtvMicroViewAdapter(mContext)); + } else { + resetPoint(); + } + if (!RtcEngineManager.get().isOpenKtv()) { + RtcEngineManager.get().openKtvModel(); + } + } + + public void resetPoint() { + recyclerView.postDelayed(() -> { + removeFaceAndDragonView(faceImageViews); + removeFaceAndDragonView(dragonBarImageViews); + faceImageViews = setMicCenterPoint(); + dragonBarImageViews = setMicCenterPoint(); + }, 500); + } + + private void removeFaceAndDragonView(SparseArray array) { + if (array == null) { + return; + } + for (int i = 0; i < array.size(); i++) { + int key = array.keyAt(i); + ImageView view = array.get(key); + if (view == null) { + continue; + } + view.setImageDrawable(null); + view.clearAnimation(); + if (this == view.getParent()) { + removeView(view); + } + } + } + + public void bindAdapter(BaseMicroViewAdapter adapter) { + adapter.bindToRecyclerView(recyclerView); + adapter.setOnMicroItemClickListener(onMicroItemClickListener); + recyclerView.postDelayed(() -> { + removeFaceAndDragonView(faceImageViews); + removeFaceAndDragonView(dragonBarImageViews); + faceImageViews = setMicCenterPoint(); + dragonBarImageViews = setMicCenterPoint(); + }, 500); + } + + public void closeKtvMode() { + isKtvMode = false; + mBinding.setKtvModel(isKtvMode); + ktvView.setVisibility(GONE); + if (AvRoomDataManager.get().isCpRoom()) { + bindAdapter(new CpMicroViewAdapter(mContext)); + } else { + bindAdapter(new MicroViewAdapter(mContext)); + } + RtcEngineManager.get().closeKtvModel(); + } + + public void removeDragonBar(int micPosition) { + ImageView imageView = dragonBarImageViews.get(micPosition); + if (imageView == null) return; + imageView.setImageDrawable(null); + imageView.clearAnimation(); + } + + private int getRealPosition(int position) { + return isKtvMode && !AvRoomDataManager.get().isCpRoom() ? realPositions[position] : position; + } + + /** + * 根据坑位查找recyclerView的子View + * 如果是ktv模式的话,要额外处理 + * + * @param position 就是坑位(-1到7)的值+1 + * @return 坑位对应的recyclerView的子View + */ + private int getWavePosition(int position) { + if (isKtvMode && !AvRoomDataManager.get().isCpRoom()) { + for (int i = 0; i < realPositions.length; i++) { + if (position == realPositions[i]) { + return i; + } + } + } + return position; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/PKBoardView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/PKBoardView.java new file mode 100644 index 000000000..7180526ee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/PKBoardView.java @@ -0,0 +1,455 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.dialog.PKScoreBoardDialog; +import com.yizhuan.erban.avroom.dialog.PKSelectPeopleDialog; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.pk.bean.PKMemberInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPKInvitedUpMicMember; +import com.yizhuan.xchat_android_core.room.pk.bean.RoomPkData; +import com.yizhuan.xchat_android_core.room.pk.event.PKDataUpdateEvent; +import com.yizhuan.xchat_android_core.room.pk.event.PKTimeFinishEvent; +import com.yizhuan.xchat_android_core.room.pk.event.PKTimeTickEvent; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import io.reactivex.functions.BiConsumer; + +/** + * @author jack + * @Description + * @Date 2019/1/8 + */ +public class PKBoardView extends RelativeLayout implements View.OnClickListener { + + public PKBoardView(Context context) { + super(context); + init(); + } + + public PKBoardView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public PKBoardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private LinearLayout llPkScoreBoard; + private RelativeLayout rlRedTeamAddPeople; + private TextView tvRedTeamScore; + private RelativeLayout rlBlueTeamAddPeople; + private TextView tvBlueTeamScore; + private TextView tvPkTimer; + private CircleImageView civRedTeamMember1; + private CircleImageView civRedTeamMember2; + private CircleImageView civRedTeamMember3; + private CircleImageView civRedTeamMember4; + private CircleImageView ivAddRedTeamMember; + private CircleImageView civBlueTeamMember1; + private CircleImageView civBlueTeamMember2; + private CircleImageView civBlueTeamMember3; + private CircleImageView civBlueTeamMember4; + private CircleImageView ivAddBlueTeamMember; + + private List civRedAvatars = new ArrayList<>(); + private List civBlueAvatars = new ArrayList<>(); + + private void init() { + inflate(getContext(), R.layout.layout_pk_board_view, this); + + llPkScoreBoard = (LinearLayout) findViewById(R.id.ll_pk_score_board); + rlRedTeamAddPeople = (RelativeLayout) this.findViewById(R.id.rl_red_team_add_people); + tvRedTeamScore = (TextView) this.findViewById(R.id.tv_red_team_score); + rlBlueTeamAddPeople = (RelativeLayout) this.findViewById(R.id.rl_blue_team_add_people); + tvBlueTeamScore = (TextView) this.findViewById(R.id.tv_blue_team_score); + tvPkTimer = (TextView) this.findViewById(R.id.tv_pk_timer); + + + civRedTeamMember1 = (CircleImageView) findViewById(R.id.civ_red_team_member_1); + civRedTeamMember2 = (CircleImageView) findViewById(R.id.civ_red_team_member_2); + civRedTeamMember3 = (CircleImageView) findViewById(R.id.civ_red_team_member_3); + civRedTeamMember4 = (CircleImageView) findViewById(R.id.civ_red_team_member_4); + ivAddRedTeamMember = (CircleImageView) findViewById(R.id.iv_add_red_team_member); + civBlueTeamMember1 = (CircleImageView) findViewById(R.id.civ_blue_team_member_1); + civBlueTeamMember2 = (CircleImageView) findViewById(R.id.civ_blue_team_member_2); + civBlueTeamMember3 = (CircleImageView) findViewById(R.id.civ_blue_team_member_3); + civBlueTeamMember4 = (CircleImageView) findViewById(R.id.civ_blue_team_member_4); + ivAddBlueTeamMember = (CircleImageView) findViewById(R.id.iv_add_blue_team_member); + + civRedAvatars.add(civRedTeamMember1); + civRedAvatars.add(civRedTeamMember2); + civRedAvatars.add(civRedTeamMember3); + civRedAvatars.add(civRedTeamMember4); + + civBlueAvatars.add(civBlueTeamMember1); + civBlueAvatars.add(civBlueTeamMember2); + civBlueAvatars.add(civBlueTeamMember3); + civBlueAvatars.add(civBlueTeamMember4); + + updateView(); + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + EventBus.getDefault().register(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + } + + public void updateView() { + if (PkModel.get().isFighting()) { + long countDownTime = PkModel.get().getCurPkInfo().getCurPkTimeUntilEnd(); + tvPkTimer.setText(String.format(Locale.getDefault(), "%1$02d:%2$02d", countDownTime / 60, countDownTime % 60)); + + ivAddRedTeamMember.setVisibility(GONE); + ivAddBlueTeamMember.setVisibility(GONE); + + rlRedTeamAddPeople.setOnClickListener(null); + rlBlueTeamAddPeople.setOnClickListener(null); + tvPkTimer.setOnClickListener(null); + llPkScoreBoard.setOnClickListener(this); + showTeamAvatars(); + + PKTeamInfo blueTeamInfo = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_BLUE); + if (blueTeamInfo != null) { + tvBlueTeamScore.setText(FormatUtils.formatToShortHalfUp(blueTeamInfo.getScore())); + } + PKTeamInfo redTeamInfo = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_RED); + if (redTeamInfo != null) { + tvRedTeamScore.setText(FormatUtils.formatToShortHalfUp(redTeamInfo.getScore())); + } + } else { + + if (!isTeamHaveMember(PKTeamInfo.TEAM_RED)) { + ivAddRedTeamMember.setVisibility(VISIBLE); + } else { + ivAddRedTeamMember.setVisibility(GONE); + } + + if (!isTeamHaveMember(PKTeamInfo.TEAM_BLUE)) { + ivAddBlueTeamMember.setVisibility(VISIBLE); + } else { + ivAddBlueTeamMember.setVisibility(GONE); + } + + showTeamAvatars(); + rlRedTeamAddPeople.setOnClickListener(this); + rlBlueTeamAddPeople.setOnClickListener(this); + if (AvRoomDataManager.get().isManager()) { + tvPkTimer.setText("开始"); + tvPkTimer.setOnClickListener(this); + } else { + tvPkTimer.setText("未开始"); + tvPkTimer.setOnClickListener(null); + } + llPkScoreBoard.setOnClickListener(null); + + if (PkModel.get().getCurPkInfo() != null && PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_BEFORE_PK) { + tvBlueTeamScore.setText("0"); + tvRedTeamScore.setText("0"); + } + } + } + + private boolean isTeamHaveMember(int teamId) { + for (PKMemberInfo pkMemberInfo : PkModel.get().getPkMemberInfoList()) { + if (pkMemberInfo.getTeamId() == teamId) { + return true; + } + } + return false; + } + + public void showTeamAvatars() { + List pkMemberInfoList = PkModel.get().getPkMemberInfoList(); + for (CircleImageView civRedAvatar : civRedAvatars) { + civRedAvatar.setVisibility(GONE); + } + for (CircleImageView civBlueAvatar : civBlueAvatars) { + civBlueAvatar.setVisibility(GONE); + } + int redIndex = 0; + int blueIndex = 0; + for (int i = 0; i < pkMemberInfoList.size(); i++) { + PKMemberInfo pkMemberInfo = pkMemberInfoList.get(i); + if (pkMemberInfo.getTeamId() == PKTeamInfo.TEAM_RED) { + if (redIndex >= civRedAvatars.size()) { + break; + } + civRedAvatars.get(redIndex).setVisibility(VISIBLE); + GlideApp.with(this) + .load(pkMemberInfo.getUserInfo().getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(civRedAvatars.get(redIndex)); + redIndex++; + } else if (pkMemberInfoList.get(i).getTeamId() == PKTeamInfo.TEAM_BLUE) { + if (blueIndex >= civBlueAvatars.size()) { + break; + } + civBlueAvatars.get(blueIndex).setVisibility(VISIBLE); + GlideApp.with(this) + .load(pkMemberInfo.getUserInfo().getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(civBlueAvatars.get(blueIndex)); + blueIndex++; + } + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKTimeTickEvent(PKTimeTickEvent event) { + if (PkModel.get().getCurPkInfo() == null) { + return; + } + long countDownTime = PkModel.get().getCurPkInfo().getCurPkTimeUntilEnd(); + tvPkTimer.setText(String.format("%1$02d:%2$02d", countDownTime / 60, countDownTime % 60)); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKTimeFinishEvent(PKTimeFinishEvent event) { + updateView(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPKDataUpdateEvent(PKDataUpdateEvent event) { + if (PkModel.get().getCurPkInfo() == null) { + return; + } + if (PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_IN_PK) { + PKTeamInfo blueTeamInfo = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_BLUE); + if (blueTeamInfo != null) { + tvBlueTeamScore.setText(FormatUtils.formatToShortHalfUp(blueTeamInfo.getScore())); + } + PKTeamInfo redTeamInfo = PkModel.get().findTeamByTeamId(PKTeamInfo.TEAM_RED); + if (redTeamInfo != null) { + tvRedTeamScore.setText(FormatUtils.formatToShortHalfUp(redTeamInfo.getScore())); + } + } + if (PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_AFTER_PK) { + if (onActionListener != null) { + onActionListener.onEndPK(); + } + tvBlueTeamScore.setText("0"); + tvRedTeamScore.setText("0"); + } + if (PkModel.get().getCurPkInfo().getPkStatus() == RoomPkData.PK_STATUS_TERMINAL_PK_BEFORE_END) { + tvBlueTeamScore.setText("0"); + tvRedTeamScore.setText("0"); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.rl_red_team_add_people: + //不是管理员或者房主弹出排麦dialog + if (!AvRoomDataManager.get().isManager()) { + //已经排麦不操作 + if (!PkModel.get().getPkMemberInfoList().isEmpty() && AvRoomDataManager.get().myIsInQueue) { +// Toast.makeText(getContext(), "您已经在排麦了~", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("您已经在排麦了~"); + return; + } + if (onActionListener != null) { + onActionListener.onShowPKMicQueueDialog(); + } + + return; + } + //添加红队人员 + PKSelectPeopleDialog selectRedDialog = new PKSelectPeopleDialog(getContext(), PKTeamInfo.TEAM_RED, PkModel.get().getPkMemberInfoList()); + selectRedDialog.setOnSelectPeopleListener(new PKSelectPeopleDialog.OnSelectPeopleListener() { + @Override + public void onSelectPeople(List micEntityList) { + //更新队伍,麦序,显示头像 + List upMicMemberList = new ArrayList<>(); + for (PKSelectPeopleDialog.MicEntity micEntity : micEntityList) { + if (TextUtils.isEmpty(micEntity.uid)) { + continue; + } + RoomPKInvitedUpMicMember roomPKInvitedUpMicMember = new RoomPKInvitedUpMicMember(); + if (micEntity.isSelect) { + roomPKInvitedUpMicMember.setGroupType(PKTeamInfo.TEAM_RED); + } else { + if (TextUtils.isEmpty(micEntity.uid)) { + roomPKInvitedUpMicMember.setGroupType(PKTeamInfo.TEAM_NONE); + } else { + int teamId = PkModel.get().getTeamIdInPKMemberList(micEntity.uid); + roomPKInvitedUpMicMember.setGroupType( + teamId == PKTeamInfo.TEAM_RED ? PKTeamInfo.TEAM_NONE : teamId); + } + } + roomPKInvitedUpMicMember.setUid(micEntity.uid); + roomPKInvitedUpMicMember.setNick(micEntity.nick); + SparseArray micQueue = AvRoomDataManager.get().mMicQueueMemberMap; + //设置坑位的位置 + for (int i = 0; i < micQueue.size(); i++) { + int key = micQueue.keyAt(i); + RoomQueueInfo roomQueueInfo = micQueue.get(key); + if (roomQueueInfo.mChatRoomMember != null + && roomQueueInfo.mChatRoomMember.getAccount().equals(micEntity.uid)) { + roomPKInvitedUpMicMember.setPosition(key); + } + } + upMicMemberList.add(roomPKInvitedUpMicMember); + } + PkModel.get().inviteInTeam(upMicMemberList).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (throwable != null) { +// Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(throwable.getMessage()); + } + } + }); + + } + }); + selectRedDialog.show(); + break; + case R.id.rl_blue_team_add_people: + //不是管理员或者房主弹出排麦dialog + if (!AvRoomDataManager.get().isManager()) { + //已经排麦不操作 + if (!PkModel.get().getPkMemberInfoList().isEmpty() && AvRoomDataManager.get().myIsInQueue) { + return; + } + if (onActionListener != null) { + onActionListener.onShowPKMicQueueDialog(); + } + + return; + } + //添加蓝队人员 + PKSelectPeopleDialog selectBlueDialog = new PKSelectPeopleDialog(getContext(), PKTeamInfo.TEAM_BLUE, PkModel.get().getPkMemberInfoList()); + selectBlueDialog.setOnSelectPeopleListener(new PKSelectPeopleDialog.OnSelectPeopleListener() { + @Override + public void onSelectPeople(List micEntityList) { + //更新队伍,麦序,显示头像 + List upMicMemberList = new ArrayList<>(); + for (PKSelectPeopleDialog.MicEntity micEntity : micEntityList) { + if (TextUtils.isEmpty(micEntity.uid)) { + continue; + } + RoomPKInvitedUpMicMember roomPKInvitedUpMicMember = new RoomPKInvitedUpMicMember(); + if (micEntity.isSelect) { + roomPKInvitedUpMicMember.setGroupType(PKTeamInfo.TEAM_BLUE); + } else { + int teamId = PkModel.get().getTeamIdInPKMemberList(micEntity.uid); + roomPKInvitedUpMicMember.setGroupType( + teamId == PKTeamInfo.TEAM_BLUE ? PKTeamInfo.TEAM_NONE : teamId); + } + roomPKInvitedUpMicMember.setUid(micEntity.uid); + roomPKInvitedUpMicMember.setNick(micEntity.nick); + SparseArray micQueue = AvRoomDataManager.get().mMicQueueMemberMap; + //设置坑位的位置 + for (int i = 0; i < micQueue.size(); i++) { + int key = micQueue.keyAt(i); + RoomQueueInfo roomQueueInfo = micQueue.get(key); + if (roomQueueInfo.mChatRoomMember != null && + roomQueueInfo.mChatRoomMember.getAccount().equals(micEntity.uid)) { + roomPKInvitedUpMicMember.setPosition(key); + } + } + upMicMemberList.add(roomPKInvitedUpMicMember); + } + PkModel.get().inviteInTeam(upMicMemberList).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (throwable != null) { +// Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(throwable.getMessage()); + } + } + }); + } + }); + selectBlueDialog.show(); + break; + case R.id.tv_pk_timer: + // 开始PK 倒计时 + if (onActionListener != null) { + OnOperateStatusCallback callback = new OnOperateStatusCallback() { + @Override + public void onStart() { + tvPkTimer.setEnabled(false); + tvPkTimer.setTextColor(getContext().getResources().getColor(R.color.color_CCCCCC)); + } + + @Override + public void onFinish() { + tvPkTimer.setEnabled(true); + tvPkTimer.setTextColor(getContext().getResources().getColor(R.color.color_FC3D74)); + } + }; + onActionListener.onBeginPK(callback); + } + + break; + case R.id.ll_pk_score_board: + //pk中点击pk 面板 + if (PkModel.get().isFighting()) { + PKScoreBoardDialog pkScoreBoardDialog = new PKScoreBoardDialog(getContext()); + pkScoreBoardDialog.show(); + } + break; + } + } + + private OnActionListener onActionListener; + + public void setOnActionListener(OnActionListener onActionListener) { + this.onActionListener = onActionListener; + } + + public interface OnActionListener { + void onBeginPK(OnOperateStatusCallback callback); + + void onEndPK(); + + void onShowPKMicQueueDialog(); + } + + public interface OnOperateStatusCallback { + void onStart(); + + void onFinish(); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/RankNavigatorAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/RankNavigatorAdapter.java new file mode 100644 index 000000000..520593ee0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/RankNavigatorAdapter.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.ArrayList; +import java.util.List; + +/** + * 排行榜指示器定制 + * Created by lvzebiao on 2018/10/30. + */ + +public class RankNavigatorAdapter extends CommonNavigatorAdapter { + + private List mTitleList = new ArrayList<>(); + + public RankNavigatorAdapter() { + mTitleList.add("日榜"); + mTitleList.add("周榜"); +// mTitleList.add("总榜"); + } + + @Override + public int getCount() { + return mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.white_transparent_50)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.white)); + scaleTransitionPagerTitleView.setMinScale(1f); + scaleTransitionPagerTitleView.setTextSize(14); + scaleTransitionPagerTitleView.setText(mTitleList.get(index)); + + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(index); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(context, 3)); + indicator.setRoundRadius(UIUtil.dip2px(context, 1.5)); + indicator.setLineWidth(UIUtil.dip2px(context, 9)); + indicator.setColors(Color.parseColor("#FFFFFF")); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + //lp.bottomMargin = 0; + indicator.setLayoutParams(lp); + return indicator; + } + + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener mOnItemSelectListener) { + this.mOnItemSelectListener = mOnItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankNavigatorAdapter.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankNavigatorAdapter.java new file mode 100644 index 000000000..2e37d037e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankNavigatorAdapter.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.ArrayList; +import java.util.List; + +/** + * 排行榜指示器定制 + * Created by lvzebiao on 2018/10/30. + */ + +public class RoomRankNavigatorAdapter extends CommonNavigatorAdapter { + + private List mTitleList = new ArrayList<>(); + + public RoomRankNavigatorAdapter() { + mTitleList.add("贡献榜"); + mTitleList.add("魅力榜"); + } + + @Override + public int getCount() { + return mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int index) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.white_transparent_50)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_759EF0)); + scaleTransitionPagerTitleView.setMinScale(1f); + scaleTransitionPagerTitleView.setTextSize(14); + scaleTransitionPagerTitleView.setText(mTitleList.get(index)); + + scaleTransitionPagerTitleView.setOnClickListener(v -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(index); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT); + indicator.setLineHeight(UIUtil.dip2px(context, 30)); + indicator.setRoundRadius(UIUtil.dip2px(context, 15)); + indicator.setLineWidth(UIUtil.dip2px(context, 171)); + indicator.setYOffset(UIUtil.dip2px(context, 2)); + indicator.setXOffset(UIUtil.dip2px(context, 2)); + indicator.setColors(Color.parseColor("#FFFFFF")); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + indicator.setLayoutParams(lp); + return indicator; + } + + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener mOnItemSelectListener) { + this.mOnItemSelectListener = mOnItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankWrapViewPager.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankWrapViewPager.java new file mode 100644 index 000000000..32a6797bc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/RoomRankWrapViewPager.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; + +public class RoomRankWrapViewPager extends ViewPager { + private Context context; + private int minHeight; + + public RoomRankWrapViewPager(@NonNull Context context) { + super(context); + this.context = context; + minHeight = getMinHeight(); + } + + public RoomRankWrapViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + minHeight = getMinHeight(); + } + + private int getMinHeight() { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + if (windowManager != null) { + DisplayMetrics displayMetrics = new DisplayMetrics(); + windowManager.getDefaultDisplay().getMetrics(displayMetrics); + return displayMetrics.heightPixels / 3 * 2; + } else { + return 800; + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int height = 0; + // 遍历所有child的高度 + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); +// child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(minHeight, MeasureSpec.AT_MOST)); + int h = child.getMeasuredHeight(); + if (h < minHeight) { + h = minHeight; + } + if (h > height) { + height = h; // 采用最大的view的高度。 + } + } + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return false; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/ScaleTransformer.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/ScaleTransformer.java new file mode 100644 index 000000000..25112028c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/ScaleTransformer.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.avroom.widget; + +import android.view.View; + +/** + * Created by chensuilun on 2016/12/16. + */ +public class ScaleTransformer implements GalleryLayoutManager.ItemTransformer { + + private static final String TAG = "CurveTransformer"; + + + @Override + public void transformItem(GalleryLayoutManager layoutManager, View item, float fraction) { + item.setPivotX(item.getWidth() / 2.f); + item.setPivotY(item.getHeight() / 2.0f); + float scale = 1 - 0.32f * Math.abs(fraction); + float alpah = 1 - 0.5f * Math.abs(fraction); + item.setScaleX(scale); + item.setScaleY(scale); + item.setAlpha(alpah); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/ScrollSpeedLinearLayoutManger.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/ScrollSpeedLinearLayoutManger.java new file mode 100644 index 000000000..daab1bbe8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/ScrollSpeedLinearLayoutManger.java @@ -0,0 +1,52 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.graphics.PointF; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.LinearSmoothScroller; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.util.Log; + +/** + * @author chenran + * @date 2017/9/24 + */ + +public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager { + private float MILLISECONDS_PER_INCH = 0.2F; + private Context context; + private LinearSmoothScroller linearSmoothScroller; + private int lastPosition = -1; + + ScrollSpeedLinearLayoutManger(Context context) { + super(context); + this.context = context; + linearSmoothScroller = new LinearSmoothScroller(context) { + @Override + public PointF computeScrollVectorForPosition(int targetPosition) { + PointF pointF = ScrollSpeedLinearLayoutManger.this + .computeScrollVectorForPosition(targetPosition); + Log.e("Point", pointF.y + ""); + return pointF; + } + + @Override + protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { + //返回滑动一个pixel需要多少毫秒 + return MILLISECONDS_PER_INCH; + } + + }; + } + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + if (linearSmoothScroller.isRunning() && lastPosition != -1) { + scrollToPosition(lastPosition); + } + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + lastPosition = position; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/SliddingView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/SliddingView.java new file mode 100644 index 000000000..ab8412521 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/SliddingView.java @@ -0,0 +1,51 @@ +package com.yizhuan.erban.avroom.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + + +/** + * Created by huangmeng1 on 2018/1/18. + */ +public class SliddingView extends HorizontalScrollView { + private LinearLayout mLayout; + private View delete; + private int deletewidth; + private boolean once; + + public SliddingView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (!once) { + mLayout = (LinearLayout) getChildAt(0); + delete = mLayout.getChildAt(1); + deletewidth = delete.getLayoutParams().width = UIUtil.dip2px(getContext(), 63); + once = true; + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_UP: + int scollx=getScrollX(); + if (scollx>=deletewidth/2) { + smoothScrollTo(deletewidth, 0); + }else { + smoothScrollTo(0, 0); + } + return true; + } + return super.onTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/ViewItem.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/ViewItem.java new file mode 100644 index 000000000..b4a70d282 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/ViewItem.java @@ -0,0 +1,114 @@ +package com.yizhuan.erban.avroom.widget; + +import com.yizhuan.erban.R; + +/** + * 从library拿到client + * Created by lvzebiao on 2018/11/9. + */ + +public class ViewItem { + public static final int BUTTON_TYPE_NORMAL = 0; + public static final int BUTTON_TYPE_CANCEL = 1; + /**放置在资料卡片的底部位置的button*/ + public static final int BUTTON_TYPE_USER_CAR_BOTTOM = 2; + + + /** 发送礼物 */ + public static final int SEND_GIFT_ITEM = 0; + /** 锁坑 */ + public static final int SEND_LOCK_MIC_ITEM = 1; + /** 踢下麦 */ + public static final int SEND_KICKDOWN_MIC_ITEM = 2; + /** 踢出房间 */ + public static final int SEND_KICKOUT_ROOM_ITEM = 3; + /** 查看个人信息 */ + public static final int SEND_SHOW_USER_INCO_ITEM = 4; + /** 下麦 */ + public static final int SEND_DOWN_MIC_ITEM = 5; + /** 释放麦 */ + public static final int SEND_FREE_MIC_ITEM = 6; + /** 设置管理员 */ + public static final int SEND_MARK_MANAGER_ITEM = 7; + /** 取消管理员 */ + public static final int SEND_NOMARK_MANAGER_ITEM = 11; + /** 加入黑名单 */ + public static final int SEND_MARK_BLACK_ITEM = 8; + /** 开麦 */ + public static final int SEND_OPEN_MUTE_ITEM = 9; + /** + * 装扮 + */ + public static final int SEND_DECORATION_ITEM = 10; + /** 抱上麦 */ + public static final int SEND_INVITE_MIC_ITEM = 12; + /** 发起竞拍 */ + public static final int START_AUCTION = 13; + /**关注or取消*/ + public static final int ATTENT_ITEM = 15; + /**房间外送礼物*/ + public final static int SEND_GIFT_OUT_ROOM = 16; + /**房间内送礼物*/ + public final static int SEND_MAGIC_OUT_ROOM = 17; + + /**是否是关注按钮*/ + public boolean isAttent = false; + /**ture则的话,则显示在个人资料卡片底部*/ + public boolean isBottom = false; + /** + * 找到Ta + */ + public boolean isFindTa = false; + + public String mText; + public int resourceID; + public int imgRes; + public OnClickListener mClickListener; + public int mButtonType; + public int mTheme = -1; + public boolean noDissmis; + public ViewItem(String text, int imgRes, OnClickListener l) { + this(text, imgRes,BUTTON_TYPE_NORMAL, l); + } + public ViewItem(String text, int imgRes, boolean noDissmis, OnClickListener l) { + this(text, imgRes,BUTTON_TYPE_NORMAL, l); + this.noDissmis = noDissmis; + } + public ViewItem(String text, int imgRes, int buttonType, OnClickListener l) { + mText = text; + mClickListener = l; + mButtonType = buttonType; + this.imgRes = imgRes; + resourceID = R.layout.dialog_user_card_item; + } + + public ViewItem(String text, int imgRes, int buttonType, int theme, OnClickListener l) { + mText = text; + this.imgRes = imgRes; + mClickListener = l; + mButtonType = buttonType; + resourceID = R.layout.dialog_user_card_item; + mTheme = theme; + } + + /**用户卡片的底部item*/ + public ViewItem(String text, OnClickListener l) { + mText = text; + mClickListener = l; + mButtonType = BUTTON_TYPE_USER_CAR_BOTTOM; + resourceID = R.layout.item_room_user_dialog_bottom_button; + } + + public void setText(String text) { + this.mText = text; + } + + public void setClickListener(OnClickListener mClickListener) { + this.mClickListener = mClickListener; + } + + public interface OnClickListener { + void onClick(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java new file mode 100644 index 000000000..20264cbaf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseActivity.java @@ -0,0 +1,1105 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.model.BroadcastMessage; +import com.orhanobut.logger.Logger; +import com.readystatesoftware.systembartint.SystemBarTintManager; +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.MiddleActivity; +import com.yizhuan.erban.NimMiddleActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.common.LoadingFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.common.ReloadFragment; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.common.widget.StatusLayout; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.common.widget.dialog.DialogUiHelper; +import com.yizhuan.erban.common.widget.dialog.LoginPopupDialog; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.erban.ui.login.ErbanQQMemberBindAndLoginActivity; +import com.yizhuan.erban.ui.login.ForgetPswActivity; +import com.yizhuan.erban.ui.login.LoginActivity; +import com.yizhuan.erban.ui.login.RegisterActivity; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.DefaultToolBar; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleGlobalNoticeDialog; +import com.yizhuan.tutu.mentoring_relationship.dialog.GrabApprenticesNoticeDialog; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.bean.BaseProtocol; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.GrabApprenticesEvent; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleProtocol; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.ImeUtil; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.UIUtils; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; + +import static com.yizhuan.xchat_android_core.Constants.DEBUG_MAX_UID; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_HEAD_NOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_OPENNOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE; + + +/** + * @author alvin hwang + */ +public abstract class BaseActivity extends RxAppCompatActivity + implements IDataStatus, ConnectiveChangedReceiver.ConnectiveChangedListener, + DialogManagerInterface { + + private static final Object TAG = "BaseActivity"; + private Handler mHandler = new Handler(); + //底部登录弹窗 + private LoginPopupDialog mLoginDialog; + private DialogManager mDialogManager; + protected TitleBar mTitleBar; + protected DefaultToolBar mToolBar; + protected CompositeDisposable mCompositeDisposable; + private BroadcastObserver broadcastObserver; + protected Context context; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + context = this; + mCompositeDisposable = new CompositeDisposable(); + if (setBgColor() > 0) { + getWindow().setBackgroundDrawableResource(setBgColor()); + } + if (needSteepStateBar()) { + setStatusBar(); + } + registerNimBroadcastMessage(true); + } + + + /** + * 注册云信全服广播接收器 + * + * @param register true为注册,false为注销 + */ + protected void registerNimBroadcastMessage(boolean register) { + if (broadcastObserver == null) { + broadcastObserver = new BroadcastObserver(this); + } + NIMSDK.getMsgServiceObserve().observeBroadcastMessage(broadcastObserver, register); + } + + /** + * 当前Activity 是否有效 + */ + protected boolean isValid() { + return !isFinishing() && !isDestroyed(); + } + + public void initToolBar(int resId) { + initToolBar(getString(resId)); + } + + public void initToolBar(CharSequence title) { + mToolBar = (DefaultToolBar) findViewById(R.id.toolbar); + if (mToolBar != null) { + mToolBar.setCenterTitle(title); + mToolBar.setNavigationIcon(R.drawable.arrow_left); + mToolBar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onLeftClickListener(); + } + }); + } + } + + public void initTitleBar() { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && needSteepStateBar()) { + mTitleBar.setImmersive(true); + } + mTitleBar.setBackgroundColor(getResources().getColor(R.color.white)); + mTitleBar.setTitleColor(getResources().getColor(R.color.text_primary)); + } + } + + public void initTitleBar(int title) { + initTitleBar(getResources().getString(title)); + } + + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.mipmap.common_ic_back); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onLeftClickListener(); + } + }); + } + } + + public void initTitleBar(String title, boolean whiteModel) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor( + whiteModel ? R.color.white : R.color.back_font)); + mTitleBar.setLeftImageResource( + whiteModel ? R.mipmap.common_ic_back_white : R.mipmap.common_ic_back); + mTitleBar.setCommonBackgroundColor(getResources().getColor( + whiteModel ? R.color.transparent : R.color.white) + ); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onLeftClickListener(); + } + }); + } + } + + protected void onLeftClickListener() { + finish(); + } + + protected boolean needSteepStateBar() { + return false; + } + + public boolean blackStatusBar() { + return true; + } + + protected int setBgColor() { + return 0; + } + + /** + * 设置沉浸式状态栏 + */ + protected void setStatusBar() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //透明状态栏 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + //透明导航栏 +// getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + } + // create our manager instance after the content view is set + SystemBarTintManager tintManager = new SystemBarTintManager(this); + // enable status bar tint + tintManager.setStatusBarTintEnabled(true); + // enable navigation bar tint + tintManager.setNavigationBarTintEnabled(true); + tintManager.setTintColor(Color.parseColor("#00000000")); + } + + /** + * 通知栏白底黑字 + * + * @param isDark true:黑色 + */ + public void StatusBarLightModes(boolean isDark) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setStatusBarColor(getResources().getColor(R.color.white)); + } + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (isDark) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + } + } + } + + /** + * 获取状态栏的高度 + * + * @return + */ + protected int getStatusBarHeight() { + try { + Class c = Class.forName("com.android.internal.R$dimen"); + Object obj = c.newInstance(); + Field field = c.getField("status_bar_height"); + int x = Integer.parseInt(field.get(obj).toString()); + return getResources().getDimensionPixelSize(x); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + @Override + public void setContentView(int layoutResID) { + super.setContentView(layoutResID); + initTitleBar(); + } + + /** + * 是否需要渲染成主题色的status bar + * + * @return + */ + protected boolean shouldConfigStatusBar() { + return true; + } + + @Override + protected void onStart() { + super.onStart(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + @Override + protected void onDestroy() { + registerNimBroadcastMessage(false); + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + + if (mNoticeDialog != null && mNoticeDialog.isShowing()) { + mNoticeDialog.dismiss(); + mNoticeDialog = null; + } + + super.onDestroy(); + LogUtil.i(this.getClass().getName(), "onDestroy"); + + /* ImageLoadUtils.clearMemory(this);*/ + + if (XChatApplication.isDebug()) { + XChatApplication.getRefWatcher(this).watch(this); + } + } + @Override + public DialogManager getDialogManager() { + if (mDialogManager == null) { + mDialogManager = new DialogManager(this); + mDialogManager.setCanceledOnClickOutside(false); + } + return mDialogManager; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Fragment fragment = getTopFragment(); + if (fragment != null && fragment instanceof BaseFragment) { + if (((BaseFragment) fragment).onKeyDown(keyCode, event)) { + return true; + } + } + + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Fragment fragment = getTopFragment(); + if (fragment != null && fragment instanceof BaseFragment) { + fragment.onActivityResult(requestCode, resultCode, data); + } + super.onActivityResult(requestCode, resultCode, data); + } + + public Fragment getTopFragment() { + FragmentManager fragmentManager = getSupportFragmentManager(); + List fragments = fragmentManager.getFragments(); + if (fragments != null) { + for (Fragment fragment : fragments) { + if (fragment != null && fragment.isVisible()) { + return fragment; + } + } + } + return null; + } + + @Override + public void onBackPressed() { + hideIME(); + try { + super.onBackPressed(); + } catch (Exception ex) { + MLog.error(this, ex); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case android.R.id.home: + Fragment fragment = getTopFragment(); + if (fragment != null && fragment instanceof BaseFragment) { + if (fragment.onOptionsItemSelected(item)) { + return true; + } + } + onBackPressed(); + return true; + default: + break; + + } + + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { + if (menu.getClass().getSimpleName().equals("MenuBuilder")) { + try { + Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); + m.setAccessible(true); + m.invoke(menu, true); + } catch (Exception e) { + } + } + } + return super.onMenuOpened(featureId, menu); + } + + /** + * 获取backstack top + * + * @return + */ + private Fragment getLastFragment() { + List fragments = getSupportFragmentManager().getFragments(); + if (null != fragments && fragments.size() > 0) { + for (int i = fragments.size() - 1; i >= 0; i--) { + Fragment f = fragments.get(i); + if (f != null && f instanceof BaseFragment) { + return f; + } + } + } + + return null; + } + + /** + * @param fragmentName Fragment.class.getName() + */ + public void popFragment(String fragmentName) { + getSupportFragmentManager().popBackStack(fragmentName, FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + + public String getTopFragmentName() { + FragmentManager fragmentManager = getSupportFragmentManager(); + if (fragmentManager.getBackStackEntryCount() > 0) { + return fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); + } + return null; + } + + + protected void updateBottomBar(boolean isShow) { + + } + + @SuppressLint("CheckResult") + @Override + protected void onResume() { + super.onResume(); + //add connective changed broadcast receiver +// ConnectiveChangedReceiver.getInstance().registerConnectiveChange(this); + StatisticManager.Instance().onResume(this); + //GlideApp.with(this).resumeRequests(); + RxBus.get().toFlowable(String.class) + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .subscribe((s) -> { + if (XChatConstants.SHOW.equals(s)) { + getDialogManager().showProgressDialog(this, "请稍后...", true); + } else if (XChatConstants.HIDE.equals(s)) { + getDialogManager().dismissDialog(); + } + }, throwable -> { + }); + + RxBus.get() + .toFlowable(GrabApprenticesEvent.class) + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onGrabApprenticesEvent); + + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onRoomEventReceived); + + } + + @Override + protected void onPause() { + super.onPause(); + //remove connective changed broadcast receiver +// ConnectiveChangedReceiver.getInstance().unRegisterConnectiveChange(this); + StatisticManager.Instance().onPause(this); + //GlideApp.with(this).pauseRequests(); + } + + /** + * 网络连接变化 + */ + /** + * 网络连接变化 + */ + /** + * wifi 转 2G/3G/4G + */ + public void wifiChange2MobileData() { + + } + + /** + * 有网络变为无网络 + */ + public void change2NoConnection() { + if (isTopActive()) { + + } + } + + /** + * 连上wifi + */ + public void connectiveWifi() { + if (isTopActive()) { + + } + } + + /** + * 连上移动数据网络 + */ + public void connectiveMobileData() { + if (isTopActive()) { + + } + } + + /** + * 移动数据网络 改为连上wifi + */ + public void mobileDataChange2Wifi() { + + } + + protected boolean checkActivityValid() { + return UIUtils.checkActivityValid(this); + } + + /** + * 弹出登录框 + * + * @return + */ + public void showLoginDialog() { + ImeUtil.hideIME(this); + mLoginDialog.show(); + } + + /** + * -------------------------------------------------- + * -------------------------数据状态状态相关------------- + * -------------------------------------------------- + */ + + protected static final String STATUS_TAG = "STATUS_TAG"; + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + onReloadDate(); + } + }; + } + + /** + * 网络错误重新加载数据 + */ + public void onReloadDate() { + + } + + @Override + public View.OnClickListener getLoadMoreListener() { + return null; + } + + @Override + public View.OnClickListener getNoMobileLiveDataListener() { + return null; + } + + @Override + public void showLoading() { + showLoading(0, 0); + } + + @Override + public void showLoading(View view) { + showLoading(view, 0, 0); + } + + @Override + public void showReload() { + showReload(0, 0); + } + + @Override + public void showNoData() { + showNoData(0, ""); + } + + @Override + public void showNoLogin() { + + } + + @SuppressLint("ResourceType") + @Override + public void showLoading(int drawable, int tips) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + Fragment fragment = LoadingFragment.newInstance(drawable, tips); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + public void showCustomFragment(Fragment fragment) { + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showLoading(View view, int drawable, int tips) { + + } + + @SuppressLint("ResourceType") + @Override + public void showReload(int drawable, int tips) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + ReloadFragment fragment = ReloadFragment.newInstance(drawable, tips); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showReload(View view, int drawable, int tips) { + + } + + @Override + public void showNoData(CharSequence charSequence) { + showNoData(0, charSequence); + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(drawable, charSequence); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + + } + + @SuppressLint("ResourceType") + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = new NetworkErrorFragment(); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void hideStatus() { + Fragment fragment = getSupportFragmentManager().findFragmentByTag(STATUS_TAG); + if (fragment != null) { + getSupportFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss(); + } + } + + @Override + public void showPageError(int tips) { + if (!checkActivityValid()) { + return; + } + + View more = findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showErrorPage(tips, getLoadMoreListener()); + } + + @Override + public void showPageError(View view, int tips) { + + } + + @Override + public void showPageLoading() { + if (!checkActivityValid()) { + return; + } + + View more = findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showLoadMore(); + } + + /** + * 当前网络是否可用 + * + * @return + */ + public boolean isNetworkAvailable() { + return NetworkUtils.isNetworkStrictlyAvailable(this); + } + + public boolean checkNetToast() { + boolean flag = isNetworkAvailable(); + if (!flag) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), R.string.str_network_not_capable); + } + return flag; + } + + /** + * -------------------------------------------------- + * -------------------------UI基本功能------------------ + * -------------------------------------------------- + */ + public void hideIME() { + View v = getCurrentFocus(); + if (null != v) + hideIME(v); + } + + public void hideIME(View v) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + } + + public void showIME(final View vv) { + View v = vv; + if (null == v) { + v = getCurrentFocus(); + if (null == v) + return; + } + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) + .showSoftInput(v, InputMethodManager.SHOW_FORCED); + } + + /** + * 当前无Fragment 或 无Fragment添加 视为顶部激活状态 + * + * @return + */ + public boolean isTopActive() { + + if (isTopActivity()) { + FragmentManager fragmentManager = getSupportFragmentManager(); + + List fragments = fragmentManager.getFragments(); + if (fragments == null || fragments.size() == 0) { + return true; + } else { + int size = fragments.size(); + for (int i = 0; i < size; i++) { + //TODO why null? + if (fragments.get(i) != null && fragments.get(i).isAdded()) + return false; + } + return true; + } + } + return false; + } + + public boolean isTopActivity() { + return UIUtils.isTopActivity(this); + } + + /** + * 通用消息提示 + * + * @param resId + */ + public void toast(int resId) { + toast(resId, Toast.LENGTH_SHORT); + } + + public void toast(String toast) { + toast(toast, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param resId + * @param length + */ + public void toast(int resId, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), resId, length); + } + + public void toast(String toast, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), toast, length); + } + + + private void configStatusBar() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.setStatusBarColor(getResources().getColor(R.color.white)); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + + // create our manager instance after the content view is set + SystemBarTintManager tintManager = new SystemBarTintManager(this); + // enable status bar tint + tintManager.setStatusBarTintEnabled(true); + // enable navigation bar tint + tintManager.setNavigationBarTintEnabled(true); + + tintManager.setTintResource(R.color.white); + } + } + + + /** + * 权限回调接口 + */ + private PermissionActivity.CheckPermListener mListener; + + private RxPermissions rxPermissions = new RxPermissions(this); + + @SuppressLint("CheckResult") + public void checkPermission(PermissionActivity.CheckPermListener listener, int resString, String... mPerms) { + mListener = listener; + rxPermissions.request(mPerms) + .subscribe(aBoolean -> { + if (aBoolean && listener != null) { + listener.superPermission(); + } + }, Throwable::printStackTrace); + } + + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + /** + * 接收到全局广播信息 + * + * @param body 信息实体 + */ + protected void onReceivedNimBroadcastMessage(String body) { + if (!isNeedToHandleBroadcastMessageActivity()) { + return; + } + BaseProtocol baseProtocol; + try { + baseProtocol = JSON.parseObject(body, BaseProtocol.class); + } catch (Exception e) { + baseProtocol = null; + } + if (baseProtocol == null) return; + + switch (baseProtocol.getFirst()) { + case CUSTOM_MESS_HEAD_NOBLE: + int second = baseProtocol.getSecond(); + if (second == CUSTOM_MESS_SUB_OPENNOBLE || second == CUSTOM_MESS_SUB_RENEWNOBLE) { + NobleProtocol.DataBean data = JSON.parseObject(String.valueOf(baseProtocol.getData()), NobleProtocol.DataBean.class); + NobleInfo nobleInfo; + if (data == null || (nobleInfo = data.getNobleInfo()) == null || (data.getUid() < DEBUG_MAX_UID && !XChatApplication.isDebug())) + return; + + int type = data.getType(); + String nick = data.getNick(); + String content = null; + String noticeBefore = getString(R.string.global_notice_before); + if (type == 1) { + //恭喜 xxxx 开通“国王”贵族,速来膜拜 + if (TextUtils.isEmpty(data.getRoomTitle())) { + content = noticeBefore + getString(R.string.noble_open_notice, nick, nobleInfo.getName()); + } else { + content = noticeBefore + getString(R.string.noble_open_in_room_notice, nick, nobleInfo.getName(), + String.valueOf(data.getRoomErbanNo()), data.getRoomTitle()); + } + } else if (type == 2) { + //恭喜 xxxx 续费“国王”贵族 + content = noticeBefore + getString(R.string.noble_reopen_notice, nick, nobleInfo.getName()); + } + if (!TextUtils.isEmpty(content)) { + + String nobleName = nobleInfo.getName(); + Spannable spannable = new SpannableString(content); + + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, noticeBefore.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + int start = content.lastIndexOf(nick); + int end = start + nick.length(); + spannable.setSpan(new StyleSpan(Typeface.BOLD), start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + start = content.lastIndexOf(nobleName); + end = start + nobleName.length(); + spannable.setSpan(new StyleSpan(Typeface.BOLD), start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (!isFinishing()) { + if (mNoticeDialog != null && mNoticeDialog.isShowing()) + mNoticeDialog.dismiss(); + mNoticeDialog = new OpenNobleGlobalNoticeDialog(this, spannable); + mNoticeDialog.show(); + } + } + } + break; + default: + break; + } + } + + private OpenNobleGlobalNoticeDialog mNoticeDialog; + + private static class BroadcastObserver implements Observer { + private WeakReference mReference; + + BroadcastObserver(BaseActivity baseMvpActivity) { + mReference = new WeakReference<>(baseMvpActivity); + } + + @Override + public void onEvent(BroadcastMessage broadcastMessage) { + if (broadcastMessage != null) { + String contentStr = broadcastMessage.getContent(); + Logger.i("全局广播:" + contentStr); + if (TextUtils.isEmpty(contentStr)) return; + BaseActivity baseMvpActivity = mReference.get(); + if (baseMvpActivity == null) return; + if (baseMvpActivity.isValid()) { + JSONObject jsonObject; + try { + jsonObject = JSON.parseObject(contentStr); + } catch (Exception e) { + jsonObject = null; + } + if (jsonObject == null) return; + if (jsonObject.containsKey("body")) { + String body = jsonObject.getString("body"); + if (TextUtils.isEmpty(body)) return; + baseMvpActivity.onReceivedNimBroadcastMessage(body); + } + } + } + } + } + + protected volatile GrabApprenticesNoticeDialog dialog; + + public void onGrabApprenticesEvent(GrabApprenticesEvent event) { + if (!isTopActivity()) return; + if (dialog != null && dialog.isAdded()) { + dialog.dismiss(); + } + dialog = new GrabApprenticesNoticeDialog(); + dialog.show(getSupportFragmentManager()); + } + + public void onRoomEventReceived(RoomEvent roomEvent) { + switch (roomEvent.getEvent()) { + case RoomEvent.RECHARGE: + onNeedCharge(); + break; + + case RoomEvent.RADISH_NOT_ENOUGH: + DialogUiHelper.showRadishNotEnoughDialog(this, null); + break; + + case RoomEvent.GIFT_OUT_OF_DATE: + SingleToastUtil.showToast(roomEvent.getMessage()); + break; + } + } + + public String DESAndBase64(String psw) { + String pwd = ""; + try { + pwd = DESUtils.DESAndBase64Encrypt(psw); + } catch (Exception e) { + e.printStackTrace(); + } + return pwd; + } + + + /** + * 把不需要处理云信广播的activity 添加到这里。 + * + * @return + */ + private boolean isNeedToHandleBroadcastMessageActivity() { + List acts = new ArrayList<>(); + acts.add(LoginActivity.class); + acts.add(ForgetPswActivity.class); + acts.add(RegisterActivity.class); + acts.add(AddUserInfoActivity.class); + acts.add(MiddleActivity.class); + acts.add(NimMiddleActivity.class); + acts.add(ErbanQQMemberBindAndLoginActivity.class); + + + for (Class act : acts) { + if (this.getClass().isInstance(act)) { + return false; + } + } + return true; + } + + private boolean isShowingChargeDialog; + + private void onNeedCharge() { + if (isShowingChargeDialog) { + return; + } + isShowingChargeDialog = true; + new DialogManager(this).showOkCancelDialog(getString(R.string.tips_need_charge), + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + isShowingChargeDialog = false; + ChargeActivity.start(context); + } + + @Override + public void onCancel() { + isShowingChargeDialog = false; + } + }); + } + + public static void start(Context context, Class clazz) { + context.startActivity(new Intent(context, clazz)); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseBindingActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseBindingActivity.java new file mode 100644 index 000000000..e0a6de21c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseBindingActivity.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.base; + +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.databinding.ViewDataBinding; +import android.os.Bundle; +import android.view.View; + +import com.yizhuan.erban.BR; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +/** + * Created by huangmeng1 on 2018/5/7. + * 以包裹的布局文件会生成自动ViewDataBinding类 + * 如activity_main生成的文件类名是ActivityMainBinding,如果没有这个类 build一下 + */ + +public abstract class BaseBindingActivity extends BaseActivity implements View.OnClickListener { + public V mBinding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, getClass().getAnnotation(ActLayoutRes.class).value()); + mBinding.setVariable(BR.click, this); + init(); + } + + protected abstract void init(); + + @Override + public void onClick(View v) { + } + + protected void start(Class c) { + startActivity(new Intent(this, c)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseBindingFragment.java b/app/src/main/java/com/yizhuan/erban/base/BaseBindingFragment.java new file mode 100644 index 000000000..d95fb3f92 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseBindingFragment.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.base; + +import android.databinding.DataBindingUtil; +import android.databinding.ViewDataBinding; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +/** + * Created by huangmeng1 on 2018/5/7. + */ + +public abstract class BaseBindingFragment extends BaseFragment { + public V mBinding; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.bind(inflater.inflate(getClass().getAnnotation(ActLayoutRes.class).value(),container,false)); + return mBinding.getRoot(); + } + + @Override + public int getRootLayoutId() { + return getClass().getAnnotation(ActLayoutRes.class).value(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseBindingTakePhotoActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseBindingTakePhotoActivity.java new file mode 100644 index 000000000..45d142864 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseBindingTakePhotoActivity.java @@ -0,0 +1,127 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.databinding.DataBindingUtil; +import android.databinding.ViewDataBinding; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; + +import com.jph.takephoto.app.TakePhotoActivity; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.TResult; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * 可以拍照的 binding activity + * Created by MadisonRong on 21/06/2018. + */ +public abstract class BaseBindingTakePhotoActivity extends TakePhotoActivity implements View.OnClickListener { + + private static final String CAMERA_PREFIX = "picture_"; + public V mBinding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this,getClass().getAnnotation(ActLayoutRes.class).value()); + init(); + } + + protected abstract void init(); + + @Override + public void onClick(View v) { + } + + protected void showTakePhotoOperationDialog() { + ButtonItem buttonItem = new ButtonItem("拍照上传", this::checkPermissionAndStartCamera); + ButtonItem buttonItem1 = new ButtonItem("本地相册", () -> { + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(BaseBindingTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, true); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromGalleryWithCrop(uri, options); + + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, "取消", false); + } + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(this::takePhoto, R.string.ask_camera, android.Manifest.permission.CAMERA); + } + + private void takePhoto() { + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(BaseBindingTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, false); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromCaptureWithCrop(uri, options); + } + + public void onUpload(String url) { + if (onUploadListener != null) { + onUploadListener.onUploadSuccess(url); + } + getDialogManager().dismissDialog(); + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(BaseBindingTakePhotoActivity.this, "请稍后"); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + private OnUploadListener onUploadListener; + + public void setOnUploadListener(OnUploadListener onUploadListener) { + this.onUploadListener = onUploadListener; + } + + public interface OnUploadListener { + void onUploadSuccess(String url); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseBsDialog.java b/app/src/main/java/com/yizhuan/erban/base/BaseBsDialog.java new file mode 100644 index 000000000..d019fc53a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseBsDialog.java @@ -0,0 +1,60 @@ +package com.yizhuan.erban.base; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; + +import butterknife.ButterKnife; + +/** + * 定义一些通用的属性 + *

+ * Created by lvzebiao on 2019/2/28. + */ + +public abstract class BaseBsDialog extends BottomSheetDialog { + + protected Context context; + + public BaseBsDialog(@NonNull Context context) { + super(context, R.style.ErbanBottomSheetDialog); + this.context = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getDialogLayout()); + ButterKnife.bind(this); + setCanceledOnTouchOutside(isCanceledOnTouchOutside()); + FrameLayout bottomSheet = (FrameLayout) findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + } + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + //原来的计算方法在全面屏手机不适配 getResources().getDisplayMetrics().heightPixels 获取的高度不对 + //使用MATCH_PARENT + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + init(); + } + + protected abstract int getDialogLayout(); + + protected abstract void init(); + + /** + * 默认支持点击取消 + */ + protected boolean isCanceledOnTouchOutside() { + return true; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseFragment.java b/app/src/main/java/com/yizhuan/erban/base/BaseFragment.java new file mode 100644 index 000000000..299552500 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseFragment.java @@ -0,0 +1,660 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.trello.rxlifecycle2.components.support.RxFragment; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.common.AbsStatusFragment; +import com.yizhuan.erban.common.LoadingFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.common.ReloadFragment; +import com.yizhuan.erban.common.widget.StatusLayout; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.UIUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.List; +import java.util.Stack; + +import io.reactivex.Observable; +import io.reactivex.disposables.CompositeDisposable; + +/** + * @author alvin hwang + */ +public abstract class BaseFragment extends RxFragment implements KeyEvent.Callback, IDataStatus, + ConnectiveChangedReceiver.ConnectiveChangedListener, FragmentManager.OnBackStackChangedListener, IAcitivityBase { + + protected CompositeDisposable mCompositeDisposable; + + protected View mView; + protected Context mContext; + + protected boolean isDestroyView; + protected boolean mIsViewCreated; + protected RxPermissions rxPermissions; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = getContext(); + onInitArguments(getArguments()); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + rxPermissions = new RxPermissions(this); + } + + public void onNewIntent(Intent intent) { + + } + + protected void onInitArguments(Bundle bundle) { + + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + int rootLayoutId = getRootLayoutId(); + mView = inflater.inflate(rootLayoutId, container, false); + return mView; + } + + @Override + public void onDestroyView() { + mIsViewCreated = false; + isDestroyView = true; + super.onDestroyView(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mCompositeDisposable = new CompositeDisposable(); + } + + @Override + public void onDetach() { + super.onDetach(); + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mIsViewCreated = true; + onFindViews(); + onSetListener(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + restoreState(savedInstanceState); + initiate(); + } + + protected void restoreState(@Nullable Bundle savedInstanceState) { + + } + + @Override + public void onSetListener() { + + } + + @Override + public void onFindViews() { + + } + + @Override + public void onStart() { + super.onStart(); + getFragmentManager().addOnBackStackChangedListener(this); + } + + @Override + public void onStop() { + super.onStop(); + getFragmentManager().removeOnBackStackChangedListener(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (BasicConfig.INSTANCE.isDebuggable()) { + XChatApplication.getRefWatcher(getActivity()).watch(this); + } + } + + public int getRootLayoutId() { + return 0; + } + + @Override + public void onBackStackChanged() { + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + } + + /** + * 网络连接变化 + */ + /** + * wifi 转 2G/3G/4G + */ + public void wifiChange2MobileData() { + } + + /** + * 有网络变为无网络 + */ + public void change2NoConnection() { + if (isTopActive()) { + MLog.debug(this, "change2NoConnection"); + } + } + + /** + * 连上wifi + */ + public void connectiveWifi() { + if (isTopActive()) { + MLog.debug(this, "connectiveWifi"); + } + } + + /** + * 连上移动数据网络 + */ + public void connectiveMobileData() { + if (isTopActive()) { + MLog.debug(this, "connectiveMobileData"); + } + } + + /** + * 移动数据网络 改为连上wifi + */ + public void mobileDataChange2Wifi() { + if (isTopActive()) { + MLog.debug(this, "mobileDataChange2Wifi"); + } + } + + public Stack activityForResult = new Stack(); + + /** + * 为解决嵌套Fragment 收不到onActivityResult消息问题, Fragment需要调用onFragment + * + * @param requestCode + * @param resultCode + * @param data + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + while (!activityForResult.isEmpty()) { + Integer index = activityForResult.pop(); + + FragmentManager manager = getChildFragmentManager(); + if (manager == null) { //说明为activity是manager + manager = getFragmentManager(); + } + if (manager != null) { + @SuppressLint("RestrictedApi") + List list = manager.getFragments(); + if (list != null && list.size() > index) { + list.get(index).onActivityResult(requestCode, resultCode, data); + } + } else { + MLog.error(this, "嵌套fragment出现问题"); + } + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + + Fragment fragment = getFragmentInParent(); + if (fragment == null) { + super.startActivityForResult(intent, requestCode); + } else { + fragment.startActivityForResult(intent, requestCode); + } + } + + protected Fragment getFragmentInParent() { + + FragmentManager manager; + + Fragment parentFragment = this.getParentFragment(); + + if (parentFragment != null) { + manager = parentFragment.getChildFragmentManager(); + } else { + manager = this.getFragmentManager(); + } + + @SuppressLint("RestrictedApi") + List list = manager.getFragments(); + if (list != null) { + int index = list.indexOf(this); + + if (parentFragment != null && parentFragment instanceof BaseFragment) { + ((BaseFragment) parentFragment).activityForResult.push(index); + } + } + return parentFragment; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return super.onOptionsItemSelected(item); + } + + /** + * 权限回调 + */ + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + /** + * -------------------------------------------------- + * -------------------------数据状态相关----------------- + * -------------------------------------------------- + */ + + protected static final String STATUS_TAG = "STATUS_TAG"; + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + onReloadData(); + } + }; + } + + /** + * 重新加载页面数据:通常应用于无网络切换到有网络情况,重新刷新页面 + */ + public void onReloadData() { + + } + + @Override + public View.OnClickListener getLoadMoreListener() { + return null; + } + + @Override + public View.OnClickListener getNoMobileLiveDataListener() { + return null; + } + + @Override + public void showLoading() { + showLoading(0, 0); + } + + @Override + public void showLoading(View view) { + showLoading(view, 0, 0); + } + + @Override + public void showReload() { + showReload(0, 0); + } + + @Override + public void showNoData() { + showNoData(0, ""); + } + + @Override + public void showNoData(CharSequence charSequence) { + showNoData(0, charSequence); + } + + @Override + public void showNoLogin() { + + } + + @Override + public void showLoading(int drawable, int tips) { + showLoading(getView(), drawable, tips); + } + + @Override + public void showLoading(View view, int drawable, int tips) { + showLoading(view, drawable, tips, 0); + } + + protected void showLoading(View view, int drawable, int tips, int paddingBottom) { + if (!checkActivityValid()) { + return; + } + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + Fragment fragment; + if (paddingBottom == 0) { + fragment = LoadingFragment.newInstance(drawable, tips); + } else { + fragment = LoadingFragment.newInstance(drawable, tips, paddingBottom); + } + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showReload(int drawable, int tips) { + showReload(getView(), drawable, tips); + } + + @Override + public void showReload(View view, int drawable, int tips) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + ReloadFragment fragment = ReloadFragment.newInstance(drawable, tips); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNoData(int drawable, CharSequence charSequence) { + showNoData(getView(), drawable, charSequence); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showNoData view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + if (getView() == null) { + MLog.error(this, "xuwakao, showNetworkErr view is NULL"); + return; + } + View view = getView().findViewById(R.id.status_layout); + if (view == null || view.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = new NetworkErrorFragment(); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(view.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void hideStatus() { + Fragment fragment = getChildFragmentManager().findFragmentByTag(STATUS_TAG); + if (fragment != null) { + getChildFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss(); + } else { + MLog.warn(this, "xuwakao, status fragment is NULL"); + } + } + + @Override + public void showPageError(int tips) { + showPageError(getView(), tips); + } + + @Override + public void showPageError(View view, int tips) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View more = view.findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showErrorPage(tips, getLoadMoreListener()); + } + + @Override + public void showPageLoading() { + if (!checkActivityValid()) + return; + + if (getView() == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View more = getView().findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showLoadMore(); + } + + protected boolean checkActivityValid() { + return UIUtils.checkActivityValid(getActivity()); + } + + //====================================================================================// + //==============================请求过滤条件筛选的返回================================// + //====================================================================================// + public boolean isTopActive() {//FIXME 到我的音乐后,RecommendFragment仍然是isTopActive() + boolean isVisible = this.isResumed() && this.isVisible() && getUserVisibleHint(); + if (!isVisible) { + return false; + } + + FragmentManager manager = this.getChildFragmentManager(); + if (manager == null) { + return true; + } + + int count = manager.getFragments() == null ? 0 : manager.getFragments().size(); + if (count > 0) { + for (int i = 0; i < count; i++) { + Fragment fragment = manager.getFragments().get(i); + if (fragment == null) { + return true; + } + + if (fragment instanceof AbsStatusFragment) { + return true; + } + + if (fragment.isVisible()) { + return false; + } + } + } + + return true; + } + + + /** + * 当前网络是否可用 + * + * @return + */ + public boolean isNetworkAvailable() { + return NetworkUtils.isNetworkStrictlyAvailable(getActivity()); + } + + /** + * 通用消息提示 + * + * @param resId + */ + public void toast(int resId) { + toast(resId, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param tip + */ + public void toast(String tip) { + toast(tip, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param resId + * @param length + */ + public void toast(int resId, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), resId); + } + + /** + * 通用消息提示 + * + * @param tip + * @param length + */ + public void toast(String tip, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), tip, length); + } + + public boolean checkNetToast() { + boolean flag = isNetworkAvailable(); + if (!flag) + toast(R.string.str_network_not_capable); + return flag; + } + + protected DialogManager getDialogManager() { + FragmentActivity activity = getActivity(); + if (activity instanceof BaseMvpActivity) { + return ((BaseMvpActivity) activity).getDialogManager(); + } else + return getBaseActivity().getDialogManager(); + } + + public BaseActivity getBaseActivity() { + return (BaseActivity) getActivity(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU) { + showOptionsMenu(); + } +// if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { +// AudioManager audio = (AudioManager) (getContext().getSystemService(Service.AUDIO_SERVICE)); +// audio.adjustStreamVolume( +// AudioManager.STREAM_VOICE_CALL, +// AudioManager.ADJUST_LOWER, +// AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI); +// return true; +// } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { +// AudioManager audio = (AudioManager) (getContext().getSystemService(Service.AUDIO_SERVICE)); +// audio.adjustStreamVolume( +// AudioManager.STREAM_VOICE_CALL, +// AudioManager.ADJUST_RAISE, +// AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI); +// return true; +// } + return false; + } + + protected void showOptionsMenu() { + + } + + @Override + public boolean onKeyLongPress(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) { + return false; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseLazyFragment.java b/app/src/main/java/com/yizhuan/erban/base/BaseLazyFragment.java new file mode 100644 index 000000000..06ebb156c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseLazyFragment.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.base; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +/** + *

具备懒加载的fragment

+ * + * @author Administrator + * @date 2017/11/23 + */ +public abstract class BaseLazyFragment extends BaseFragment { + + private boolean mIsInitView; + private boolean mIsLoaded; + /** 当前fragment是否还活着 */ + private boolean mIsDestroyView = true; + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mIsInitView = true; + if (getUserVisibleHint() && !mIsLoaded && mIsDestroyView) { + mIsDestroyView = false; + onLazyLoadData(); + } + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser) { + if (mIsInitView && !mIsLoaded && mIsDestroyView) { + mIsDestroyView = false; + mIsLoaded = true; + onLazyLoadData(); + } + } else { + mIsLoaded = false; + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mIsDestroyView = true; + } + + /** 数据懒加载 */ + protected abstract void onLazyLoadData(); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseListViewModel.java b/app/src/main/java/com/yizhuan/erban/base/BaseListViewModel.java new file mode 100644 index 000000000..fa9adb76b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseListViewModel.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.base; + +import android.databinding.ObservableArrayList; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.support.v4.widget.SwipeRefreshLayout; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +/** + * Created by huangmeng1 on 2018/5/10. + */ + +public abstract class BaseListViewModel { + public int page = 1; + public int pageSize = Constants.PAGE_SIZE; + + public ObservableBoolean loading = new ObservableBoolean(false); + public ObservableBoolean isLode = new ObservableBoolean(false); + public ObservableArrayList data = new ObservableArrayList<>(); + public ObservableArrayList loadData = new ObservableArrayList<>(); + public ObservableField throwable = new ObservableField<>(); + + public SwipeRefreshLayout.OnRefreshListener onRefreshListener = () -> loadData(false).subscribe(); + public BaseQuickAdapter.RequestLoadMoreListener loadMoreListener = () -> loadData(true).subscribe(); + + public Single> loadData(boolean isLode) { + this.isLode.set(isLode); + if (isLode) { + page++; + } else { + page = 1; + loading.set(true); + } + return getSingle().compose(RxHelper.handleBeanData()) + .doAfterTerminate(() -> loading.set(false)) + .doOnSuccess(carInfos -> { + throwable.set(null); + loadData.clear(); + loadData.addAll(carInfos); + if (!isLode) data.clear(); + data.addAll(carInfos); + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable e) throws Exception { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), e.getMessage()); + loading.set(false); + throwable.set(e); + } + }); + } + + public abstract Single>> getSingle(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseMsListViewModel.java b/app/src/main/java/com/yizhuan/erban/base/BaseMsListViewModel.java new file mode 100644 index 000000000..3cdb79b76 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseMsListViewModel.java @@ -0,0 +1,72 @@ +package com.yizhuan.erban.base; + +import android.databinding.ObservableArrayList; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.databinding.ViewDataBinding; + +import com.trello.rxlifecycle2.LifecycleProvider; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +/** + * 移植萌声ktv复制的类 + * Created by lvzebiao on 2018/11/1. + */ + +public abstract class BaseMsListViewModel { + public V mBinding; + public int page=1; + public int pageSize= Constants.PAGE_SIZE; + + public ObservableBoolean loading=new ObservableBoolean(false); + public ObservableBoolean isLode=new ObservableBoolean(false); + public ObservableArrayList data=new ObservableArrayList<>(); + public ObservableArrayList loadData=new ObservableArrayList<>(); + public ObservableField throwable=new ObservableField<>(); + + public BaseMsListViewModel(V mBinding) { + this.mBinding = mBinding; + } + + public Single> loadData(boolean isLode){ + this.isLode.set(isLode); + if (isLode){ + page++; + }else { + page=1; + loading.set(true); + } + return getSingle().compose(RxHelper.handleBeanData()) + .compose(RxHelper.handleSchedulers()) + .doAfterTerminate(() -> loading.set(false)) + .doOnSuccess(carInfos -> { + throwable.set(null); + loadData.clear(); + loadData.addAll(carInfos); + if (!isLode) data.clear(); + data.addAll(carInfos); + }) + .doOnError(new Consumer(){ + @Override + public void accept(Throwable e) throws Exception { + loading.set(false); + throwable.set(e); + } + }); + } + + public abstract Single>> getSingle(); + + public void loadData(LifecycleProvider provider, boolean isLoad){ + loadData(isLoad) + .compose(provider.bindToLifecycle()) + .subscribe(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseMvpActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseMvpActivity.java new file mode 100644 index 000000000..65090b7d2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseMvpActivity.java @@ -0,0 +1,1034 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.ColorInt; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.model.BroadcastMessage; +import com.orhanobut.logger.Logger; +import com.readystatesoftware.systembartint.SystemBarTintManager; +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.common.LoadingFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.common.ReloadFragment; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.common.widget.StatusLayout; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.common.widget.dialog.DialogUiHelper; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.DefaultToolBar; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleGlobalNoticeDialog; +import com.yizhuan.tutu.mentoring_relationship.dialog.GrabApprenticesNoticeDialog; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.bean.BaseProtocol; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.GrabApprenticesEvent; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleProtocol; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_library.base.AbstractMvpActivity; +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.ImeUtil; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.UIUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; + +import static com.yizhuan.xchat_android_core.Constants.DEBUG_MAX_UID; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_HEAD_NOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_OPENNOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE; + + +/** + * @author alvin hwang + */ +public abstract class BaseMvpActivity> extends AbstractMvpActivity + implements IDataStatus, ConnectiveChangedReceiver.ConnectiveChangedListener, DialogManagerInterface { + + private static final String TAG = "BaseMvpActivity"; + + private DialogManager mDialogManager; + protected TitleBar mTitleBar; + protected DefaultToolBar mToolBar; + protected CompositeDisposable mCompositeDisposable; + private volatile LinkedList giftList; + private BroadcastObserver broadcastObserver; + + protected Context context; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + context = this; + mCompositeDisposable = new CompositeDisposable(); + if (setBgColor() > 0) { + getWindow().setBackgroundDrawableResource(setBgColor()); + } + if (needSteepStateBar()) { + setStatusBar(); + } + mCompositeDisposable.add(IMNetEaseManager.get().getChatRoomEventObservable() + .subscribe(roomEvent -> { + if (roomEvent == null) return; + onReceiveChatRoomEvent(roomEvent); + })); + registerNimBroadcastMessage(true); + + } + + protected void onReceiveChatRoomEvent(RoomEvent roomEvent) { + } + + /** + * 注册云信全服广播接收器 + * + * @param register true为注册,false为注销 + */ + private void registerNimBroadcastMessage(boolean register) { + if (broadcastObserver == null) { + broadcastObserver = new BroadcastObserver(this); + } + NIMSDK.getMsgServiceObserve().observeBroadcastMessage(broadcastObserver, register); + } + + public void initToolBar(int resId) { + initToolBar(getString(resId)); + } + + public void initToolBar(CharSequence title) { + mToolBar = (DefaultToolBar) findViewById(R.id.toolbar); + if (mToolBar != null) { + mToolBar.setCenterTitle(title); + mToolBar.setNavigationIcon(R.drawable.arrow_left); + mToolBar.setNavigationOnClickListener(v -> onLeftClickListener()); + } + } + + public void initTitleBar() { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && needSteepStateBar()) { + mTitleBar.setImmersive(true); + } + mTitleBar.setBackgroundColor(getResources().getColor(R.color.white)); + mTitleBar.setTitleColor(getResources().getColor(R.color.text_primary)); + } + } + + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.mipmap.common_ic_back); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } + + public void initTitleBar(int title) { + initTitleBar(getResources().getString(title)); + } + + public void initTitleBar(String title, TitleBar.Action action) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.mipmap.common_ic_back); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + // action + if (action != null) { + mTitleBar.addAction(action); + } + } + } + + protected void onLeftClickListener() { + finish(); + } + + protected boolean needSteepStateBar() { + return false; + } + + protected int setBgColor() { + return 0; + } + + /** + * 设置沉浸式状态栏 + */ + protected void setStatusBar() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //透明状态栏 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + // create our manager instance after the content view is set + SystemBarTintManager tintManager = new SystemBarTintManager(this); + // enable status bar tint + tintManager.setStatusBarTintEnabled(true); + // enable navigation bar tint + tintManager.setNavigationBarTintEnabled(true); + tintManager.setTintColor(Color.parseColor("#00000000")); + } + + /** + * 获取状态栏的高度 + * + * @return + */ + protected int getStatusBarHeight() { + try { + Class c = Class.forName("com.android.internal.R$dimen"); + Object obj = c.newInstance(); + Field field = c.getField("status_bar_height"); + int x = Integer.parseInt(field.get(obj).toString()); + return getResources().getDimensionPixelSize(x); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + @Override + public void setContentView(int layoutResID) { + super.setContentView(layoutResID); + initTitleBar(); + } + + /** + * 是否需要渲染成主题色的status bar + * + * @return + */ + protected boolean shouldConfigStatusBar() { + return true; + } + + @Override + protected void onStart() { + super.onStart(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + @Override + protected void onDestroy() { + registerNimBroadcastMessage(false); + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + + if (mNoticeDialog != null && mNoticeDialog.isShowing()) { + mNoticeDialog.dismiss(); + mNoticeDialog = null; + } + super.onDestroy(); + LogUtil.i(this.getClass().getName(), "onDestroy"); + /* ImageLoadUtils.clearMemory(this);*/ + + if (XChatApplication.isDebug()) { + XChatApplication.getRefWatcher(this).watch(this); + } + + } + + @Override + public DialogManager getDialogManager() { + if (mDialogManager == null) { + mDialogManager = new DialogManager(this); + mDialogManager.setCanceledOnClickOutside(false); + } + return mDialogManager; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Fragment fragment = getTopFragment(); + if (fragment != null && fragment instanceof BaseFragment) { + if (((BaseFragment) fragment).onKeyDown(keyCode, event)) { + return true; + } + } + + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Fragment fragment = getTopFragment(); + if (fragment != null && (fragment instanceof BaseFragment || fragment instanceof BaseMvpFragment)) { + fragment.onActivityResult(requestCode, resultCode, data); + } + super.onActivityResult(requestCode, resultCode, data); + } + + public Fragment getTopFragment() { + FragmentManager fragmentManager = getSupportFragmentManager(); + @SuppressLint("RestrictedApi") + List fragments = fragmentManager.getFragments(); + if (fragments != null) { + for (Fragment fragment : fragments) { + if (fragment != null && fragment.isVisible()) { + return fragment; + } + } + } + return null; + } + + @Override + public void onBackPressed() { + try { + super.onBackPressed(); + } catch (Exception ex) { + MLog.error(this, ex); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case android.R.id.home: + Fragment fragment = getTopFragment(); + if (fragment != null && fragment instanceof BaseFragment) { + if (fragment.onOptionsItemSelected(item)) { + return true; + } + } + onBackPressed(); + return true; + default: + break; + + } + + return super.onOptionsItemSelected(item); + } + + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { + if (menu.getClass().getSimpleName().equals("MenuBuilder")) { + try { + Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); + m.setAccessible(true); + m.invoke(menu, true); + } catch (Exception e) { + } + } + } + return super.onMenuOpened(featureId, menu); + } + + /** + * 获取backstack top + * + * @return + */ + private Fragment getLastFragment() { + @SuppressLint("RestrictedApi") + List fragments = getSupportFragmentManager().getFragments(); + if (null != fragments && fragments.size() > 0) { + for (int i = fragments.size() - 1; i >= 0; i--) { + Fragment f = fragments.get(i); + if (f != null && f instanceof BaseFragment) { + return f; + } + } + } + + return null; + } + + /** + * @param fragmentName Fragment.class.getName() + */ + public void popFragment(String fragmentName) { + getSupportFragmentManager().popBackStack(fragmentName, FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + + public String getTopFragmentName() { + FragmentManager fragmentManager = getSupportFragmentManager(); + if (fragmentManager.getBackStackEntryCount() > 0) { + return fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); + } + return null; + } + + @SuppressLint("CheckResult") + @Override + protected void onResume() { + super.onResume(); + //add connective changed broadcast receiver +// ConnectiveChangedReceiver.getInstance().registerConnectiveChange(this); + StatisticManager.Instance().onResume(this); + // TODO: 2018/2/25 bug fixed + // TODO: 2018/2/25 java.lang.RuntimeException:Unable to resume activity + // TODO: 2018/2/25 {com.yizhuan.erban/com.yizhuan.erban.other.activity.SplashActivity}: java.lang.ClassCastException: int[] cannot be cast to java.lang.Object[] + //GlideApp.with(this).resumeRequests(); + RxBus.get().toFlowable(String.class) + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .subscribe((s) -> { + if (XChatConstants.SHOW.equals(s)) { + getDialogManager().showProgressDialog(this, "请稍后...", true); + } else if (XChatConstants.HIDE.equals(s)) { + getDialogManager().dismissDialog(); + } + }, throwable -> { + }); + + RxBus.get() + .toFlowable(GrabApprenticesEvent.class) + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onGrabApprenticesEvent); + + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindUntilEvent(ActivityEvent.PAUSE)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::onRoomEventReceived); + } + + @Override + protected void onPause() { + hideIME(); + super.onPause(); + //remove connective changed broadcast receiver +// ConnectiveChangedReceiver.getInstance().unRegisterConnectiveChange(this); + + StatisticManager.Instance().onPause(this); + + // TODO: 2018/2/25 java.lang.IllegalStateException: You cannot call Glide.get() in registerComponents(), use the provided Glide instance instead + // GlideApp.with(this).pauseRequests(); + } + + + /** + * wifi 转 2G/3G/4G + */ + @Override + public void wifiChange2MobileData() { + + } + + /** + * 有网络变为无网络 + */ + @Override + public void change2NoConnection() { + if (isTopActive()) { + + } + } + + /** + * 连上wifi + */ + @Override + public void connectiveWifi() { + if (isTopActive()) { + + } + } + + /** + * 连上移动数据网络 + */ + @Override + public void connectiveMobileData() { + if (isTopActive()) { + + } + } + + /** + * 移动数据网络 改为连上wifi + */ + @Override + public void mobileDataChange2Wifi() { + + } + + protected boolean checkActivityValid() { + return UIUtils.checkActivityValid(this); + } + + /** + * 弹出登录框 + * + * @return + */ + public void showLoginDialog() { +// if (mLoginDialog == null) { +// mLoginDialog = new LoginPopupDialog(this, new OnClickLoginPopupListener(this)); +// } + ImeUtil.hideIME(this); +// mLoginDialog.show(); + } + + protected static final String STATUS_TAG = "STATUS_TAG"; + + @Override + public View.OnClickListener getLoadListener() { + return v -> onReloadDate(); + } + + /** + * 网络错误重新加载数据 + */ + public void onReloadDate() { + + } + + @Override + public View.OnClickListener getLoadMoreListener() { + return null; + } + + @Override + public View.OnClickListener getNoMobileLiveDataListener() { + return null; + } + + @Override + public void showLoading() { + showLoading(0, 0); + } + + @Override + public void showLoading(View view) { + showLoading(view, 0, 0); + } + + @Override + public void showReload() { + showReload(0, 0); + } + + @Override + public void showNoData() { + showNoData(0, ""); + } + + @Override + public void showNoLogin() { + + } + + @Override + public void showLoading(int drawable, int tips) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + Fragment fragment = LoadingFragment.newInstance(drawable, tips); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showLoading(View view, int drawable, int tips) { + + } + + @Override + public void showReload(int drawable, int tips) { + showReload(drawable, tips, 1); + } + + public void showReload(@ColorInt int bgColor) { + showReload(0, 0, bgColor); + } + + public void showReload(int drawable, int tips, @ColorInt int bgColor) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + ReloadFragment fragment = ReloadFragment.newInstance(drawable, tips, bgColor); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showReload(View view, int drawable, int tips) { + + } + + @Override + public void showNoData(CharSequence charSequence) { + showNoData(0, charSequence); + } + + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(drawable, charSequence); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + + } + + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = new NetworkErrorFragment(); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void hideStatus() { + Fragment fragment = getSupportFragmentManager().findFragmentByTag(STATUS_TAG); + if (fragment != null) { + getSupportFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss(); + } + } + + @Override + public void showPageError(int tips) { + if (!checkActivityValid()) { + return; + } + + View more = findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showErrorPage(tips, getLoadMoreListener()); + } + + @Override + public void showPageError(View view, int tips) { + + } + + @Override + public void showPageLoading() { + if (!checkActivityValid()) { + return; + } + + View more = findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showLoadMore(); + } + + /** + * 当前网络是否可用 + * + * @return + */ + public boolean isNetworkAvailable() { + return NetworkUtils.isNetworkStrictlyAvailable(this); + } + + public boolean checkNetToast() { + boolean flag = isNetworkAvailable(); + if (!flag) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), R.string.str_network_not_capable); + } + return flag; + } + + + public void hideIME() { + View v = getCurrentFocus(); + if (null != v) + hideIME(v); + } + + public void hideIME(View v) { + InputMethodManager imm = (InputMethodManager) BasicConfig.INSTANCE.getAppContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null && imm.isActive()) { + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + } + } + + public void showIME(final View vv) { + View v = vv; + if (null == v) { + v = getCurrentFocus(); + if (null == v) + return; + } + ((InputMethodManager) BasicConfig.INSTANCE.getAppContext().getSystemService(INPUT_METHOD_SERVICE)) + .showSoftInput(v, InputMethodManager.SHOW_FORCED); + } + + /** + * 当前无Fragment 或 无Fragment添加 视为顶部激活状态 + * + * @return + */ + public boolean isTopActive() { + + if (isTopActivity()) { + FragmentManager fragmentManager = getSupportFragmentManager(); + + @SuppressLint("RestrictedApi") + List fragments = fragmentManager.getFragments(); + if (fragments == null || fragments.size() == 0) { + return true; + } else { + int size = fragments.size(); + for (int i = 0; i < size; i++) { + //TODO why null? + if (fragments.get(i) != null && fragments.get(i).isAdded()) + return false; + } + return true; + } + } + return false; + } + + public boolean isTopActivity() { + return UIUtils.isTopActivity(this); + } + + /** + * 通用消息提示 + * + * @param resId + */ + public void toast(int resId) { + toast(resId, Toast.LENGTH_SHORT); + } + + public void toast(String toast) { + toast(toast, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param resId + * @param length + */ + public void toast(int resId, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), resId, length); + } + + public void toast(String toast, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), toast, length); + } + + + private void configStatusBar() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.setStatusBarColor(getResources().getColor(R.color.white)); + + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + + // create our manager instance after the content view is set + SystemBarTintManager tintManager = new SystemBarTintManager(this); + // enable status bar tint + tintManager.setStatusBarTintEnabled(true); + // enable navigation bar tint + tintManager.setNavigationBarTintEnabled(true); + + tintManager.setTintResource(R.color.white); + } + } + + + /** + * 权限回调接口 + */ + private PermissionActivity.CheckPermListener mListener; + + private RxPermissions rxPermissions = new RxPermissions(this); + + @SuppressLint("CheckResult") + public void checkPermission(PermissionActivity.CheckPermListener listener, + int resString, String... mPerms) { + mListener = listener; + rxPermissions.request(mPerms) + .subscribe(aBoolean -> { + if (aBoolean && listener != null) { + listener.superPermission(); + } + }, Throwable::printStackTrace); + } + + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + /** + * 当前Activity 是否有效 + */ + protected boolean isValid() { + return !isFinishing() && !isDestroyed(); + } + + /** + * 接收到全局广播信息 + * + * @param body 信息实体 + */ + protected void onReceivedNimBroadcastMessage(String body) { + + BaseProtocol baseProtocol; + try { + baseProtocol = JSON.parseObject(body, BaseProtocol.class); + } catch (Exception e) { + baseProtocol = null; + } + + if (baseProtocol == null) return; + + switch (baseProtocol.getFirst()) { + case CUSTOM_MESS_HEAD_NOBLE: + int second = baseProtocol.getSecond(); + if (second == CUSTOM_MESS_SUB_OPENNOBLE || second == CUSTOM_MESS_SUB_RENEWNOBLE) { + NobleProtocol.DataBean data = JSON.parseObject(String.valueOf(baseProtocol.getData()), NobleProtocol.DataBean.class); + NobleInfo nobleInfo; + if (data == null || (nobleInfo = data.getNobleInfo()) == null || (data.getUid() < DEBUG_MAX_UID && !XChatApplication.isDebug())) + return; + + int type = data.getType(); + String nick = data.getNick(); + String content = null; + String noticeBefore = getString(R.string.global_notice_before); + if (type == 1) { + //恭喜 xxxx 开通“国王”贵族,速来膜拜 + if (TextUtils.isEmpty(data.getRoomTitle())) { + content = noticeBefore + getString(R.string.noble_open_notice, nick, nobleInfo.getName()); + } else { + content = noticeBefore + getString(R.string.noble_open_in_room_notice, nick, nobleInfo.getName(), + String.valueOf(data.getRoomErbanNo()), data.getRoomTitle()); + } + } else if (type == 2) { + //恭喜 xxxx 续费“国王”贵族 + content = noticeBefore + getString(R.string.noble_reopen_notice, nick, nobleInfo.getName()); + } + if (!TextUtils.isEmpty(content)) { + + String nobleName = nobleInfo.getName(); + Spannable spannable = new SpannableString(content); + + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, noticeBefore.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + int start = content.lastIndexOf(nick); + int end = start + nick.length(); + spannable.setSpan(new StyleSpan(Typeface.BOLD), start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + start = content.lastIndexOf(nobleName); + end = start + nobleName.length(); + spannable.setSpan(new StyleSpan(Typeface.BOLD), start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + if (mNoticeDialog != null && mNoticeDialog.isShowing()) + mNoticeDialog.dismiss(); + mNoticeDialog = new OpenNobleGlobalNoticeDialog(this, spannable); + mNoticeDialog.show(); + } + } + break; + default: + break; + } + + } + + + private OpenNobleGlobalNoticeDialog mNoticeDialog; + + public static class BroadcastObserver implements Observer { + private WeakReference mReference; + + public BroadcastObserver(BaseMvpActivity baseMvpActivity) { + mReference = new WeakReference<>(baseMvpActivity); + } + + @Override + public void onEvent(BroadcastMessage broadcastMessage) { + if (broadcastMessage != null) { + String contentStr = broadcastMessage.getContent(); + Logger.i("全局广播:" + contentStr); + if (TextUtils.isEmpty(contentStr)) return; + BaseMvpActivity baseMvpActivity = mReference.get(); + if (baseMvpActivity == null) return; + if (baseMvpActivity.isValid()) { + + JSONObject jsonObject; + try { + jsonObject = JSON.parseObject(contentStr); + } catch (Exception e) { + jsonObject = null; + } + if (jsonObject == null) return; + if (jsonObject.containsKey("body")) { + String body = jsonObject.getString("body"); + if (TextUtils.isEmpty(body)) return; + baseMvpActivity.onReceivedNimBroadcastMessage(body); + } + } + } + } + } + + /** + * 通知栏白底黑字 + * + * @param isDark true:黑色 + */ + public void StatusBarLightModes(boolean isDark) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setStatusBarColor(getResources().getColor(R.color.white)); + } + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (isDark) { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } else { + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + } + } + } + } + + protected volatile GrabApprenticesNoticeDialog dialog; + + public void onGrabApprenticesEvent(GrabApprenticesEvent event) { + if (!isTopActivity()) return; + if (dialog != null && dialog.isAdded()) { + dialog.dismiss(); + } + dialog = new GrabApprenticesNoticeDialog(); + dialog.show(getSupportFragmentManager()); + } + + public void onRoomEventReceived(RoomEvent roomEvent) { + switch (roomEvent.getEvent()) { + case RoomEvent.RECHARGE: + onNeedCharge(); + break; + + case RoomEvent.RADISH_NOT_ENOUGH: + DialogUiHelper.showRadishNotEnoughDialog(this, null); + break; + + case RoomEvent.GIFT_OUT_OF_DATE: + SingleToastUtil.showToast(roomEvent.getMessage()); + break; + } + } + + private boolean isShowingChargeDialog; + + private void onNeedCharge() { + if (isShowingChargeDialog) { + return; + } + isShowingChargeDialog = true; + new DialogManager(this).showOkCancelDialog(getString(R.string.tips_need_charge), + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + isShowingChargeDialog = false; + ChargeActivity.start(context); + } + + @Override + public void onCancel() { + isShowingChargeDialog = false; + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseMvpFragment.java b/app/src/main/java/com/yizhuan/erban/base/BaseMvpFragment.java new file mode 100644 index 000000000..9c353cf93 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseMvpFragment.java @@ -0,0 +1,644 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.common.AbsStatusFragment; +import com.yizhuan.erban.common.LoadingFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.common.ReloadFragment; +import com.yizhuan.erban.common.widget.StatusLayout; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.reciever.ConnectiveChangedReceiver; +import com.yizhuan.xchat_android_library.base.AbstractMvpFragment; +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.UIUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.lang.ref.SoftReference; +import java.util.List; +import java.util.Stack; + +import io.reactivex.Observable; +import io.reactivex.disposables.CompositeDisposable; + +/** + * @author alvin hwang + */ +public abstract class BaseMvpFragment> extends AbstractMvpFragment implements KeyEvent.Callback, IDataStatus, + ConnectiveChangedReceiver.ConnectiveChangedListener, FragmentManager.OnBackStackChangedListener, IAcitivityBase { + + //是否已经已完成(网络、数据库)请求数据 + protected boolean requested = false; + + //保留对最初的视图的软引用 + private SoftReference mViewReference; + + protected View mView; + protected Context mContext; + protected CompositeDisposable mCompositeDisposable; + protected RxPermissions rxPermissions; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCompositeDisposable = new CompositeDisposable(); + mContext = getContext(); + onInitArguments(getArguments()); + } + + + public void onNewIntent(Intent intent) { + + } + + protected void onInitArguments(Bundle bundle) { + + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + int rootLayoutId = getRootLayoutId(); + mView = inflater.inflate(rootLayoutId, container, false); + return mView; + } + + public void showLoginDialog() { + getBaseActivity().showLoginDialog(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + rxPermissions = new RxPermissions(this); + } + + @Override + public void onDetach() { + super.onDetach(); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + onFindViews(); + onSetListener(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + restoreState(savedInstanceState); + initiate(); + } + + protected void restoreState(@Nullable Bundle savedInstanceState) { + + } + + @Override + public void onStart() { + super.onStart(); + getFragmentManager().addOnBackStackChangedListener(this); + } + + @Override + public void onStop() { + super.onStop(); + getFragmentManager().removeOnBackStackChangedListener(this); + } + + @Override + public void onDestroy() { + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + super.onDestroy(); + if (BasicConfig.INSTANCE.isDebuggable()) { + XChatApplication.getRefWatcher(getActivity()).watch(this); + } + } + + public abstract int getRootLayoutId(); + + @Override + public void onBackStackChanged() { + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + } + + /** + * 网络连接变化 + */ + /** + * wifi 转 2G/3G/4G + */ + public void wifiChange2MobileData() { + } + + /** + * 有网络变为无网络 + */ + public void change2NoConnection() { + if (isTopActive()) { + MLog.debug(this, "change2NoConnection"); + } + } + + /** + * 连上wifi + */ + public void connectiveWifi() { + if (isTopActive()) { + MLog.debug(this, "connectiveWifi"); + } + } + + /** + * 连上移动数据网络 + */ + public void connectiveMobileData() { + if (isTopActive()) { + MLog.debug(this, "connectiveMobileData"); + } + } + + /** + * 移动数据网络 改为连上wifi + */ + public void mobileDataChange2Wifi() { + if (isTopActive()) { + MLog.debug(this, "mobileDataChange2Wifi"); + } + } + + public Stack activityForResult = new Stack(); + + /** + * 为解决嵌套Fragment 收不到onActivityResult消息问题, Fragment需要调用onFragment + * + * @param requestCode + * @param resultCode + * @param data + */ + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + while (!activityForResult.isEmpty()) { + Integer index = activityForResult.pop(); + + FragmentManager manager = getChildFragmentManager(); + if (manager == null) { //说明为activity是manager + manager = getFragmentManager(); + } + if (manager != null) { + @SuppressLint("RestrictedApi") + List list = manager.getFragments(); + if (list != null && list.size() > index) { + list.get(index).onActivityResult(requestCode, resultCode, data); + } + } else { + MLog.error(this, "嵌套fragment出现问题"); + } + } + + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + + Fragment fragment = getFragmentInParent(); + if (fragment == null) { + super.startActivityForResult(intent, requestCode); + } else { + fragment.startActivityForResult(intent, requestCode); + } + } + + protected Fragment getFragmentInParent() { + + FragmentManager manager; + + Fragment parentFragment = this.getParentFragment(); + + if (parentFragment != null) { + manager = parentFragment.getChildFragmentManager(); + } else { + manager = this.getFragmentManager(); + } + + @SuppressLint("RestrictedApi") + List list = manager.getFragments(); + if (list != null) { + int index = list.indexOf(this); + + if (parentFragment != null && parentFragment instanceof BaseMvpFragment) { + ((BaseMvpFragment) parentFragment).activityForResult.push(index); + } + } + return parentFragment; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return super.onOptionsItemSelected(item); + } + + /** + * 权限回调 + */ + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + /** + * -------------------------------------------------- + * -------------------------数据状态相关----------------- + * -------------------------------------------------- + */ + + protected static final String STATUS_TAG = "STATUS_TAG"; + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + onReloadData(); + } + }; + } + + /** + * 重新加载页面数据:通常应用于无网络切换到有网络情况,重新刷新页面 + */ + public void onReloadData() { + + } + + @Override + public View.OnClickListener getLoadMoreListener() { + return null; + } + + @Override + public View.OnClickListener getNoMobileLiveDataListener() { + return null; + } + + @Override + public void showLoading() { + showLoading(0, 0); + } + + @Override + public void showLoading(View view) { + showLoading(view, 0, 0); + } + + @Override + public void showReload() { + showReload(0, 0); + } + + @Override + public void showNoData() { + showNoData(0, ""); + } + + @Override + public void showNoData(CharSequence charSequence) { + showNoData(0, charSequence); + } + + @Override + public void showNoLogin() { + + } + + @Override + public void showLoading(int drawable, int tips) { + showLoading(getView(), drawable, tips); + } + + @Override + public void showLoading(View view, int drawable, int tips) { + showLoading(view, drawable, tips, 0); + } + + protected void showLoading(View view, int drawable, int tips, int paddingBottom) { + if (!checkActivityValid()) { + return; + } + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + Fragment fragment; + if (paddingBottom == 0) { + fragment = LoadingFragment.newInstance(drawable, tips); + } else { + fragment = LoadingFragment.newInstance(drawable, tips, paddingBottom); + } + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showReload(int drawable, int tips) { + showReload(getView(), drawable, tips); + } + + @Override + public void showReload(View view, int drawable, int tips) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + ReloadFragment fragment = ReloadFragment.newInstance(drawable, tips); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNoData(int drawable, CharSequence charSequence) { + showNoData(getView(), drawable, charSequence); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showNoData view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + if (getView() == null) { + MLog.error(this, "xuwakao, showNetworkErr view is NULL"); + return; + } + View view = getView().findViewById(R.id.status_layout); + if (view == null || view.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = new NetworkErrorFragment(); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(view.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void hideStatus() { + Fragment fragment = getChildFragmentManager().findFragmentByTag(STATUS_TAG); + if (fragment != null) { + getChildFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss(); + } else { + MLog.warn(this, "xuwakao, status fragment is NULL"); + } + } + + @Override + public void showPageError(int tips) { + showPageError(getView(), tips); + } + + @Override + public void showPageError(View view, int tips) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View more = view.findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showErrorPage(tips, getLoadMoreListener()); + } + + @Override + public void showPageLoading() { + if (!checkActivityValid()) + return; + + if (getView() == null) { + MLog.error(this, "xuwakao, showReload view is NULL"); + return; + } + View more = getView().findViewById(R.id.loading_more); + if (more == null) { + MLog.error(this, "xuwakao, showReload more is NULL"); + return; + } + StatusLayout statusLayout = (StatusLayout) more.getParent(); + statusLayout.showLoadMore(); + } + + protected boolean checkActivityValid() { + return UIUtils.checkActivityValid(getActivity()); + } + + //====================================================================================// + //==============================请求过滤条件筛选的返回================================// + //====================================================================================// + public boolean isTopActive() {//FIXME 到我的音乐后,RecommendFragment仍然是isTopActive() + boolean isVisible = this.isResumed() && this.isVisible() && getUserVisibleHint(); + if (!isVisible) { + return false; + } + + FragmentManager manager = this.getChildFragmentManager(); + if (manager == null) { + return true; + } + + int count = manager.getFragments() == null ? 0 : manager.getFragments().size(); + if (count > 0) { + for (int i = 0; i < count; i++) { + Fragment fragment = manager.getFragments().get(i); + if (fragment == null) { + return true; + } + + if (fragment instanceof AbsStatusFragment) { + return true; + } + + if (fragment.isVisible()) { + return false; + } + } + } + + return true; + } + + + /** + * 当前网络是否可用 + * + * @return + */ + public boolean isNetworkAvailable() { + return NetworkUtils.isNetworkStrictlyAvailable(getActivity()); + } + + /** + * 通用消息提示 + * + * @param resId + */ + public void toast(int resId) { + toast(resId, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param tip + */ + public void toast(String tip) { + toast(tip, Toast.LENGTH_SHORT); + } + + /** + * 通用消息提示 + * + * @param resId + * @param length + */ + public void toast(int resId, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), resId); + } + + /** + * 通用消息提示 + * + * @param tip + * @param length + */ + public void toast(String tip, int length) { + SingleToastUtil.showToast(BasicConfig.INSTANCE.getAppContext(), tip, length); + } + + public boolean checkNetToast() { + boolean flag = isNetworkAvailable(); + if (!flag) + toast(R.string.str_network_not_capable); + return flag; + } + + protected DialogManager getDialogManager() { + if (getActivity() instanceof BaseActivity) { + return ((BaseActivity) getActivity()).getDialogManager(); + } + return getBaseActivity().getDialogManager(); + } + + public BaseMvpActivity getBaseActivity() { + return (BaseMvpActivity) getActivity(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU) { + showOptionsMenu(); + } + if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { + AudioManager audio = (AudioManager) (getContext().getSystemService(Service.AUDIO_SERVICE)); + audio.adjustStreamVolume( + AudioManager.STREAM_VOICE_CALL, + AudioManager.ADJUST_LOWER, + AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI); + return true; + } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { + AudioManager audio = (AudioManager) (getContext().getSystemService(Service.AUDIO_SERVICE)); + audio.adjustStreamVolume( + AudioManager.STREAM_VOICE_CALL, + AudioManager.ADJUST_RAISE, + AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_SHOW_UI); + return true; + } + return false; + } + + protected void showOptionsMenu() { + + } + + @Override + public boolean onKeyLongPress(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) { + return false; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseMvpPresenter.java b/app/src/main/java/com/yizhuan/erban/base/BaseMvpPresenter.java new file mode 100644 index 000000000..cc385595d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseMvpPresenter.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.base; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + + + +/** + * @author jack + * @Description + * @Date 2018/5/9 + */ + +public class BaseMvpPresenter extends AbstractMvpPresenter { + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseMvpTakePhotoActivity.java b/app/src/main/java/com/yizhuan/erban/base/BaseMvpTakePhotoActivity.java new file mode 100644 index 000000000..88f6eb3bc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseMvpTakePhotoActivity.java @@ -0,0 +1,190 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.CallSuper; +import android.util.Log; +import android.view.View; + +import com.jph.takephoto.app.TakePhoto; +import com.jph.takephoto.app.TakePhotoActivity; +import com.jph.takephoto.app.TakePhotoImpl; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.CropOptions; +import com.jph.takephoto.model.InvokeParam; +import com.jph.takephoto.model.TContextWrap; +import com.jph.takephoto.model.TResult; +import com.jph.takephoto.permission.InvokeListener; +import com.jph.takephoto.permission.PermissionManager; +import com.jph.takephoto.permission.TakePhotoInvocationHandler; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; +import com.jph.takephoto.permission.PermissionManager.TPermissionType; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * 拍照功能 + * Created by lvzebiao on 2019/1/3. + */ + +public abstract class BaseMvpTakePhotoActivity> extends BaseMvpActivity + implements TakePhoto.TakeResultListener, InvokeListener { + private static final String TAG = BaseMvpTakePhotoActivity.class.getName(); + private static final String CAMERA_PREFIX = "picture_"; + + private TakePhoto takePhoto; + private InvokeParam invokeParam; + + protected void showTakePhotoOperationDialog() { + ButtonItem buttonItem = new ButtonItem("拍照上传", this::checkPermissionAndStartCamera); + ButtonItem buttonItem1 = new ButtonItem("本地相册", () -> { + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(BaseMvpTakePhotoActivity.this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, true); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromGalleryWithCrop(uri, options); + + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, "取消", false); + } + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(checkPermissionListener, R.string.ask_camera, android.Manifest.permission.CAMERA); + } + + PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() { + @Override + public void superPermission() { + takePhoto(); + } + }; + + private void takePhoto() { + String mCameraCapturingName = CAMERA_PREFIX + System.currentTimeMillis() + ".jpg"; + File cameraOutFile = JXFileUtils.getTempFile(this, mCameraCapturingName); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + getTakePhoto().onEnableCompress(compressConfig, false); + CropOptions options = new CropOptions.Builder().setWithOwnCrop(true).create(); + getTakePhoto().onPickFromCaptureWithCrop(uri, options); + } + + public void onUpload(String url) { + if (onUploadListener != null) { + onUploadListener.onUploadSuccess(url); + } + getDialogManager().dismissDialog(); + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(this, "请稍后"); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + + //保存activity之前的状态 + @Override + @CallSuper + protected void onSaveInstanceState(Bundle outState) { + getTakePhoto().onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + + //访问请求结果 + @Override + @CallSuper + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + getTakePhoto().onActivityResult(requestCode, resultCode, data); + super.onActivityResult(requestCode, resultCode, data); + + } + + //请求权限返回结果 + @Override + @CallSuper + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + TPermissionType type = PermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + PermissionManager.handlePermissionsResult(this, type, invokeParam, this); + } + + /** + * 获取TakePhoto实例 + * + * @return + */ + public TakePhoto getTakePhoto() { + if (takePhoto == null) { + takePhoto = (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this, this)); + } + return takePhoto; + } + + @Override + public void takeCancel() { + Log.i(TAG, getResources().getString(R.string.msg_operation_canceled)); + } + + @Override + public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) { + PermissionManager.TPermissionType type = PermissionManager.checkPermission(TContextWrap.of(this), invokeParam.getMethod()); + if (PermissionManager.TPermissionType.WAIT.equals(type)) { + this.invokeParam = invokeParam; + } + return type; + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + private OnUploadListener onUploadListener; + + public void setOnUploadListener(OnUploadListener onUploadListener) { + this.onUploadListener = onUploadListener; + } + + public interface OnUploadListener { + void onUploadSuccess(String url); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseSdDialog.java b/app/src/main/java/com/yizhuan/erban/base/BaseSdDialog.java new file mode 100644 index 000000000..b20f771a5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseSdDialog.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.base; + +import android.content.Context; +import android.support.v7.app.AppCompatDialog; + + +/** + * save dismiss dialog + * create by lvzebiao @2019/7/19 + */ +public class BaseSdDialog extends AppCompatDialog { + + public Context context; + + public BaseSdDialog(Context context) { + super(context); + init(context); + } + + public BaseSdDialog(Context context, int theme) { + super(context, theme); + init(context); + } + + protected BaseSdDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + init(context); + } + + private void init(Context context) { + this.context = context; + } + + @Override + public void dismiss() { + try { + super.dismiss(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseViewModel.java b/app/src/main/java/com/yizhuan/erban/base/BaseViewModel.java new file mode 100644 index 000000000..e1c4eaada --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseViewModel.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.base; + +import android.databinding.ObservableBoolean; +import android.databinding.ViewDataBinding; + +/** + * Created by huangmeng1 on 2018/5/7. + */ + +public class BaseViewModel { + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/BaseYAdapter.java b/app/src/main/java/com/yizhuan/erban/base/BaseYAdapter.java new file mode 100644 index 000000000..2561f293c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/BaseYAdapter.java @@ -0,0 +1,121 @@ +package com.yizhuan.erban.base; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.erban.ui.utils.ArrayUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public abstract class BaseYAdapter extends RecyclerView.Adapter { + + public Context mContext; + public ArrayList mListData; + //子项点击事件 + + public BaseYAdapter(Context context) { + this.mContext = context; + mListData = new ArrayList(); + } + + public ArrayList getListData() { + return mListData; + } + + /** + * 删除列表�?��数据并刷�? + */ + public void deleteAll() { + mListData.clear(); + } + + /** + * 获取指定未知的数�? + */ + public T getItem(int position) { + if (null == mListData) { + return null; + } else { + return mListData.get(position); + } + } + + /** + * 删除某项数据 + */ + public void deleteItemOf(int position) { + mListData.remove(position); + notifyItemRemoved(position); + } + + public void deleteItem(T t){ + mListData.remove(t); + notifyDataSetChanged(); + } + + + /** + * 添加数据并刷新 + */ + public void addItem(Collection t) { + if (null == t) { + return; + } + if (t instanceof ArrayList) { + mListData.addAll(t); + } else { + mListData.add((T) t); + } + notifyDataSetChanged(); + } + + public void add(T t) { + mListData.add(t); + notifyDataSetChanged(); + } + + public void add(int position,T t) { + mListData.add(position,t); + notifyDataSetChanged(); + } + + public void set(int position,T t) { + mListData.set(position,t); + notifyItemChanged(position); + } + + public boolean replace(T newT,T t){ + if(mListData.contains(t)){ + int position = mListData.indexOf(t); + mListData.set(position,newT); + return true; + }else{ + return false; + } + } + + private List deepList; + + public List deepCopy(){ + deepList = ArrayUtils.deepCopy(mListData); + return deepList; + } + + @Override + public int getItemCount() { + return (mListData == null) ? 0 : mListData.size(); + } + + + public static class BaseViewHolder extends RecyclerView.ViewHolder { + + public BaseViewHolder(View arg0) { + super(arg0); + + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/DialogManagerInterface.java b/app/src/main/java/com/yizhuan/erban/base/DialogManagerInterface.java new file mode 100644 index 000000000..2e362409e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/DialogManagerInterface.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.base; + +import com.yizhuan.erban.common.widget.dialog.DialogManager; + +/** + * 返回通用的dialogmanager + */ +public interface DialogManagerInterface { + DialogManager getDialogManager(); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/IAcitivityBase.java b/app/src/main/java/com/yizhuan/erban/base/IAcitivityBase.java new file mode 100644 index 000000000..dc07eeda0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/IAcitivityBase.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.base; + +/** + * Created by zhouxiangfeng on 17/3/5. + */ + +public interface IAcitivityBase extends IBase { + + void onFindViews(); + + void onSetListener(); + + void initiate(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/IBase.java b/app/src/main/java/com/yizhuan/erban/base/IBase.java new file mode 100644 index 000000000..e763517be --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/IBase.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.base; + +/** + * Created by zhouxiangfeng on 17/3/5. + */ +public interface IBase { +} diff --git a/app/src/main/java/com/yizhuan/erban/base/IDataStatus.java b/app/src/main/java/com/yizhuan/erban/base/IDataStatus.java new file mode 100644 index 000000000..0f12fc946 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/IDataStatus.java @@ -0,0 +1,50 @@ +package com.yizhuan.erban.base; + +import android.view.View; + +/** + * Created by xujiexing on 14-7-15. + */ +public interface IDataStatus { + + public View.OnClickListener getLoadListener(); + + public View.OnClickListener getLoadMoreListener(); + + public View.OnClickListener getNoMobileLiveDataListener(); + + public void showLoading(); + + public void showLoading(View view); + + public void showReload(); + + public void showNoLogin(); + + public void showLoading(int drawable, int tips); + + public void showLoading(View view, int drawable, int tips); + + public void showReload(int drawable, int tips); + + public void showReload(View view, int drawable, int tips); + + public void showNoData(); + + public void showNoData(CharSequence charSequence); + + public void showNoData(int drawable, CharSequence charSequence); + + public void showNoData(View view, int drawable, CharSequence charSequence); + + public void showNetworkErr(); + + public void hideStatus(); + + public void showPageError(int tips); + + public void showPageError(View view, int tips); + + public void showPageLoading(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/LRecyclerView.java b/app/src/main/java/com/yizhuan/erban/base/LRecyclerView.java new file mode 100644 index 000000000..0a1e5d575 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/LRecyclerView.java @@ -0,0 +1,163 @@ +package com.yizhuan.erban.base; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; + +/** + *

具有加载更多的recycler view

+ * Created by Administrator on 2017/11/13. + */ +public class LRecyclerView extends RecyclerView { + + private boolean mIsLoading = false; + private int initPreItem = 0; //预加载个数 + private SwipeRefreshLayout mSwipeRefreshLayout; + + public LRecyclerView(Context context) { + this(context, null); + } + + public LRecyclerView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public LRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + addOnScrollListener(mOnScrollListener); + } + + /** + * 绑定刷新控件 + * + * @param swipeRefreshLayout + */ + public void bindSwipeRefreshLayout(SwipeRefreshLayout swipeRefreshLayout) { + this.mSwipeRefreshLayout = swipeRefreshLayout; + } + + public void finishLoading() { + mIsLoading = false; + } + + public boolean isLoading() { + return mIsLoading; + } + + /** + * 设置预加载的item个数 + * + * @param initPreItem + */ + public void setInitPreItem(int initPreItem) { + this.initPreItem = initPreItem; + } + + private OnScrollListener mOnScrollListener = new OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + checkSwipeRefreshNull(); + /* Log.i("liao", "newState=" + newState); + + //第一种方式 有个bug:当最后一个item刚显示出来的时候停止滑动这个时候也会触发滑动到底部的操作 + LayoutManager layoutManager = getLayoutManager(); + int itemCount = layoutManager.getItemCount(); + int lastVisibleItemPosition = 0; + if (layoutManager instanceof LinearLayoutManager) { + LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; + lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition(); + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; + //得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了 + int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()]; + staggeredGridLayoutManager.findLastVisibleItemPositions(lastPositions); + lastVisibleItemPosition = findMax(lastPositions); + } + + if (!mIsLoading && ((lastVisibleItemPosition + 1) >= itemCount) && newState == SCROLL_STATE_IDLE) { + + Log.i("liao", "加载.....lastVisibleItemPosition=" + lastVisibleItemPosition + ",itemCount=" + itemCount); + mIsLoading = true; + post(new Runnable() { + @Override + public void run() { + if (mOnLoadingListener != null) { + mOnLoadingListener.onLoading(); + } + } + }); + }*/ + + //第二种方式 + //得到当前显示的最后一个item的view + View lastChildView = recyclerView.getLayoutManager().getChildAt(recyclerView.getLayoutManager().getChildCount() - 1); + //得到lastChildView的bottom坐标值 + int lastChildBottom = lastChildView.getBottom(); + //得到Recycler view的底部坐标减去底部padding值,也就是显示内容最底部的坐标 + int recyclerBottom = recyclerView.getBottom() - recyclerView.getPaddingBottom(); + //通过这个lastChildView得到这个view当前的position值 + int lastPosition = recyclerView.getLayoutManager().getPosition(lastChildView); + + //判断lastChildView的bottom值跟recyclerBottom + //判断lastPosition是不是最后一个position + //如果两个条件都满足则说明是真正的滑动到了底部 + if (!mIsLoading + && lastChildBottom == recyclerBottom + && (lastPosition == recyclerView.getLayoutManager().getItemCount() - 1 - initPreItem) + && newState == SCROLL_STATE_IDLE + && !mSwipeRefreshLayout.isRefreshing()) { + mIsLoading = true; + post(new Runnable() { + @Override + public void run() { + if (mOnLoadingListener != null) { + mOnLoadingListener.onLoading(); + } + } + }); + } + mSwipeRefreshLayout.setEnabled(!mIsLoading); + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + //处理刷新冲突问题 +// int topRowVerticalPosition = +// (recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop(); +// checkSwipeRefreshNull(); +// mSwipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0 ); + + } + }; + + private void checkSwipeRefreshNull() { + if (mSwipeRefreshLayout == null) + throw new IllegalArgumentException("必须调用bindSwipeRefreshLayout(SwipeRefreshLayout)绑定SwipeRefreshLayout,解决冲突!!!"); + } + + //找到数组中的最大值 + private int findMax(int[] lastPositions) { + int max = lastPositions[0]; + for (int value : lastPositions) { + if (value > max) { + max = value; + } + } + return max; + } + + private OnLoadingListener mOnLoadingListener; + + public void setOnLoadingListener(OnLoadingListener onLoadingListener) { + mOnLoadingListener = onLoadingListener; + } + + public interface OnLoadingListener { + void onLoading(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/SystemStatusManager.java b/app/src/main/java/com/yizhuan/erban/base/SystemStatusManager.java new file mode 100644 index 000000000..37cef1431 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/SystemStatusManager.java @@ -0,0 +1,578 @@ +package com.yizhuan.erban.base; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.ActionBar.LayoutParams; +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 java.lang.reflect.Method; + +@SuppressWarnings({ "unchecked", "rawtypes", "ResourceType"}) +public class SystemStatusManager { + static { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + try { + Class c = Class.forName("android.os.SystemProperties"); + 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 SystemStatusManager(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 { + 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; + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/base/TitleBar.java b/app/src/main/java/com/yizhuan/erban/base/TitleBar.java new file mode 100644 index 000000000..d05de63b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/TitleBar.java @@ -0,0 +1,553 @@ +package com.yizhuan.erban.base; + +/** + * Created by zhouxiangfeng on 2017/4/9. + */ + + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + + +import com.yizhuan.erban.R; + +import java.util.LinkedList; + +/** + * 类描述: + * 创建人:Bob + * 创建时间:2015/9/25 11:36 + */ +public class TitleBar extends ViewGroup implements View.OnClickListener { + private static final int DEFAULT_MAIN_TEXT_SIZE = 18; + private static final int DEFAULT_SUB_TEXT_SIZE = 12; + private static final int DEFAULT_ACTION_TEXT_SIZE = 15; + private static final int DEFAULT_TITLE_BAR_HEIGHT = 48; + + private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; + + private TextView mLeftText; + private View mLeftView; + private RelativeLayout mLeftLayout; + private LinearLayout mRightLayout; + private LinearLayout mCenterLayout; + private TextView mCenterText; + private TextView mSubTitleText; + private View mCustomCenterView; + private View mDividerView; + + private boolean mImmersive; + + private int mScreenWidth; + private int mStatusBarHeight; + private int mActionPadding; + private int mOutPadding; + private int mActionTextColor; + private int mHeight; + + private LayoutInflater mInflater; + + public void setCommonBackgroundColor(int mBackgroundColor) { + this.mBackgroundColor = mBackgroundColor; + setBackgroundColor(mBackgroundColor); + } + + private int mBackgroundColor = getResources().getColor(R.color.white); + + public TitleBar(Context context) { + super(context); + init(context); + } + + public TitleBar(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleBarStyle); + mBackgroundColor = a.getColor(R.styleable.TitleBarStyle_mBackgroundColor, mBackgroundColor); + a.recycle(); + init(context); + } + + public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleBarStyle); + mBackgroundColor = a.getColor(R.styleable.TitleBarStyle_mBackgroundColor, mBackgroundColor); + a.recycle(); + init(context); + } + + private void init(Context context) { + mInflater = LayoutInflater.from(context); + mScreenWidth = getResources().getDisplayMetrics().widthPixels; + if (mImmersive) { + mStatusBarHeight = getStatusBarHeight(); + } + mActionPadding = dip2px(5); + mOutPadding = dip2px(10); + mHeight = dip2px(DEFAULT_TITLE_BAR_HEIGHT); + initView(context); + } + + private void initView(Context context) { + + mLeftLayout = new RelativeLayout(context); + mCenterLayout = new LinearLayout(context); + mRightLayout = new LinearLayout(context); + mDividerView = new View(context); + + LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + + mLeftText = new TextView(context); + mLeftText.setTextSize(DEFAULT_ACTION_TEXT_SIZE); + mLeftText.setSingleLine(); + mLeftText.setGravity(Gravity.CENTER_VERTICAL); + mLeftText.setPadding(mOutPadding + mActionPadding, 0, mOutPadding, 0); + setLeftView(mLeftText); + + mCenterText = new TextView(context); + mSubTitleText = new TextView(context); + mCenterLayout.addView(mCenterText); + mCenterLayout.addView(mSubTitleText); + + mCenterLayout.setGravity(Gravity.CENTER); + mCenterText.setTextSize(DEFAULT_MAIN_TEXT_SIZE); + mCenterText.setSingleLine(); + mCenterText.setGravity(Gravity.CENTER); + mCenterText.setEllipsize(TextUtils.TruncateAt.END); + + mSubTitleText.setTextSize(DEFAULT_SUB_TEXT_SIZE); + mSubTitleText.setSingleLine(); + mSubTitleText.setGravity(Gravity.CENTER); + mSubTitleText.setEllipsize(TextUtils.TruncateAt.END); + + mRightLayout.setPadding(mOutPadding, 0, mOutPadding, 0); + + addView(mLeftLayout, layoutParams); + addView(mCenterLayout); + addView(mRightLayout, layoutParams); + addView(mDividerView, new LayoutParams(LayoutParams.MATCH_PARENT, 1)); + + //默认主题色 + setBackgroundColor(mBackgroundColor); + } + + public void setImmersive(boolean immersive) { + mImmersive = immersive; + if (mImmersive) { + mStatusBarHeight = getStatusBarHeight(); + } else { + mStatusBarHeight = 0; + } + } + + public void setHeight(int height) { + mHeight = height; + setMeasuredDimension(getMeasuredWidth(), mHeight); + } + + public int getmHeight() { + return mHeight; + } + + public void setLeftLayout(int leftLayout) { + if (leftLayout > 0) { + setLeftView(mInflater.inflate(leftLayout, null)); + } + } + + public void setLeftView(View leftView) { + if (leftView == null) { + return; + } + if (this.mLeftView != null) { + removeView(this.mLeftView); + } + this.mLeftView = leftView; + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + params.addRule(RelativeLayout.CENTER_VERTICAL); + mLeftLayout.addView(leftView, params); + } + + public void setLeftImageResource(int resId) { +// mLeftText.setBackgroundResource(resId); + mLeftText.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0); + } + + public void setLeftDrawPadding(int padding) { + mLeftText.setCompoundDrawablePadding(padding); + } + + public void setLeftClickListener(OnClickListener l) { + mLeftLayout.setOnClickListener(l); + } + + public void setLeftText(CharSequence title) { + mLeftText.setText(title); + } + + public void setLeftText(int resid) { + mLeftText.setText(resid); + } + + public void setLeftTextSize(float size) { + mLeftText.setTextSize(size); + } + + public void setLeftTextColor(int color) { + mLeftText.setTextColor(color); + } + + public void setLeftVisible(boolean visible) { + mLeftText.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + public void setTitle(CharSequence title) { + int index = title.toString().indexOf("\n"); + if (index > 0) { + setTitle(title.subSequence(0, index), title.subSequence(index + 1, title.length()), LinearLayout.VERTICAL); + } else { + index = title.toString().indexOf("\t"); + if (index > 0) { + setTitle(title.subSequence(0, index), " " + title.subSequence(index + 1, title.length()), LinearLayout.HORIZONTAL); + } else { + mCenterText.setText(title); + mSubTitleText.setVisibility(View.GONE); + } + } + } + + private void setTitle(CharSequence title, CharSequence subTitle, int orientation) { + mCenterLayout.setOrientation(orientation); + mCenterText.setText(title); + + mSubTitleText.setText(subTitle); + mSubTitleText.setVisibility(View.VISIBLE); + } + + public void setCenterClickListener(OnClickListener l) { + mCenterLayout.setOnClickListener(l); + } + + public void setTitle(int resid) { + setTitle(getResources().getString(resid)); + } + + public void setTitleColor(int resid) { + mCenterText.setTextColor(resid); + } + + public void setTitleSize(float size) { + mCenterText.setTextSize(size); + } + + public void setTitleBackground(int resid) { + mCenterText.setBackgroundResource(resid); + } + + public void setSubTitleColor(int resid) { + mSubTitleText.setTextColor(resid); + } + + public void setSubTitleSize(float size) { + mSubTitleText.setTextSize(size); + } + + public void setCustomTitle(View titleView) { + if (titleView == null) { + mCenterText.setVisibility(View.VISIBLE); + if (mCustomCenterView != null) { + mCenterLayout.removeView(mCustomCenterView); + } + + } else { + if (mCustomCenterView != null) { + mCenterLayout.removeView(mCustomCenterView); + } + LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mCustomCenterView = titleView; + mCenterLayout.addView(titleView, layoutParams); + mCenterText.setVisibility(View.GONE); + } + } + + public void setDivider(Drawable drawable) { + mDividerView.setBackgroundDrawable(drawable); + } + + public void setDividerColor(int color) { + mDividerView.setBackgroundColor(color); + } + + public void setDividerHeight(int dividerHeight) { + mDividerView.getLayoutParams().height = dividerHeight; + } + + public void setActionTextColor(int colorResId) { + mActionTextColor = colorResId; + } + + /** + * Function to set a click listener for Title TextView + * + * @param listener the onClickListener + */ + public void setOnTitleClickListener(OnClickListener listener) { + mCenterText.setOnClickListener(listener); + } + + @Override + public void onClick(View view) { + final Object tag = view.getTag(); + if (tag instanceof Action) { + final Action action = (Action) tag; + action.performAction(view); + } + } + + /** + * Adds a list of {@link Action}s. + * + * @param actionList the actions to add + */ + public void addActions(ActionList actionList) { + int actions = actionList.size(); + for (int i = 0; i < actions; i++) { + addAction(actionList.get(i)); + } + } + + /** + * Adds a new {@link Action}. + * + * @param action the action to add + */ + public View addAction(Action action) { + final int index = mRightLayout.getChildCount(); + return addAction(action, index); + } + + /** + * Adds a new {@link Action} at the specified index. + * + * @param action the action to add + * @param index the position at which to add the action + */ + public View addAction(Action action, int index) { + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + View view = inflateAction(action); + mRightLayout.addView(view, index, params); + return view; + } + + /** + * Removes all action views from this action bar + */ + public void removeAllActions() { + mRightLayout.removeAllViews(); + } + + /** + * Remove a action from the action bar. + * + * @param index position of action to remove + */ + public void removeActionAt(int index) { + mRightLayout.removeViewAt(index); + } + + /** + * Remove a action from the action bar. + * + * @param action The action to remove + */ + public void removeAction(Action action) { + int childCount = mRightLayout.getChildCount(); + for (int i = 0; i < childCount; i++) { + View view = mRightLayout.getChildAt(i); + if (view != null) { + final Object tag = view.getTag(); + if (tag instanceof Action && tag.equals(action)) { + mRightLayout.removeView(view); + } + } + } + } + + /** + * Returns the number of actions currently registered with the action bar. + * + * @return action count + */ + public int getActionCount() { + return mRightLayout.getChildCount(); + } + + /** + * Inflates a {@link View} with the given {@link Action}. + * + * @param action the action to inflate + * @return a view + */ + private View inflateAction(Action action) { + View view = null; + if (TextUtils.isEmpty(action.getText())) { + ImageView img = new ImageView(getContext()); + img.setScaleType(ImageView.ScaleType.CENTER); + img.setImageResource(action.getDrawable()); + view = img; + } else { + TextView text = new TextView(getContext()); + text.setGravity(Gravity.CENTER); + text.setText(action.getText()); + text.setTextSize(DEFAULT_ACTION_TEXT_SIZE); + if (mActionTextColor != 0) { + text.setTextColor(mActionTextColor); + } + view = text; + } + + view.setPadding(mActionPadding, 0, mActionPadding, 0); + view.setTag(action); + view.setOnClickListener(this); + return view; + } + + public View getViewByAction(Action action) { + View view = findViewWithTag(action); + return view; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int height; + if (heightMode != MeasureSpec.EXACTLY) { + height = mHeight + mStatusBarHeight; + heightMeasureSpec = MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY); + } else { + height = MeasureSpec.getSize(heightMeasureSpec) + mStatusBarHeight; + } + + measureChild(mLeftLayout, widthMeasureSpec, heightMeasureSpec); + measureChild(mRightLayout, widthMeasureSpec, heightMeasureSpec); + if (mLeftLayout.getMeasuredWidth() > mRightLayout.getMeasuredWidth()) { + mCenterLayout.measure( + MeasureSpec.makeMeasureSpec(mScreenWidth - 2 * mLeftLayout.getMeasuredWidth(), MeasureSpec.EXACTLY) + , heightMeasureSpec); + } else { + mCenterLayout.measure( + MeasureSpec.makeMeasureSpec(mScreenWidth - 2 * mRightLayout.getMeasuredWidth(), MeasureSpec.EXACTLY) + , heightMeasureSpec); + } + measureChild(mDividerView, widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mLeftLayout.layout(0, mStatusBarHeight, mLeftLayout.getMeasuredWidth(), mLeftLayout.getMeasuredHeight() + mStatusBarHeight); + mRightLayout.layout(mScreenWidth - mRightLayout.getMeasuredWidth(), mStatusBarHeight, + mScreenWidth, mRightLayout.getMeasuredHeight() + mStatusBarHeight); + if (mLeftLayout.getMeasuredWidth() > mRightLayout.getMeasuredWidth()) { + mCenterLayout.layout(mLeftLayout.getMeasuredWidth(), mStatusBarHeight, + mScreenWidth - mLeftLayout.getMeasuredWidth(), getMeasuredHeight()); + } else { + mCenterLayout.layout(mRightLayout.getMeasuredWidth(), mStatusBarHeight, + mScreenWidth - mRightLayout.getMeasuredWidth(), getMeasuredHeight()); + } + mDividerView.layout(0, getMeasuredHeight() - mDividerView.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight()); + } + + public static int dip2px(int dpValue) { + final float scale = Resources.getSystem().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + /** + * 计算状态栏高度高度 + * getStatusBarHeight + * + * @return + */ + public static int getStatusBarHeight() { + return getInternalDimensionSize(Resources.getSystem(), STATUS_BAR_HEIGHT_RES_NAME); + } + + private static 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; + } + + + /** + * A {@link LinkedList} that holds a list of {@link Action}s. + */ + @SuppressWarnings("serial") + public static class ActionList extends LinkedList { + } + + /** + * Definition of an action that could be performed, along with a icon to + * show. + */ + public interface Action { + String getText(); + + int getDrawable(); + + void performAction(View view); + } + + public static abstract class ImageAction implements Action { + private int mDrawable; + + public ImageAction(int drawable) { + mDrawable = drawable; + } + + @Override + public int getDrawable() { + return mDrawable; + } + + @Override + public String getText() { + return null; + } + } + + public static abstract class TextAction implements Action { + final private String mText; + + public TextAction(String text) { + mText = text; + } + + @Override + public int getDrawable() { + return 0; + } + + @Override + public String getText() { + return mText; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/XchatGlideModule.java b/app/src/main/java/com/yizhuan/erban/base/XchatGlideModule.java new file mode 100644 index 000000000..15fabd5d0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/XchatGlideModule.java @@ -0,0 +1,105 @@ +package com.yizhuan.erban.base; + +import android.content.Context; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.Registry; +import com.bumptech.glide.load.engine.cache.DiskCache; +import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper; +import com.bumptech.glide.manager.ConnectivityMonitor; +import com.bumptech.glide.manager.ConnectivityMonitorFactory; +import com.bumptech.glide.module.AppGlideModule; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.file.StorageUtils; + +import java.io.File; + +/** + *

应用工程的glide 配置

+ * Created by Administrator on 2017/11/14. + */ +//@GlideModule +public class XchatGlideModule extends AppGlideModule { + private static final String TAG = "NIMGlideModule"; + + private static final int M = 1024 * 1024; + private static final int MAX_DISK_CACHE_SIZE = 256 * M; + private static DiskCache diskCache = null; + + /** + * ************************ Disk Cache ************************ + */ + private static synchronized DiskCache getDiskCache() { + if (diskCache == null) { + diskCache = createDiskCache(); + } + return diskCache; + } + + private static synchronized DiskCache createDiskCache() { + final Context context = NimUIKit.getContext(); + File cacheDir = StorageUtils.getOwnCacheDirectory(context, context.getPackageName() + "/cache/image/"); + if (!cacheDir.exists()) { + cacheDir.mkdirs(); + } + return DiskLruCacheWrapper.get(cacheDir, MAX_DISK_CACHE_SIZE); + } + + /** + * ************************ Memory Cache ************************ + */ + + static void clearMemoryCache(Context context) { + Glide.get(context).clearMemory(); + } + + /** + * ************************ GlideModule override ************************ + */ + @Override + public void applyOptions(Context context, GlideBuilder builder) { + builder.setDiskCache(new DiskCache.Factory() { + @Override + public DiskCache build() { + return getDiskCache(); + } + }); + //广播过多问题,这里不监听链接状态 + builder.setConnectivityMonitorFactory(new MyConnectivityMonitorFactory()); + + LogUtil.i(TAG, "NIMGlideModule apply options"); + } + + @Override + public void registerComponents(Context context, Glide glide, Registry registry) { + super.registerComponents(context, glide, registry); + } + + + public class MyConnectivityMonitorFactory implements ConnectivityMonitorFactory { + public ConnectivityMonitor build(Context context, ConnectivityMonitor.ConnectivityListener listener) { + return new ConnectivityMonitor() { + @Override + public void onStart() { + + } + + @Override + public void onStop() { + + } + + @Override + public void onDestroy() { + + } + }; + } + } + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/component/BaseComponent.java b/app/src/main/java/com/yizhuan/erban/base/component/BaseComponent.java new file mode 100644 index 000000000..e03452402 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/component/BaseComponent.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.base.component; + +import android.content.Intent; +import android.os.Bundle; + +/** + * create by lvzebiao @2019/12/24 + */ +public abstract class BaseComponent implements IComponent { + + @Override + public void onCreate(Bundle savedInstanceState) { + + } + + @Override + public void onResume() { + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + } + + @Override + public void onPause() { + + } + + @Override + public void onDestroy() { + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/component/IComponent.java b/app/src/main/java/com/yizhuan/erban/base/component/IComponent.java new file mode 100644 index 000000000..f405015eb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/component/IComponent.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.base.component; + +import android.content.Intent; +import android.os.Bundle; + +/** + * create by lvzebiao @2019/12/24 + */ +public interface IComponent { + + void onCreate(Bundle savedInstanceState); + + void onResume(); + + void onActivityResult(int requestCode, int resultCode, Intent data); + + void onPause(); + + void onDestroy(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/BaseRecyclerView.java b/app/src/main/java/com/yizhuan/erban/base/list/BaseRecyclerView.java new file mode 100644 index 000000000..6dec883e3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/BaseRecyclerView.java @@ -0,0 +1,343 @@ +package com.yizhuan.erban.base.list; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.AttributeSet; + +import com.trello.rxlifecycle2.LifecycleProvider; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.trello.rxlifecycle2.components.RxActivity; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.trello.rxlifecycle2.components.support.RxFragment; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.SingleTransformer; +import io.reactivex.functions.BiConsumer; + +/** + * 通用的刷新列表控件 + * Created by lvzebiao on 2018/12/13. + */ + +public abstract class BaseRecyclerView extends SwipeRefreshLayout { + + private List
headerList = new ArrayList<>(); + + private RecyclerView recyclerView; + + private Context context; + + private int page; + + private IStatusView statusView; + + private int pageSize; + + public BaseRecyclerView(@NonNull Context context) { + this(context, null); + } + + public BaseRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + recyclerView = new RecyclerView(context); + LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); + addView(recyclerView, params); + page = 1; + loadMoreEnable = true; + statusView = createStatus(); + if (getDefalutPageSize() > 0) { + pageSize = getDefalutPageSize(); + } else { + pageSize = 15; + } + //画间距 + + } + + private WrapperAdapter wrapper; + + public void addHeader(Header header) { + headerList.add(header); + } + + public WrapperAdapter getWrapper() { + return wrapper; + } + + private CommonAdapter mInnerAdapter; + private IRecyclerListener mListener; + private LifecycleProvider mProvider; + + public void setRecyclerListener(final LifecycleProvider provider, final IRecyclerListener listener) { + if (listener == null) { + return; + } + RecyclerView.LayoutManager layoutManager = listener.createLayoutManager(); + final CommonAdapter adapter = listener.createAdapter(context); + this.mInnerAdapter = adapter; + this.mListener = listener; + this.mProvider = provider; + if (layoutManager == null) { + throw new IllegalArgumentException("you must to Override createLayoutManager methor!"); + } + if (adapter == null) { + throw new IllegalArgumentException("you must to Override createAdapter methor!"); + } + + wrapper = new WrapperAdapter(context, adapter, headerList); + if (mSpanSizeLookup != null) { + wrapper.setSpanSizeLookup(mSpanSizeLookup); + } + if (mItemDecoration != null) { + recyclerView.addItemDecoration(mItemDecoration); + } + + wrapper.setReloadListener(new WrapperAdapter.ReloadListener() { + @Override + public void onEmptyClick() { + if (isLoading) { + return; + } + wrapper.clearStatusView(); + noMoreData = false; + page = 1; + loadingData(provider, listener, adapter, true, true); + } + + @Override + public void onNetErrorClick() { + if (isLoading) { + return; + } + wrapper.clearStatusView(); + noMoreData = false; + page = 1; + loadingData(provider, listener, adapter, true, true); + } + }); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(wrapper); + + setOnRefreshListener(() -> { + if (isLoading) { + setRefreshing(false); + return; + } + noMoreData = false; + page = 1; + loadingData(provider, listener, adapter, false, true); + }); + + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView view, int newState) { + super.onScrollStateChanged(view, newState); + if (!loadMoreEnable) { + return; + } + if (isLoading) { + return; + } + if (noMoreData) { + return; + } + if (wrapper.isEmptyOrNetError()) { + return; + } + int itemCount = recyclerView.getAdapter().getItemCount(); + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { + LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager(); + int lastVisiItem = manager.findLastVisibleItemPosition(); + if (lastVisiItem >= itemCount - 2) { + if (loadMoreListener != null) { + loadMoreListener.onLoadMore(); + } + } + } + } + } + }); + + setLoadMoreListener(new LoadMoreListener() { + @Override + public void onLoadMore() { + loadingData(provider, listener, adapter, false, false); + } + }); + + loadingData(provider, listener, adapter, true, true); + + } + + public void onRefreshList() { + page = 1; + if (mInnerAdapter == null || mListener == null) { + return; + } + loadingData(mProvider, mListener, mInnerAdapter, false, true); + } + + private boolean isLoading; + + private boolean loadMoreEnable; + + private boolean noMoreData; + + public void setLoadMoreEnable(boolean enable) { + loadMoreEnable = enable; + } + + private LoadMoreListener loadMoreListener; + + public void setLoadMoreListener(LoadMoreListener listener) { + loadMoreListener = listener; + } + + public interface LoadMoreListener { + void onLoadMore(); + } + + @SuppressLint("CheckResult") + private void loadingData(final LifecycleProvider provider, + final IRecyclerListener listener, + final CommonAdapter adapter, + final boolean startLoading, + final boolean isRefresh) { + isLoading = true; + if (startLoading) { + wrapper.startLoading(statusView.getStartLoadingView()); + } + Single> single = listener.getSingle(page, pageSize); + if (provider != null) { + single = single.compose(bindDestroy(provider)); + } + //noinspection ResultOfMethodCallIgnored + single.subscribe((list, throwable) -> { + setRefreshing(false); + isLoading = false; + if (wrapper.isEmptyOrNetError()) { + wrapper.clearStatusView(); + } + if (startLoading) { + wrapper.startLoadingComplete(); + } + wrapper.loadMoreComplete(); + if (throwable != null) { + if (page == 1 && ListUtils.isListEmpty(adapter.getData())) { + wrapper.setNetError(statusView.getNetErrorView()); + } + } else { + if (page == 1 && list.size() == 0) { + adapter.getData().clear(); + wrapper.setEmpty(statusView.getEmptyView(), listener.getEmptyTips(), listener.getEmptyResId()); + return; + } + if (isRefresh) { + adapter.getData().clear(); + adapter.getData().addAll(list); + wrapper.notifyDataSetChanged(); + } else { + int insertPos = wrapper.getItemCount() - wrapper.getStatusViewCount(); + adapter.getData().addAll(list); + wrapper.notifyItemInserted(insertPos); + } + if (loadMoreEnable) { + if (list.size() == 0) { + noMoreData = true; + } else { + noMoreData = false; + wrapper.setLoadMoreView(statusView.getLoadMoreView()); + recyclerView.post(() -> { + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager instanceof StaggeredGridLayoutManager) { + return; + } + if (manager instanceof LinearLayoutManager) { + int lastCplPos = ((LinearLayoutManager) manager).findLastVisibleItemPosition(); + //加个兼容,只要最后一个可视项是倒数几项,就自动加载第二页 + if (lastCplPos >= wrapper.getItemCount() - 3) { + page++; + loadingData(provider, listener, adapter, false, false); + } else { + page++; + } + } + }); + } + } + + } + }); + } + + /** + * ============================= recyclerview的属性 ================================ + */ + + public RecyclerView getRealRecyclerView() { + return recyclerView; + } + + public void setPageSize(int number) { + this.pageSize = number; + } + + private WrapperAdapter.SpanSizeLookup mSpanSizeLookup; + + public void setSpanSizeLookup(WrapperAdapter.SpanSizeLookup spanSizeLookup) { + this.mSpanSizeLookup = spanSizeLookup; + } + + private RecyclerView.ItemDecoration mItemDecoration; + + public void addItemDecoration(RecyclerView.ItemDecoration itemDecoration) { + this.mItemDecoration = itemDecoration; + } + + public abstract IStatusView createStatus(); + + public abstract int getDefalutPageSize(); + + /** + * ============================= 静态方法 ================================ + */ + + public static SingleTransformer bindDestroy(LifecycleProvider provider) { + return upstream -> { + if (provider == null) { + return upstream; + } + if (provider instanceof RxFragment) { + RxFragment fragment = (RxFragment) provider; + return upstream.compose(fragment.bindUntilEvent(FragmentEvent.DESTROY)); + } else if (provider instanceof RxAppCompatActivity) { + RxAppCompatActivity appCompatActivity = (RxAppCompatActivity) provider; + return upstream.compose(appCompatActivity.bindUntilEvent(ActivityEvent.DESTROY)); + } else if (provider instanceof RxActivity) { + RxActivity activity = (RxActivity) provider; + return upstream.compose(activity.bindUntilEvent(ActivityEvent.DESTROY)); + } else if (provider instanceof com.trello.rxlifecycle2.components.RxFragment) { + com.trello.rxlifecycle2.components.RxFragment fragment = + (com.trello.rxlifecycle2.components.RxFragment) provider; + return upstream.compose(fragment.bindUntilEvent(FragmentEvent.DESTROY)); + } + return upstream; + }; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/BaseViewHolder.java b/app/src/main/java/com/yizhuan/erban/base/list/BaseViewHolder.java new file mode 100644 index 000000000..8a2fb90d0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/BaseViewHolder.java @@ -0,0 +1,507 @@ +/** + * Copyright 2013 Joan Zapata + *

+ * 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.yizhuan.erban.base.list; + +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.DrawableRes; +import android.support.annotation.IdRes; +import android.support.annotation.StringRes; +import android.support.v7.widget.RecyclerView; +import android.text.util.Linkify; +import android.util.SparseArray; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.widget.Adapter; +import android.widget.AdapterView; +import android.widget.Checkable; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RatingBar; +import android.widget.TextView; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + + +/** + * https://github.com/CymChad/BaseRecyclerViewAdapterHelper + */ +public class BaseViewHolder extends RecyclerView.ViewHolder { + + /** + * Views indexed with their IDs + */ + private final SparseArray views; + + public Set getNestViews() { + return nestViews; + } + + private final HashSet nestViews; + + private final LinkedHashSet childClickViewIds; + + private final LinkedHashSet itemChildLongClickViewIds; + private CommonAdapter adapter; + /** + * use itemView instead + */ + @Deprecated + public View convertView; + + /** + * Package private field to retain the associated user object and detect a change + */ + Object associatedObject; + + + public BaseViewHolder(final View view) { + super(view); + this.views = new SparseArray<>(); + this.childClickViewIds = new LinkedHashSet<>(); + this.itemChildLongClickViewIds = new LinkedHashSet<>(); + this.nestViews = new HashSet<>(); + convertView = view; + + + } + + public HashSet getItemChildLongClickViewIds() { + return itemChildLongClickViewIds; + } + + public HashSet getChildClickViewIds() { + return childClickViewIds; + } + + /** + * use itemView instead + * + * @return the ViewHolder root view + */ + @Deprecated + public View getConvertView() { + + return convertView; + } + + /** + * Will set the text of a TextView. + * + * @param viewId The view id. + * @param value The text to put in the text view. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setText(@IdRes int viewId, CharSequence value) { + TextView view = getView(viewId); + view.setText(value); + return this; + } + + public BaseViewHolder setText(@IdRes int viewId, @StringRes int strId) { + TextView view = getView(viewId); + view.setText(strId); + return this; + } + + /** + * Will set the image of an ImageView from a resource id. + * + * @param viewId The view id. + * @param imageResId The image resource id. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setImageResource(@IdRes int viewId, @DrawableRes int imageResId) { + ImageView view = getView(viewId); + view.setImageResource(imageResId); + return this; + } + + /** + * Will set background color of a view. + * + * @param viewId The view id. + * @param color A color, not a resource id. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setBackgroundColor(@IdRes int viewId, @ColorInt int color) { + View view = getView(viewId); + view.setBackgroundColor(color); + return this; + } + + /** + * Will set background of a view. + * + * @param viewId The view id. + * @param backgroundRes A resource to use as a background. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setBackgroundRes(@IdRes int viewId, @DrawableRes int backgroundRes) { + View view = getView(viewId); + view.setBackgroundResource(backgroundRes); + return this; + } + + /** + * Will set text color of a TextView. + * + * @param viewId The view id. + * @param textColor The text color (not a resource id). + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTextColor(@IdRes int viewId, @ColorInt int textColor) { + TextView view = getView(viewId); + view.setTextColor(textColor); + return this; + } + + + /** + * Will set the image of an ImageView from a drawable. + * + * @param viewId The view id. + * @param drawable The image drawable. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setImageDrawable(@IdRes int viewId, Drawable drawable) { + ImageView view = getView(viewId); + view.setImageDrawable(drawable); + return this; + } + + /** + * Add an action to set the image of an image view. Can be called multiple times. + */ + public BaseViewHolder setImageBitmap(@IdRes int viewId, Bitmap bitmap) { + ImageView view = getView(viewId); + view.setImageBitmap(bitmap); + return this; + } + + /** + * Add an action to set the alpha of a view. Can be called multiple times. + * Alpha between 0-1. + */ + public BaseViewHolder setAlpha(@IdRes int viewId, float value) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + getView(viewId).setAlpha(value); + } else { + // Pre-honeycomb hack to set Alpha value + AlphaAnimation alpha = new AlphaAnimation(value, value); + alpha.setDuration(0); + alpha.setFillAfter(true); + getView(viewId).startAnimation(alpha); + } + return this; + } + + /** + * Set a view visibility to VISIBLE (true) or GONE (false). + * + * @param viewId The view id. + * @param visible True for VISIBLE, false for GONE. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setGone(@IdRes int viewId, boolean visible) { + View view = getView(viewId); + view.setVisibility(visible ? View.VISIBLE : View.GONE); + return this; + } + + /** + * Set a view visibility to VISIBLE (true) or INVISIBLE (false). + * + * @param viewId The view id. + * @param visible True for VISIBLE, false for INVISIBLE. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setVisible(@IdRes int viewId, boolean visible) { + View view = getView(viewId); + view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); + return this; + } + + /** + * Add links into a TextView. + * + * @param viewId The id of the TextView to linkify. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder linkify(@IdRes int viewId) { + TextView view = getView(viewId); + Linkify.addLinks(view, Linkify.ALL); + return this; + } + + /** + * Apply the typeface to the given viewId, and enable subpixel rendering. + */ + public BaseViewHolder setTypeface(@IdRes int viewId, Typeface typeface) { + TextView view = getView(viewId); + view.setTypeface(typeface); + view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + return this; + } + + /** + * Apply the typeface to all the given viewIds, and enable subpixel rendering. + */ + public BaseViewHolder setTypeface(Typeface typeface, int... viewIds) { + for (int viewId : viewIds) { + TextView view = getView(viewId); + view.setTypeface(typeface); + view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } + return this; + } + + /** + * Sets the progress of a ProgressBar. + * + * @param viewId The view id. + * @param progress The progress. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setProgress(@IdRes int viewId, int progress) { + ProgressBar view = getView(viewId); + view.setProgress(progress); + return this; + } + + /** + * Sets the progress and max of a ProgressBar. + * + * @param viewId The view id. + * @param progress The progress. + * @param max The max value of a ProgressBar. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setProgress(@IdRes int viewId, int progress, int max) { + ProgressBar view = getView(viewId); + view.setMax(max); + view.setProgress(progress); + return this; + } + + /** + * Sets the range of a ProgressBar to 0...max. + * + * @param viewId The view id. + * @param max The max value of a ProgressBar. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setMax(@IdRes int viewId, int max) { + ProgressBar view = getView(viewId); + view.setMax(max); + return this; + } + + /** + * Sets the rating (the number of stars filled) of a RatingBar. + * + * @param viewId The view id. + * @param rating The rating. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setRating(@IdRes int viewId, float rating) { + RatingBar view = getView(viewId); + view.setRating(rating); + return this; + } + + /** + * Sets the rating (the number of stars filled) and max of a RatingBar. + * + * @param viewId The view id. + * @param rating The rating. + * @param max The range of the RatingBar to 0...max. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setRating(@IdRes int viewId, float rating, int max) { + RatingBar view = getView(viewId); + view.setMax(max); + view.setRating(rating); + return this; + } + + /** + * Sets the on click listener of the view. + * + * @param viewId The view id. + * @param listener The on click listener; + * @return The BaseViewHolder for chaining. + */ + @Deprecated + public BaseViewHolder setOnClickListener(@IdRes int viewId, View.OnClickListener listener) { + View view = getView(viewId); + view.setOnClickListener(listener); + return this; + } + + + /** + * Sets the on touch listener of the view. + * + * @param viewId The view id. + * @param listener The on touch listener; + * @return The BaseViewHolder for chaining. + */ + @Deprecated + public BaseViewHolder setOnTouchListener(@IdRes int viewId, View.OnTouchListener listener) { + View view = getView(viewId); + view.setOnTouchListener(listener); + return this; + } + + /** + * Sets the listview or gridview's item long click listener of the view + * + * @param viewId The view id. + * @param listener The item long click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnItemLongClickListener(@IdRes int viewId, AdapterView.OnItemLongClickListener listener) { + AdapterView view = getView(viewId); + view.setOnItemLongClickListener(listener); + return this; + } + + /** + * Sets the listview or gridview's item selected click listener of the view + * + * @param viewId The view id. + * @param listener The item selected click listener; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnItemSelectedClickListener(@IdRes int viewId, AdapterView.OnItemSelectedListener listener) { + AdapterView view = getView(viewId); + view.setOnItemSelectedListener(listener); + return this; + } + + /** + * Sets the on checked change listener of the view. + * + * @param viewId The view id. + * @param listener The checked change listener of compound button. + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setOnCheckedChangeListener(@IdRes int viewId, CompoundButton.OnCheckedChangeListener listener) { + CompoundButton view = getView(viewId); + view.setOnCheckedChangeListener(listener); + return this; + } + + /** + * Sets the tag of the view. + * + * @param viewId The view id. + * @param tag The tag; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTag(@IdRes int viewId, Object tag) { + View view = getView(viewId); + view.setTag(tag); + return this; + } + + /** + * Sets the tag of the view. + * + * @param viewId The view id. + * @param key The key of tag; + * @param tag The tag; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setTag(@IdRes int viewId, int key, Object tag) { + View view = getView(viewId); + view.setTag(key, tag); + return this; + } + + /** + * Sets the checked status of a checkable. + * + * @param viewId The view id. + * @param checked The checked status; + * @return The BaseViewHolder for chaining. + */ + public BaseViewHolder setChecked(@IdRes int viewId, boolean checked) { + View view = getView(viewId); + // View unable cast to Checkable + if (view instanceof Checkable) { + ((Checkable) view).setChecked(checked); + } + return this; + } + + /** + * Sets the adapter of a adapter view. + * + * @param viewId The view id. + * @param adapter The adapter; + * @return The BaseViewHolder for chaining. + */ + @SuppressWarnings("unchecked") + public BaseViewHolder setAdapter(@IdRes int viewId, Adapter adapter) { + AdapterView view = getView(viewId); + view.setAdapter(adapter); + return this; + } + + /** + * Sets the adapter of a adapter view. + * + * @param adapter The adapter; + * @return The BaseViewHolder for chaining. + */ + protected BaseViewHolder setAdapter(CommonAdapter adapter) { + this.adapter = adapter; + return this; + } + + @SuppressWarnings("unchecked") + public T getView(@IdRes int viewId) { + View view = views.get(viewId); + if (view == null) { + view = itemView.findViewById(viewId); + views.put(viewId, view); + } + return (T) view; + } + + /** + * Retrieves the last converted object on this view. + */ + public Object getAssociatedObject() { + return associatedObject; + } + + /** + * Should be called during convert + */ + public void setAssociatedObject(Object associatedObject) { + this.associatedObject = associatedObject; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/CommonAdapter.java b/app/src/main/java/com/yizhuan/erban/base/list/CommonAdapter.java new file mode 100644 index 000000000..c197b6873 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/CommonAdapter.java @@ -0,0 +1,116 @@ +package com.yizhuan.erban.base.list; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public abstract class CommonAdapter extends RecyclerView.Adapter { + + private int mLayoutId; + + private List mData; + + private OnItemClickListener mOnItemClickListener; + + private OnItemChildClickListener mOnItemChildClickListener; + + private List mClickViewIds = new ArrayList<>(); + + public CommonAdapter setOnItemChildClickListener(OnItemChildClickListener onItemChildClickListener) { + this.mOnItemChildClickListener = onItemChildClickListener; + return this; + } + + public CommonAdapter addChildClickIds(int... viewIds) { + for (int index : viewIds) { + mClickViewIds.add(index); + } + return this; + } + + public CommonAdapter setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.mOnItemClickListener = onItemClickListener; + return this; + } + + public CommonAdapter(int layoutId, List data) { + this.mLayoutId = layoutId; + this.mData = data == null ? new ArrayList() : data; + } + + public CommonAdapter(int layoutId) { + this(layoutId, null); + } + + @Override + public K onCreateViewHolder(ViewGroup parent, int viewType) { + return onCreateDefViewHolder(parent, viewType); + } + + protected K onCreateDefViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(mLayoutId, parent, false); + return createBaseViewHolder(view); + } + + public K createBaseViewHolder(View view) { + K holder = (K) new BaseViewHolder(view); + return holder; + } + + @Override + public void onBindViewHolder(K holder, int position) { + convert(holder, getItem(position)); + convert(holder, getItem(position), position); + bindClick(holder, position); + } + + private void bindClick(final K holder, final int position) { + if (mOnItemClickListener != null) { + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mOnItemClickListener.onItemClick(holder, getItem(position), position); + } + }); + } + if (mOnItemChildClickListener != null) { + for (int viewId : mClickViewIds) { + holder.getView(viewId).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mOnItemChildClickListener.onItemChildClick(holder, v.getId(), + getItem(position), position); + } + }); + } + } + } + + public T getItem(int position) { + return mData.get(position); + } + + @Override + public int getItemCount() { + return mData == null ? 0 : mData.size(); + } + + public List getData() { + return mData; + } + + protected abstract void convert(K holder, T item); + + protected void convert(K holder, T item, int position) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/DefalutStatus.java b/app/src/main/java/com/yizhuan/erban/base/list/DefalutStatus.java new file mode 100644 index 000000000..0429bf86d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/DefalutStatus.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.base.list; + +import com.yizhuan.erban.R; + +/** + * 默认列表状态view + * Created by lvzebiao on 2018/12/14. + */ + +public class DefalutStatus implements IStatusView { + + @Override + public int getStartLoadingView() { + return R.layout.item_default_common_loading_view; + } + + @Override + public int getLoadMoreView() { + return R.layout.item_default_common_load_more_view; + } + + @Override + public int getEmptyView() { + return R.layout.item_default_common_empty_view; + } + + @Override + public int getNetErrorView() { + return R.layout.item_default_common_network_error_view; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/Header.java b/app/src/main/java/com/yizhuan/erban/base/list/Header.java new file mode 100644 index 000000000..3f6c253af --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/Header.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public class Header { + public int layoutId; + public IHeaderHolderListener listener; + + public Header(int layoutId, IHeaderHolderListener listener) { + this.layoutId = layoutId; + this.listener = listener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/IHeaderHolderListener.java b/app/src/main/java/com/yizhuan/erban/base/list/IHeaderHolderListener.java new file mode 100644 index 000000000..27c20a28f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/IHeaderHolderListener.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public interface IHeaderHolderListener { + void onViewHolder(BaseViewHolder holder); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/IRecyclerListener.java b/app/src/main/java/com/yizhuan/erban/base/list/IRecyclerListener.java new file mode 100644 index 000000000..2b83ee061 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/IRecyclerListener.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.base.list; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by lvzebiao on 2018/12/13. + */ + +public interface IRecyclerListener { + + CommonAdapter createAdapter(Context context); + + RecyclerView.LayoutManager createLayoutManager(); + + Single> getSingle(int page, int size); + + default String getEmptyTips() { + return "暂无数据"; + } + + default int getEmptyResId() { + return R.drawable.icon_common_failure; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/IStatusView.java b/app/src/main/java/com/yizhuan/erban/base/list/IStatusView.java new file mode 100644 index 000000000..977cbde89 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/IStatusView.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/14. + */ + +public interface IStatusView { + + int getStartLoadingView(); + + int getLoadMoreView(); + + int getEmptyView(); + + int getNetErrorView(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/LineColorDecoration.java b/app/src/main/java/com/yizhuan/erban/base/list/LineColorDecoration.java new file mode 100644 index 000000000..5ea05168e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/LineColorDecoration.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.base.list; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.xchat_android_library.bindinglist.MultiTypeAdapter; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + + +/** + * 水平带颜色左右padding的分割线 + * Created by lvzebiao on 2018/10/26. + */ + +public class LineColorDecoration extends RecyclerView.ItemDecoration { + + private Context context; + private int startPos; + private Drawable drawable; + private int leftPadding; + private int rightPadding; + + /** + * 1px + */ + private int divider = 1; + /**为ture,则表示需要底部的线*/ + private boolean needBottom; + + public LineColorDecoration(Context context, int startPos, int dividerPx, int color, int leftPadding, int rightPadding, boolean bottom) { + this.context = context; + this.divider = dividerPx; + drawable = new ColorDrawable(context.getResources().getColor(color)); + this.leftPadding = SizeUtils.dp2px(context, leftPadding); + this.rightPadding = SizeUtils.dp2px(context, rightPadding); + this.startPos = startPos; + this.needBottom = bottom; + } + + public LineColorDecoration(Context context, int color, int leftPadding, int rightPadding, boolean bottom) { + this(context, 0, 1, color, leftPadding, rightPadding, bottom); + } + + public LineColorDecoration(Context context, int color, int leftPadding, int rightPadding) { + this(context, 0, 1, color, leftPadding, rightPadding, true); + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int postion = parent.getChildAdapterPosition(view); + int bottom; + if (postion < startPos) { + bottom = 0; + } else if (!needBottom && postion == parent.getAdapter().getItemCount() - 1) { + bottom = 0; + } else { + bottom = divider; + } + outRect.set(0, 0, 0, bottom); + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDraw(c, parent, state); + if (drawable == null) { + return; + } + int left = leftPadding; + int right = parent.getWidth() - rightPadding; + for (int i = 0; i < parent.getChildCount(); i++) { + View childView = parent.getChildAt(i); + RecyclerView.LayoutParams childViewParams = (RecyclerView.LayoutParams) childView.getLayoutParams(); + int position = childViewParams.getViewAdapterPosition(); + if (position < startPos) { + //头不画 + continue; + } else if (!needBottom && position == parent.getAdapter().getItemCount() - 1) { + //尾部不画 + continue; + } + //int traX = (int)(ViewCompat.getTranslationX(childView)); 偏移值,暂时没用到 + //int traY = (int)(ViewCompat.getTranslationY(childView)); + final int top = childView.getTop() + childViewParams.height; + final int bottom = top + divider; + //drawable.setBounds(left + traX, top + traY, right + traX, bottom + traY); + drawable.setBounds(left, top, right, bottom); + drawable.draw(c); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/LoadingViewHolder.java b/app/src/main/java/com/yizhuan/erban/base/list/LoadingViewHolder.java new file mode 100644 index 000000000..98b7f07ef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/LoadingViewHolder.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.base.list; + +import android.view.View; + +/** + * Created by lvzebiao on 2018/12/27. + */ + +public class LoadingViewHolder extends BaseViewHolder { + + public LoadingViewHolder(View view) { + super(view); + } + + public void startAnim() { + + } + + public void stopAnim() { + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/MultiCommonAdapter.java b/app/src/main/java/com/yizhuan/erban/base/list/MultiCommonAdapter.java new file mode 100644 index 000000000..71154f182 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/MultiCommonAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.base.list; + +import android.support.annotation.LayoutRes; +import android.util.SparseIntArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.List; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public abstract class MultiCommonAdapter extends CommonAdapter { + + private SparseIntArray layouts; + + public MultiCommonAdapter(List data) { + super(0, data); + } + + @Override + public int getItemViewType(int position) { + return getItem(position).getItemType(); + } + + @Override + public K onCreateViewHolder(ViewGroup parent, int viewType) { + int layoutId = layouts.get(viewType); + View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); + return createBaseViewHolder(view); + } + + protected void addItemType(int type, @LayoutRes int layoutResId) { + if (layouts == null) { + layouts = new SparseIntArray(); + } + layouts.put(type, layoutResId); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/MultiItemEntity.java b/app/src/main/java/com/yizhuan/erban/base/list/MultiItemEntity.java new file mode 100644 index 000000000..bb3970d63 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/MultiItemEntity.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public interface MultiItemEntity { + int getItemType(); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/OnItemChildClickListener.java b/app/src/main/java/com/yizhuan/erban/base/list/OnItemChildClickListener.java new file mode 100644 index 000000000..49ab74b26 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/OnItemChildClickListener.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public interface OnItemChildClickListener { + void onItemChildClick(K holder, int viewId, T item, int position); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/OnItemClickListener.java b/app/src/main/java/com/yizhuan/erban/base/list/OnItemClickListener.java new file mode 100644 index 000000000..fa38f0667 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/OnItemClickListener.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.base.list; + +/** + * Created by lvzebiao on 2018/12/18. + */ + +public interface OnItemClickListener { + void onItemClick(K holder, T item, int position); +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/RefreshRecyclerView.java b/app/src/main/java/com/yizhuan/erban/base/list/RefreshRecyclerView.java new file mode 100644 index 000000000..b4acb76ac --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/RefreshRecyclerView.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.base.list; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; + +/** + * Created by lvzebiao on 2018/12/28. + */ + +public class RefreshRecyclerView extends BaseRecyclerView { + + public final static int DEFALUT_SIZE = 15; + + public RefreshRecyclerView(@NonNull Context context) { + super(context); + } + + public RefreshRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + public IStatusView createStatus() { + return new DefalutStatus(); + } + + @Override + public int getDefalutPageSize() { + return DEFALUT_SIZE; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/base/list/WrapperAdapter.java b/app/src/main/java/com/yizhuan/erban/base/list/WrapperAdapter.java new file mode 100644 index 000000000..fcef4d477 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/base/list/WrapperAdapter.java @@ -0,0 +1,323 @@ +package com.yizhuan.erban.base.list; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Created by lvzebiao on 2018/12/13. + */ + +public class WrapperAdapter extends RecyclerView.Adapter { + + private final static int VIEW_TYPE_HEADER = -10; + private final static int VIEW_TYPE_LOAD_MORE = -11; + private final static int VIEW_TYPE_NET_ERROR = -12; + private final static int VIEW_TYPE_EMPTY = -13; + private final static int VIEW_TYPE_START_LOADING = -14; + + private boolean mIsEmpty; + private boolean mIsNetError; + private boolean mIsStartLoading; + + private String emptyTips; + + private int emptyResId; + + private int mCurrentHeader = 0; + + private List

mHeaderViews = new ArrayList<>(); + + private List mStatusViews = new ArrayList<>(); + + public int getStatusViewCount() { + return mStatusViews.size(); + } + + public int getHeaderCount() { + return mHeaderViews.size(); + } + + private Integer mLoadMoreView = 0; + + private Integer mEmptyView = 0; + + private Integer mStartLoadingView = 0; + + private Integer mNetErrorView = 0; + + private RecyclerView.Adapter mInnerAdapter; + + private Context mContext; + + public WrapperAdapter(Context context, RecyclerView.Adapter adapter, List
headerViews) { + this.mInnerAdapter = adapter; + this.mHeaderViews = headerViews; + this.mContext = context; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + int layout = 0; + if (viewType == VIEW_TYPE_HEADER) { + View view = LayoutInflater.from(mContext).inflate(mHeaderViews.get(mCurrentHeader).layoutId, parent, false); + return new BaseViewHolder(view); + } + if (viewType == VIEW_TYPE_EMPTY) { + layout = mEmptyView; + } + if (viewType == VIEW_TYPE_NET_ERROR) { + layout = mNetErrorView; + } + if (viewType == VIEW_TYPE_START_LOADING) { + layout = mStartLoadingView; + View view = LayoutInflater.from(mContext).inflate(layout, parent, false); + return new LoadingViewHolder(view); + } + if (viewType == VIEW_TYPE_LOAD_MORE) { + layout = mLoadMoreView; + } + if (layout != 0) { + View view = LayoutInflater.from(mContext).inflate(layout, parent, false); + return new BaseViewHolder(view); + } + return mInnerAdapter.onCreateViewHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (position >= mHeaderViews.size() && position < mInnerAdapter.getItemCount() + mHeaderViews.size()) { + mInnerAdapter.onBindViewHolder(holder, position - mHeaderViews.size()); + } else if (getItemViewType(position) == VIEW_TYPE_HEADER) { + IHeaderHolderListener listener = mHeaderViews.get(position).listener; + if (listener != null) { + listener.onViewHolder((BaseViewHolder) holder); + } + } else if (getItemViewType(position) == VIEW_TYPE_EMPTY) { + holder.itemView.setOnClickListener(v -> { + if (mReloadListener != null) { + mReloadListener.onEmptyClick(); + } + }); + if (holder instanceof BaseViewHolder) { + BaseViewHolder helper = (BaseViewHolder) holder; + View textView = helper.getView(R.id.no_data_text); + if (textView != null && textView instanceof TextView) { + helper.setText(R.id.no_data_text, emptyTips); + } + View imageView = helper.getView(R.id.no_data_icon); + if (imageView != null && imageView instanceof ImageView && emptyResId != 0) { + helper.setImageResource(R.id.no_data_icon, emptyResId); + } + } + } else if (getItemViewType(position) == VIEW_TYPE_NET_ERROR) { + holder.itemView.setOnClickListener(v -> { + if (mReloadListener != null) { + mReloadListener.onNetErrorClick(); + } + }); + } else if (getItemViewType(position) == VIEW_TYPE_START_LOADING) { + if (holder instanceof LoadingViewHolder) { + ((LoadingViewHolder) holder).startAnim(); + } + } else { + holder.itemView.setOnClickListener(null); + } + } + + private ReloadListener mReloadListener; + + public void setReloadListener(ReloadListener reloadListener) { + this.mReloadListener = reloadListener; + } + + public interface ReloadListener { + void onEmptyClick(); + + void onNetErrorClick(); + } + + @Override + public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { + super.onViewDetachedFromWindow(holder); + if (holder instanceof LoadingViewHolder) { + ((LoadingViewHolder) holder).stopAnim(); + } + } + + @Override + public int getItemViewType(int position) { + if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) { + mCurrentHeader = position; + return VIEW_TYPE_HEADER; + } + if (mInnerAdapter.getItemCount() == 0) { + if (mIsEmpty) { + return VIEW_TYPE_EMPTY; + } else if (mIsNetError) { + return VIEW_TYPE_NET_ERROR; + } else { + return VIEW_TYPE_START_LOADING; + } + } + if (position >= mInnerAdapter.getItemCount() + mHeaderViews.size()) { + return VIEW_TYPE_LOAD_MORE; + } + return mInnerAdapter.getItemViewType(position - mHeaderViews.size()); + } + + @Override + public int getItemCount() { + return mHeaderViews.size() + mInnerAdapter.getItemCount() + mStatusViews.size(); + } + + public void setLoadMoreView(int layoutId) { + if (layoutId == 0) { + return; + } + mLoadMoreView = layoutId; + if (!mStatusViews.contains(mLoadMoreView)) { + int insertPos = getItemCount(); + mStatusViews.add(mLoadMoreView); + notifyItemInserted(insertPos); + } + } + + public void loadMoreComplete() { + if (mLoadMoreView <= 0) { + return; + } + if (mStatusViews.contains(mLoadMoreView)) { + int removePos = getItemCount() - 1; + mStatusViews.remove(mLoadMoreView); + notifyItemRemoved(removePos); + } + } + + public void setEmpty(int layoutId, String emptyTips, int emptyResId) { + reset(); + this.mIsEmpty = true; + if (layoutId <= 0) { + return; + } + mEmptyView = layoutId; + this.emptyTips = emptyTips; + this.emptyResId = emptyResId; + if (!mStatusViews.contains(mEmptyView)) { + mStatusViews.add(mEmptyView); + notifyDataSetChanged(); + } + } + + public void setNetError(int layoutId) { + reset(); + this.mIsNetError = true; + if (layoutId <= 0) { + return; + } + mNetErrorView = layoutId; + if (!mStatusViews.contains(mNetErrorView)) { + mStatusViews.add(mNetErrorView); + notifyDataSetChanged(); + } + } + + public void startLoading(int layoutId) { + reset(); + this.mIsStartLoading = true; + if (layoutId <= 0) { + return; + } + mStartLoadingView = layoutId; + if (!mStatusViews.contains(mStartLoadingView)) { + mStatusViews.add(mStartLoadingView); + notifyDataSetChanged(); + } + } + + public void startLoadingComplete() { + reset(); + this.mIsStartLoading = false; + if (mStartLoadingView <= 0) { + return; + } + if (mStatusViews.contains(mStartLoadingView)) { + mStatusViews.remove(mStartLoadingView); + notifyDataSetChanged(); + } + } + + private void reset() { + this.mIsEmpty = false; + this.mIsNetError = false; + this.mIsStartLoading = false; + } + + public void clearStatusView() { + reset(); + if (mStatusViews.size() > 0) { + mStatusViews.clear(); + notifyDataSetChanged(); + } + } + + public boolean isEmptyOrNetError() { + return mIsEmpty || mIsNetError; + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager; + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (isHeader(position) || isFullSpanView(position)) { + return gridLayoutManager.getSpanCount(); + } + if (mSpanSizeLookup != null) { + return mSpanSizeLookup.getSpanSize(gridLayoutManager, position - mHeaderViews.size()); + } else { + return 1; + } + } + }); + } + } + + private boolean isHeader(int position) { + return mHeaderViews.size() > 0 && position < mHeaderViews.size(); + } + + private boolean isFullSpanView(int position) { + int viewType = getItemViewType(position); + return viewType == VIEW_TYPE_LOAD_MORE || + viewType == VIEW_TYPE_EMPTY || + viewType == VIEW_TYPE_START_LOADING || + viewType == VIEW_TYPE_NET_ERROR; + } + + + private SpanSizeLookup mSpanSizeLookup; + + public void setSpanSizeLookup(SpanSizeLookup spanSizeLookup) { + this.mSpanSizeLookup = spanSizeLookup; + } + + public interface SpanSizeLookup { + int getSpanSize(GridLayoutManager gridLayoutManager, int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/BillBaseActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/BillBaseActivity.java new file mode 100644 index 000000000..1cf8461c0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/BillBaseActivity.java @@ -0,0 +1,183 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.databinding.ViewDataBinding; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.jzxiang.pickerview.TimePickerDialog; +import com.jzxiang.pickerview.data.Type; +import com.jzxiang.pickerview.listener.OnDateSetListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + *

账单base activity

+ * + * @author Administrator + * @date 2017/11/6 + */ +public abstract class BillBaseActivity extends BaseBindingActivity + implements OnDateSetListener, View.OnClickListener { + protected BillBaseActivity mActivity; + private TextView mTvDate; + private ImageView mIvSelectorDate; + protected RecyclerView mRecyclerView; + private ImageView mIvTodaySelect; + protected SwipeRefreshLayout mRefreshLayout; + protected BillBaseAdapter adapter; + + protected int mCurrentCounter = Constants.PAGE_START; + protected static final int PAGE_SIZE = Constants.BILL_PAGE_SIZE; + protected TimePickerDialog.Builder mDialogYearMonthDayBuild; + protected long time = System.currentTimeMillis(); + protected List mBillItemEntityList = new ArrayList<>(); + + protected int getLayout() { + return R.layout.activity_bills; + } + + @Override + protected void init() { + mActivity = this; + initView(); + initData(); + setListener(); + } + + protected void initView() { + mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); + mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); + mTvDate = (TextView) findViewById(R.id.tv_date); + mIvTodaySelect = (ImageView) findViewById(R.id.iv_today_select); + mIvSelectorDate = (ImageView) findViewById(R.id.tv_selector_date); + +// mRecyclerView = mBinding.recyclerView; +// mRefreshLayout = mBinding.swipeRefresh; +// mTvDate = mBinding.tvDate; +// mIvTodaySelect = mBinding.ivTodaySelect; +// mIvSelectorDate = mBinding.tvSelectorDate; + } + + protected void initData() { + setDate(System.currentTimeMillis()); + mDialogYearMonthDayBuild = new TimePickerDialog.Builder() + .setType(Type.YEAR_MONTH_DAY) + .setTitleStringId("日期选择") + .setThemeColor(getResources().getColor(R.color.line_background)) + .setWheelItemTextNormalColor(getResources().getColor(R.color + .timetimepicker_default_text_color)) + .setWheelItemTextSelectorColor(getResources().getColor(R.color.black)) + .setCallBack(mActivity); + } + + protected void setDate(long time) { + mTvDate.setText(TimeUtils.getDateTimeString(time, "yyyy-MM-dd")); + } + + protected abstract void loadData(); + + protected void setListener() { + mIvTodaySelect.setOnClickListener(this); + mIvSelectorDate.setOnClickListener(this); + mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mCurrentCounter = Constants.PAGE_START; +// time = System.currentTimeMillis(); + loadData(); + } + }); + } + + @Override + public void showNetworkErr() { + mRefreshLayout.setRefreshing(false); + super.showNetworkErr(); + } + + public void onGetDataError(String error) { + if (mCurrentCounter == Constants.PAGE_START) { + showNetworkErr(); + } else { + adapter.loadMoreFail(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_today_select: + mCurrentCounter = Constants.PAGE_START; + time = System.currentTimeMillis(); + setDate(time); + showLoading(); + loadData(); + break; + case R.id.tv_selector_date: + mDialogYearMonthDayBuild.build().show(getSupportFragmentManager(), "year_month_day"); + break; + default: + } + } + + @Override + public void onDateSet(TimePickerDialog timePickerView, long millseconds) { + this.time = millseconds; + setDate(millseconds); + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + + @Override + public void showNoData(CharSequence charSequence) { + this.showNoData(R.drawable.icon_common_failure, charSequence); + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public View.OnClickListener getLoadListener() { + return v -> { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + }; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDialogYearMonthDayBuild != null) { + mDialogYearMonthDayBuild.setCallBack(null); + mDialogYearMonthDayBuild = null; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftExpendActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftExpendActivity.java new file mode 100644 index 000000000..f0417ee86 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftExpendActivity.java @@ -0,0 +1,178 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.adapter.GiftExpendAdapter; +import com.yizhuan.erban.databinding.ActivityBillsGiftBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.ExpendInfo; +import com.yizhuan.xchat_android_core.bills.bean.ExpendListInfo; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + *

账单礼物支出界面

+ * + * @author Administrator + * @date 2017/11/6 + */ +@ActLayoutRes(R.layout.activity_bills_gift) +public class BillGiftExpendActivity extends BillBaseActivity { +// private GiftExpendAdapter adapter; + private TextView mGoldNum; + + @Override + protected void initView() { + super.initView(); + mGoldNum = (TextView) findViewById(R.id.tv_gold_num); + } + + @Override + protected void initData() { + super.initData(); + initTitleBar(getString(R.string.bill_gift_expend)); + + adapter = new GiftExpendAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(() -> { + mCurrentCounter++; + loadData(); + }, mRecyclerView); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + showLoading(); + onLoadGoldNum(); + loadData(); + } + + private void onLoadGoldNum() { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (null != walletInfo) { + mGoldNum.setText(getString(R.string.bill_gift_gold_num, walletInfo.getGoldNum())); + } + } + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .getGiftExpendBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((expendResult, throwable) -> { + if (throwable != null) { + BillGiftExpendActivity.this.onGetDataError(throwable.getMessage()); + } else if (expendResult != null && expendResult.isSuccess()) { + BillGiftExpendActivity.this.onGetExpendBills(expendResult.getData()); + } else if (expendResult != null) { + BillGiftExpendActivity.this.onGetDataError(expendResult.getError()); + } + }); + } + + public void onGetExpendBills(ExpendListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + List billItemEntities = new ArrayList<>(); + int size = mBillItemEntityList.size(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List expendInfos = map.get(key); + if (ListUtils.isListEmpty(expendInfos)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (ExpendInfo temp : expendInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + //目的是为了比较 + billItemEntity.time = key; + billItemEntity.mGiftExpendInfo = temp; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, "哼,你们不爱我了,一个礼物都没有"); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + +// public void onGetExpendBillsError(String error) { +// if (mCurrentCounter == Constants.PAGE_START) { +// showNetworkErr(); +// } else { +// adapter.loadMoreFail(); +// } +// } + + @Override + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(mActivity, ChargeActivity.class)); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftInComeActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftInComeActivity.java new file mode 100644 index 000000000..2992b9adf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftInComeActivity.java @@ -0,0 +1,204 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.adapter.GiftIncomeAdapter; +import com.yizhuan.erban.databinding.ActivityBillsGiftBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_core.bills.bean.IncomeListInfo; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + *

账单礼物收入界面

+ * + * @author Administrator + * @date 2017/11/7 + */ +@ActLayoutRes(R.layout.activity_bills_gift) +public class BillGiftInComeActivity extends BillBaseActivity { +// private GiftIncomeAdapter adapter; + private TextView mGoldNum; + private ImageView iv_goto_top; + + @Override + protected void init() { + super.init(); + initTitleBar(getString(R.string.bill_gift_income)); + } + + @Override + protected void initView() { + super.initView(); + mGoldNum = (TextView) findViewById(R.id.tv_gold_num); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void initData() { + super.initData(); + adapter = new GiftIncomeAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + + firstLoadDate(); + } + + private void firstLoadDate() { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + onLoadGoldNum(); + loadData(); + } + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .getGiftIncomeBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((incomedResult, throwable) -> { + if (throwable != null) { + onGetDataError(throwable.getMessage()); + } else if (incomedResult != null && incomedResult.isSuccess()) { + onGetIncomeBills(incomedResult.getData()); + } else if (incomedResult != null) { + onGetDataError(incomedResult.getError()); + } + }); + } + + private void onLoadGoldNum() { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (null != walletInfo) { + mGoldNum.setText(getString(R.string.bill_gift_gold_num, walletInfo.getGoldNum())); + } + } + + public void onGetIncomeBills(IncomeListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (IncomeInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mGiftInComeInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, "哼,你们不爱我了,一个礼物都没有"); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + + @Override + public void initTitleBar(String title) { + TitleBar mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(mActivity, ChargeActivity.class)); + } + }); + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + firstLoadDate(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftIncomeGroupActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftIncomeGroupActivity.java new file mode 100644 index 000000000..356a9f195 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/BillGiftIncomeGroupActivity.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.bills.activities; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.fragmemt.GiftIncomeFragment; +import com.yizhuan.erban.bills.fragmemt.GiftOutputFragment; +import com.yizhuan.erban.bills.fragmemt.RadishGiftFragment; +import com.yizhuan.erban.bills.presenter.BillGiftIncomeGroupPresenter; +import com.yizhuan.erban.bills.view.IBillGiftIncomeGroupView; +import com.yizhuan.erban.bills.view.IGiftIncomeView; +import com.yizhuan.erban.bills.view.ISmoothToTopView; +import com.yizhuan.erban.bills.widget.BillGiftIncomeGroupNavigatorAdapter; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; + +import static com.yizhuan.erban.bills.fragmemt.RadishGiftFragment.TYPE_RADISH_EXPAND; +import static com.yizhuan.erban.bills.fragmemt.RadishGiftFragment.TYPE_RADISH_INCOME; + +@CreatePresenter(BillGiftIncomeGroupPresenter.class) +public class BillGiftIncomeGroupActivity extends BaseMvpActivity + implements IBillGiftIncomeGroupView, CommonNavigator.NavigatorSelectedListener { + + public static final byte TYPE_BILL_INCOME = 1; + public static final byte TYPE_BILL_OUTPUT = 2; + private static final String FLAG_TYPE_BILL = "type_bill"; + private byte mType = TYPE_BILL_INCOME; + + private TextView mGoldNum; + private ImageView iv_goto_top; + private ViewPager mViewPager; + + public static void startActivity(Context context, byte type) { + Intent intent = new Intent(context, BillGiftIncomeGroupActivity.class); + intent.putExtra(FLAG_TYPE_BILL, type); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + StatusBarLightModes(true); + setContentView(R.layout.activity_bill_gift_income_group); + + mType = getIntent().getByteExtra(FLAG_TYPE_BILL, TYPE_BILL_INCOME); + + initTitleBar(mType == TYPE_BILL_INCOME ? "礼物收入" : "赠送记录"); + + mGoldNum = findViewById(R.id.tv_gold_num); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(v -> smoothToTop()); + + mViewPager = findViewById(R.id.vp_bill_gift_income_group); + MagicIndicator viewIndicator = findViewById(R.id.mi_bill); + + ArrayList fragments = new ArrayList<>(2); + + if (mType == TYPE_BILL_INCOME) { + fragments.add(GiftIncomeFragment.newInstance()); + fragments.add(RadishGiftFragment.newInstance(TYPE_RADISH_INCOME)); + } else { + fragments.add(GiftOutputFragment.newInstance()); + fragments.add(RadishGiftFragment.newInstance(TYPE_RADISH_EXPAND)); + } + mViewPager.setAdapter(new RoomContributeListAdapter(getSupportFragmentManager(), fragments)); + + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + commonNavigator.setmNavigatorSelectedListener(this); + + BillGiftIncomeGroupNavigatorAdapter indicator = new BillGiftIncomeGroupNavigatorAdapter(); + indicator.setOnItemSelectListener(position -> mViewPager.setCurrentItem(position)); + commonNavigator.setAdapter(indicator); + viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(viewIndicator, mViewPager); + } + + private void smoothToTop() { + try { + + if (mViewPager != null) { + int position = mViewPager.getCurrentItem(); + RoomContributeListAdapter roomConsumeListAdapter = (RoomContributeListAdapter) mViewPager.getAdapter(); + + if (roomConsumeListAdapter != null) { + ISmoothToTopView iSmoothToTopView = (ISmoothToTopView) roomConsumeListAdapter.getItem(position); + + if (iSmoothToTopView != null) + iSmoothToTopView.smoothScrollToTop(); + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void showRightOption(boolean show) { + if (mTitleBar.getActionCount() > 0) + mTitleBar.removeActionAt(0); + + if (show) { + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(BillGiftIncomeGroupActivity.this, ChargeActivity.class)); + } + }); + } + + } + + @Override + public void navigatorSelected(int position) { + showRightOption(position == 0); // 金币礼物显示充值按钮 + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/BillNobleActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/BillNobleActivity.java new file mode 100644 index 000000000..2f17ab9fb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/BillNobleActivity.java @@ -0,0 +1,155 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.NobleBillAdapter; +import com.yizhuan.erban.databinding.ActivityBillsBinding; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.NobleBillListInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + *

贵族开通记录

+ * + * @author jiahui + * @date 2018/1/10 + */ +@ActLayoutRes(R.layout.activity_bills) +public class BillNobleActivity extends BillBaseActivity { + private NobleBillAdapter mNobleBillAdapter; + + private ImageView iv_goto_top; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initTitleBar(getString(R.string.bill_noble_open)); + } + + @Override + protected void initView() { + super.initView(); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void initData() { + super.initData(); + mNobleBillAdapter = new NobleBillAdapter(mBillItemEntityList); + mNobleBillAdapter.setOnLoadMoreListener(() -> { + mCurrentCounter++; + loadData(); + }, mRecyclerView); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(mNobleBillAdapter); + showLoading(); + loadData(); + } + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .loadNobleBillRecords(time, mCurrentCounter) + .compose(bindToLifecycle()) + .subscribe((nobleBillListInfo, throwable) -> { + if (throwable != null) { + onGetDataError(throwable.getMessage()); + } else { + onLoadNobleRecordSuccess(nobleBillListInfo); + } + }); + + } + +// public void onLoadNobleRecordFail() { +// if (mCurrentCounter == Constants.PAGE_START) { +// showNetworkErr(); +// } else { +// mNobleBillAdapter.loadMoreFail(); +// } +// } + + public void onLoadNobleRecordSuccess(NobleBillListInfo nobleBillListInfo) { + mRefreshLayout.setRefreshing(false); + if (null != nobleBillListInfo) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + mNobleBillAdapter.setNewData(mBillItemEntityList); + } else { + mNobleBillAdapter.loadMoreComplete(); + } + + List>> billList = nobleBillListInfo.billList; + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List nobleBillInfoList = map.get(key); + if (ListUtils.isListEmpty(nobleBillInfoList)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = (BillItemEntity) mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (NobleBillListInfo.NobleBillInfo temp : nobleBillInfoList) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.nobleBillInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + mNobleBillAdapter.setEnableLoadMore(false); + } + mNobleBillAdapter.addData(billItemEntities); + } else { + if (mCurrentCounter == 1) { + showNoData(R.drawable.icon_common_failure, getResources().getString(R.string.bill_no_data_text)); + } else { + mNobleBillAdapter.loadMoreEnd(true); + } + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/ChargeBillsActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/ChargeBillsActivity.java new file mode 100644 index 000000000..48c355bb0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/ChargeBillsActivity.java @@ -0,0 +1,189 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.adapter.ChargeBillsAdapter; +import com.yizhuan.erban.databinding.ActivityBillsBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.ExpendInfo; +import com.yizhuan.xchat_android_core.bills.bean.ExpendListInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 充值记录 + */ +@ActLayoutRes(R.layout.activity_bills) +public class ChargeBillsActivity extends BillBaseActivity { + private TitleBar mTitleBar; +// private ChargeBillsAdapter adapter; + + private ImageView iv_goto_top; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initTitleBar("充值记录"); + } + + @Override + protected void initView() { + super.initView(); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void initData() { + super.initData(); + adapter = new ChargeBillsAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + adapter.addFooterView(View.inflate(context, R.layout.layout_bills_bottom, null)); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + showLoading(); + loadData(); + } + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .getChargeBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((chargeResult, throwable) -> { + if (throwable != null) { + onGetDataError(throwable.getMessage()); + } else if (chargeResult != null && chargeResult.isSuccess()) { + onGetChargeBills(chargeResult.getData()); + } else if (chargeResult != null) { + onGetDataError(chargeResult.getError()); + } + }); + } + + public void onGetChargeBills(ExpendListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + + BillItemEntity billItemEntity; + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List expendInfos = map.get(key); + if (ListUtils.isListEmpty(expendInfos)) { + continue; + } + //标题 + if (size > 0) { + BillItemEntity lastBillItem = (BillItemEntity) mBillItemEntityList.get(size - 1); + if (!TextUtils.equals(lastBillItem.time, key)) { //时间不一致才会添加标题 + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (ExpendInfo temp : expendInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mChargeExpendInfo = temp; + billItemEntity.time = key; //目的是为了比较 + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, XChatConstants.EMPTY_RECORD_AND_THREE_MONTHS_TIPSS); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + + + @Override + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(mActivity, ChargeActivity.class)); + } + }); + } + +// public void onGetChargeBillsError(String error) { +// if (mCurrentCounter == Constants.PAGE_START) { +// showNetworkErr(); +// } else { +// adapter.loadMoreFail(); +// } +// } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/ChatBillsActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/ChatBillsActivity.java new file mode 100644 index 000000000..849dcbc32 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/ChatBillsActivity.java @@ -0,0 +1,162 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.ChatBillsAdapter; +import com.yizhuan.erban.databinding.ActivityBillsBinding; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_core.bills.bean.IncomeListInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 竞拍记录 + * + * @author Administrator + */ +@ActLayoutRes(R.layout.activity_bills) +public class ChatBillsActivity extends BillBaseActivity { +// private ChatBillsAdapter adapter; + + private ImageView iv_goto_top; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initTitleBar(getString(R.string.menu_my_auction)); + } + + @Override + protected void initView() { + super.initView(); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void initData() { + super.initData(); + adapter = new ChatBillsAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + showLoading(); + loadData(); + } + + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .getChatBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((incomedResult, throwable) -> { + if (throwable != null) { + onGetDataError(throwable.getMessage()); + } else if (incomedResult != null && incomedResult.isSuccess()) { + onGetOrderIncomeBills(incomedResult.getData()); + } else if (incomedResult != null) { + onGetDataError(incomedResult.getError()); + } + }); + } + + public void onGetOrderIncomeBills(IncomeListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (IncomeInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mChatInComeInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == 1) { + showNoData(getResources().getString(R.string.bill_no_data_text)); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + +// public void onGetOrderIncomeBillsError(String error) { +// if (mCurrentCounter == Constants.PAGE_START) { +// showNetworkErr(); +// } else { +// adapter.loadMoreFail(); +// } +// } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/RedBagBillsActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/RedBagBillsActivity.java new file mode 100644 index 000000000..242433c9b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/RedBagBillsActivity.java @@ -0,0 +1,176 @@ +package com.yizhuan.erban.bills.activities; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.adapter.RedBagBillsAdapter; +import com.yizhuan.erban.databinding.ActivityBillsBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RedBagInfo; +import com.yizhuan.xchat_android_core.bills.bean.RedBagListInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 红包记录 + * + * @author Administrator + */ +@ActLayoutRes(R.layout.activity_bills) +public class RedBagBillsActivity extends BillBaseActivity { + +// private RedBagBillsAdapter adapter; + + private ImageView iv_goto_top; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initTitleBar(getString(R.string.bill_red)); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = mBinding.titleBar; + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.icon_user_back_black); + mTitleBar.setLeftClickListener(v -> finish()); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(RedBagBillsActivity.this, ChargeActivity.class)); + } + }); + } + + @Override + protected void initView() { + super.initView(); + iv_goto_top = findViewById(R.id.iv_goto_top); + iv_goto_top.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void initData() { + super.initData(); + adapter = new RedBagBillsAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(() -> { + mCurrentCounter++; + loadData(); + }, mRecyclerView); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mActivity); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + showLoading(); + loadData(); + } + + @SuppressLint("CheckResult") + @Override + protected void loadData() { + BillModel.get() + .getRedBagBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((redBagResult, throwable) -> { + if (throwable != null) { + onGetDataError(throwable.getMessage()); + } else if (redBagResult != null && redBagResult.isSuccess()) { + onGetRedBagBills(redBagResult.getData()); + } else if (redBagResult != null) { + onGetDataError(redBagResult.getError()); + } + }); + } + + public void onGetRedBagBills(RedBagListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + BillItemEntity billItemEntity; + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List redBagInfos = map.get(key); + if (ListUtils.isListEmpty(redBagInfos)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + if (!TextUtils.equals(lastBillItem.time, key)) { //时间不一致才会添加标题 + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (RedBagInfo temp : redBagInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mRedBagInfo = temp; + billItemEntity.time = key; //目的是为了比较 + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == 1) { + showNoData("亲爱的宝贝,你还没有红包记录哦!"); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + +// public void onGetRedBagBillsError(String error) { +// if (mCurrentCounter == Constants.PAGE_START) { +// showNetworkErr(); +// } else { +// adapter.loadMoreFail(); +// } +// } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/TotalBillsActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/TotalBillsActivity.java new file mode 100644 index 000000000..98854da58 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/TotalBillsActivity.java @@ -0,0 +1,86 @@ +package com.yizhuan.erban.bills.activities; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.bills.widget.BillItemView; + +/** + * @author Administrator + */ +public class TotalBillsActivity extends BaseActivity implements View.OnClickListener { + private BillItemView mBillGiftInCome, mBillGiftExpend; + private BillItemView mBillChat; + private BillItemView mBillCharge; + private BillItemView mBillWithdraw; + private BillItemView mBillRed; + private BillItemView mBillNoble; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_total_bills); + initTitleBar(getString(R.string.bill_title)); + initView(); + initData(); + setListener(); + } + + private void initView() { + mBillGiftInCome = (BillItemView) findViewById(R.id.bill_item_income); + mBillGiftExpend = (BillItemView) findViewById(R.id.bill_item_expend); + mBillChat = (BillItemView) findViewById(R.id.bill_item_chat); + mBillCharge = (BillItemView) findViewById(R.id.bill_item_charge); + mBillWithdraw = (BillItemView) findViewById(R.id.bill_item_withdraw); + mBillRed = (BillItemView) findViewById(R.id.bill_item_red); + mBillNoble = (BillItemView) findViewById(R.id.bill_item_noble); + } + + private void initData() { + + } + + + private void setListener() { + mBillGiftInCome.setOnClickListener(this); + mBillGiftExpend.setOnClickListener(this); + mBillChat.setOnClickListener(this); + mBillCharge.setOnClickListener(this); + mBillWithdraw.setOnClickListener(this); + mBillRed.setOnClickListener(this); + mBillNoble.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.bill_item_income: +// startActivity(new Intent(this, BillGiftInComeActivity.class)); + BillGiftIncomeGroupActivity.startActivity(this, BillGiftIncomeGroupActivity.TYPE_BILL_INCOME); + break; + case R.id.bill_item_expend: +// startActivity(new Intent(this, BillGiftExpendActivity.class)); + BillGiftIncomeGroupActivity.startActivity(this, BillGiftIncomeGroupActivity.TYPE_BILL_OUTPUT); + break; + case R.id.bill_item_chat: + startActivity(new Intent(this, ChatBillsActivity.class)); + break; + case R.id.bill_item_charge: + startActivity(new Intent(this, ChargeBillsActivity.class)); + break; + case R.id.bill_item_withdraw: + startActivity(new Intent(this, WithdrawBillsActivity.class)); + break; + case R.id.bill_item_red: + startActivity(new Intent(this, RedBagBillsActivity.class)); + break; + case R.id.bill_item_noble: + startActivity(new Intent(this, BillNobleActivity.class)); + break; + default: + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/activities/WithdrawBillsActivity.java b/app/src/main/java/com/yizhuan/erban/bills/activities/WithdrawBillsActivity.java new file mode 100644 index 000000000..2288c804e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/activities/WithdrawBillsActivity.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.bills.activities; + +import android.content.Intent; +import android.util.SparseLongArray; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.jzxiang.pickerview.TimePickerDialog; +import com.jzxiang.pickerview.data.Type; +import com.jzxiang.pickerview.listener.OnDateSetListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.event.DateInfoEvent; +import com.yizhuan.erban.bills.event.TopEvent; +import com.yizhuan.erban.bills.fragmemt.WithdrawBillsFragment; +import com.yizhuan.erban.databinding.ActivityWithdrawBillsBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import org.greenrobot.eventbus.EventBus; + +/** + * 提现账单记录 + */ +@ActLayoutRes(R.layout.activity_withdraw_bills) +public class WithdrawBillsActivity extends BaseBindingActivity + implements View.OnClickListener, OnDateSetListener { + + private TitleBar mTitleBar; + private FrameLayout fragmentContainer; + + private TextView mTvDay; + private ImageView mIvToday, mIvDay; + private ImageView iv_goto_top; + // private TimePickerDialog mDialogYearMonthDay; + private TimePickerDialog.Builder mDialogYearMonthDayBuild; + private int mPosition; + private long time = System.currentTimeMillis(); + private SparseLongArray mTodayMap = new SparseLongArray(2); + + @Override + protected void init() { + initView(); + initData(); + setListener(); + } + + private void initView() { + fragmentContainer = (FrameLayout) findViewById(R.id.fragment_container); + mTvDay = (TextView) findViewById(R.id.tv_date); + mIvToday = (ImageView) findViewById(R.id.iv_today_select); + mIvDay = (ImageView) findViewById(R.id.tv_selector_date); + iv_goto_top = findViewById(R.id.iv_goto_top); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = mBinding.titleBar; + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.icon_user_back_black); + mTitleBar.setLeftClickListener(v -> finish()); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("充值") { + @Override + public void performAction(View view) { + startActivity(new Intent(WithdrawBillsActivity.this, ChargeActivity.class)); + } + }); + } + + private void initData() { + initTitleBar(getString(R.string.bill_withdraw)); + WithdrawBillsFragment withdrawBillsFragment = new WithdrawBillsFragment(); + getSupportFragmentManager().beginTransaction() + .add(R.id.fragment_container, withdrawBillsFragment, withdrawBillsFragment.getClass().getName()) + .commit(); + //初始化时间 + mTodayMap.put(0, time); + mTodayMap.put(1, time); + setDate(); + mDialogYearMonthDayBuild = new TimePickerDialog.Builder() + .setType(Type.YEAR_MONTH_DAY) + .setTitleStringId("日期选择") + .setThemeColor(getResources().getColor(R.color.line_background)) + .setWheelItemTextNormalColor(getResources().getColor(R.color + .timetimepicker_default_text_color)) + .setWheelItemTextSelectorColor(getResources().getColor(R.color.black)) + .setCallBack(this) + ; + } + + + private void setListener() { + mIvDay.setOnClickListener(this); + mIvToday.setOnClickListener(this); + iv_goto_top.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_today_select: + time = System.currentTimeMillis(); + mTodayMap.put(mPosition, time); + setDate(); + EventBus.getDefault().post(new DateInfoEvent(time, mPosition)); + break; + case R.id.tv_selector_date: + mDialogYearMonthDayBuild.build().show(getSupportFragmentManager(), "year_month_day"); + break; + case R.id.iv_goto_top: + EventBus.getDefault().post(new TopEvent(mPosition)); + break; + default: + } + } + + + private void setDate() { + mTvDay.setText(TimeUtils.getDateTimeString(mTodayMap.get(mPosition), "yyyy-MM-dd")); + } + + @Override + public void onDateSet(TimePickerDialog timePickerView, long millseconds) { + this.time = millseconds; + mTodayMap.put(mPosition, time); + setDate(); + EventBus.getDefault().post(new DateInfoEvent(millseconds, mPosition)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDialogYearMonthDayBuild != null) { + mDialogYearMonthDayBuild.setCallBack(null); + mDialogYearMonthDayBuild = null; + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/BillBaseAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/BillBaseAdapter.java new file mode 100644 index 000000000..b862349ae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/BillBaseAdapter.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + *

账单adapter base

+ * Created by Administrator on 2017/11/6. + */ +public abstract class BillBaseAdapter extends BaseMultiItemQuickAdapter { + + public BillBaseAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_DATE, R.layout.list_income_gift_title); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + if (billItemEntity == null) { + return; + } + switch (billItemEntity.getItemType()) { + case BillItemEntity.ITEM_DATE: + baseViewHolder.setText(R.id.tv_date, + TimeUtils.getDateTimeString(Long.parseLong(billItemEntity.time), "yyyy-MM-dd")); + break; + case BillItemEntity.ITEM_NORMAL: + convertNormal(baseViewHolder, billItemEntity); + break; + default: + } + } + + public abstract void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/ChargeBillsAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/ChargeBillsAdapter.java new file mode 100644 index 000000000..5433287f9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/ChargeBillsAdapter.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.ExpendInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * 充值记录 ExpendInfo + * Created by ${Seven} on 2017/9/15. + */ +public class ChargeBillsAdapter extends BillBaseAdapter { + + public ChargeBillsAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_charge_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + ExpendInfo expendInfo = billItemEntity.mChargeExpendInfo; + if (expendInfo == null) { + return; + } + baseViewHolder.setText(R.id.tv_gold, "充值" + expendInfo.getGoldNum() + "金币") + .setText(R.id.tv_money, expendInfo.getShowStr()) + .setText(R.id.tv_charge_time, TimeUtils.getYearMonthDayHourMinuteSecond(expendInfo.getRecordTime())); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/ChatBillsAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/ChatBillsAdapter.java new file mode 100644 index 000000000..e5b8c0b71 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/ChatBillsAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * IncomeInfo + * Created by Seven on 2017/9/18. + */ +public class ChatBillsAdapter extends BillBaseAdapter { + + public ChatBillsAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_order_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + IncomeInfo incomeInfo = billItemEntity.mChatInComeInfo; + if (incomeInfo == null) return; + baseViewHolder.setVisible(R.id.rly_gold, true) + .setText(R.id.tv_user_pro, incomeInfo.getTargetNick() + "&" + incomeInfo.getUserNick()) + .setText(R.id.tv_date, TimeUtils.getYearMonthDayHourMinuteSecond(incomeInfo.getRecordTime())) + .setText(R.id.tv_gold, incomeInfo.getGoldNum() != 0 + ? String.valueOf(incomeInfo.getGoldNum()) : "+" + incomeInfo.getDiamondNum()) + .setText(R.id.tv_bill_type, incomeInfo.getGoldNum() != 0 + ? mContext.getString(R.string.gift_expend_gold) : mContext.getString(R.string.gift_income_gold)); + + CircleImageView userAvatar = baseViewHolder.getView(R.id.user_avatar); + CircleImageView proAvatar = baseViewHolder.getView(R.id.pro_avatar); + ImageLoadUtils.loadAvatar(mContext, incomeInfo.getUserAvatar(), userAvatar); + ImageLoadUtils.loadAvatar(mContext, incomeInfo.getTargetAvatar(), proAvatar); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftExpendAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftExpendAdapter.java new file mode 100644 index 000000000..485fc20dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftExpendAdapter.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.bills.adapter; + +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.ExpendInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * ExpendInfo + * Created by Seven on 2017/9/10. + */ +public class GiftExpendAdapter extends BillBaseAdapter { + + public GiftExpendAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_expend_gift_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + ExpendInfo expendInfo = billItemEntity.mGiftExpendInfo; + if (expendInfo == null) return; + baseViewHolder.setText(R.id.tv_gift_income, + mContext.getString(R.string.gift_out_gold_number_format, expendInfo.getGoldNum())) + .setText(R.id.tv_send_name, "收礼人 " + expendInfo.getTargetNick()) + .setText(R.id.tv_user_name, expendInfo.getGiftName()) + .setText(R.id.gift_date, TimeUtils.getDateTimeString(expendInfo.getRecordTime(), "HH:mm:ss")) + .setText(R.id.gold, R.string.gift_expend_gold); + + ImageView img_avatar = baseViewHolder.getView(R.id.img_avatar); + ImageLoadUtils.loadImage(mContext, expendInfo.getGiftPic(), img_avatar); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftIncomeAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftIncomeAdapter.java new file mode 100644 index 000000000..f0ae06e6d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/GiftIncomeAdapter.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.bills.adapter; + +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * Created by Seven on 2017/9/11. + */ + +public class GiftIncomeAdapter extends BillBaseAdapter { + + public GiftIncomeAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_expend_gift_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + IncomeInfo incomeInfo = billItemEntity.mGiftInComeInfo; + if (incomeInfo == null) return; + baseViewHolder.setText(R.id.tv_gift_income, + mContext.getString(R.string.gift_in_gold_number_format, incomeInfo.getDiamondNum())) + .setText(R.id.tv_send_name, "送礼人 " + incomeInfo.getTargetNick()) + .setText(R.id.tv_user_name, incomeInfo.getGiftName()) + .setText(R.id.gift_date, TimeUtils.getDateTimeString(incomeInfo.getRecordTime(), "HH:mm:ss")) + .setText(R.id.gold, R.string.gift_income_gold); + ImageView avatar = baseViewHolder.getView(R.id.img_avatar); + ImageLoadUtils.loadImage(mContext, incomeInfo.getGiftPic(), avatar); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/NobleBillAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/NobleBillAdapter.java new file mode 100644 index 000000000..131058427 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/NobleBillAdapter.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.NobleBillListInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2018/1/18 + */ +public class NobleBillAdapter extends BillBaseAdapter { + public NobleBillAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_charge_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + NobleBillListInfo.NobleBillInfo nobleBillInfo = billItemEntity.nobleBillInfo; + if (nobleBillInfo == null) return; + baseViewHolder.setText(R.id.tv_gold, nobleBillInfo.getOptStr()) + .setText(R.id.tv_money, nobleBillInfo.getPayStr()) + .setText(R.id.tv_charge_time, TimeUtils.getYearMonthDayHourMinuteSecond(nobleBillInfo.getRecordTime())); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/RadishGiftAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/RadishGiftAdapter.java new file mode 100644 index 000000000..76285ea15 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/RadishGiftAdapter.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.bills.adapter; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.fragmemt.RadishGiftFragment; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RadishGiftInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +public class RadishGiftAdapter extends BillBaseAdapter{ + private byte mType; + + public RadishGiftAdapter(List billItemEntityList, byte type) { + super(billItemEntityList); + mType = type; + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_expend_gift_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + + RadishGiftInfo radishGiftInfo = billItemEntity.mRadishGiftInfo; + if (radishGiftInfo == null) return; + + baseViewHolder.setText(R.id.tv_send_name, radishGiftInfo.getDescribeStr()) + .setText(R.id.tv_user_name, radishGiftInfo.getGiftName()) + .setText(R.id.gift_date, TimeUtils.getDateTimeString(radishGiftInfo.getCreateTime(), "HH:mm:ss")); + + // 价格/数量 + int incomeColor = ContextCompat.getColor(mContext, R.color.appColor); + int outputColor = ContextCompat.getColor(mContext, R.color.color_333333); + baseViewHolder.setTextColor(R.id.tv_gift_income, mType == RadishGiftFragment.TYPE_RADISH_INCOME ? incomeColor : outputColor) + .setText(R.id.tv_gift_income, mType == RadishGiftFragment.TYPE_RADISH_INCOME ? "x" + radishGiftInfo.getGiftNum() : radishGiftInfo.getAmountStr()) + .setText(R.id.gold, mType == RadishGiftFragment.TYPE_RADISH_INCOME ? "" : radishGiftInfo.getCurrencyStr()); + + ImageView avatar = baseViewHolder.getView(R.id.img_avatar); + ImageLoadUtils.loadImage(mContext, radishGiftInfo.getGiftPicUrl(), avatar); + } +} + diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/RedBagBillsAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/RedBagBillsAdapter.java new file mode 100644 index 000000000..7c18be716 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/RedBagBillsAdapter.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RedBagInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * 红包记录 RedBagInfo + * Created by ${Seven} on 2017/9/25. + */ +public class RedBagBillsAdapter extends BillBaseAdapter { + public RedBagBillsAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_charge_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + RedBagInfo redBagInfo = billItemEntity.mRedBagInfo; + if (redBagInfo == null) return; + baseViewHolder.setText(R.id.tv_gold, redBagInfo.getTypeStr()) + .setText(R.id.tv_money, "+" + redBagInfo.getPacketNum() + "元") + .setText(R.id.tv_charge_time, TimeUtils.getYearMonthDayHourMinuteSecond(redBagInfo.getCreateTime())); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsAdapter.java new file mode 100644 index 000000000..414de613f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsAdapter.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * IncomeInfo + * Created by Seven on 2017/9/17. + */ + +public class WithdrawBillsAdapter extends BillBaseAdapter { + + public WithdrawBillsAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_withdraw_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + IncomeInfo incomeInfo = billItemEntity.mWithdrawInfo; + if (incomeInfo == null) return; + baseViewHolder.setText(R.id.tv_date, TimeUtils.getYearMonthDayHourMinuteSecond(incomeInfo.getRecordTime())) + .setText(R.id.tv_diamondNum, "提现" + incomeInfo.getDiamondNum() + "钻石") + .setText(R.id.tv_money, "+" + incomeInfo.getMoney() + "元"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsIndicatorAdapter.java new file mode 100644 index 000000000..cbf21490d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawBillsIndicatorAdapter.java @@ -0,0 +1,102 @@ +package com.yizhuan.erban.bills.adapter; + +import android.content.Context; +import android.support.v7.widget.AppCompatTextView; +import android.view.Gravity; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public class WithdrawBillsIndicatorAdapter extends CommonNavigatorAdapter { + private List mTitleList; + private Context mContext; + + public WithdrawBillsIndicatorAdapter(Context mContext, List mTitleList) { + this.mTitleList = mTitleList; + this.mContext = mContext; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + WithdrawBillsPagerTitleView categoryPagerTitleView = new WithdrawBillsPagerTitleView(context, mTitleList.get(index)); + categoryPagerTitleView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mOnItemSelectListener) { + mOnItemSelectListener.onItemSelect(index); + } + } + }); + return categoryPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } + + class WithdrawBillsPagerTitleView extends AppCompatTextView implements IPagerTitleView { + + + public WithdrawBillsPagerTitleView(Context context, String tabInfo) { + super(context); + setWidth(Utils.dip2px(getContext(), 96)); + setHeight(Utils.dip2px(getContext(), 30)); + setTextSize(15); + setText(tabInfo); + setGravity(Gravity.CENTER); + + } + + + @Override + public void onSelected(int index, int totalCount) { + setBackgroundResource(R.drawable.shape_bg_contact_indicator_item); + setTextColor(getResources().getColor(R.color.appColor)); + } + + @Override + public void onDeselected(int index, int totalCount) { + setBackgroundDrawable(null); + setTextColor(getResources().getColor(R.color.color_999999)); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawRedBillsAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawRedBillsAdapter.java new file mode 100644 index 000000000..bee37a615 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/adapter/WithdrawRedBillsAdapter.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.bills.adapter; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RedBagInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +/** + * 红包提现账单adapter RedBagInfo + * Created by Seven on 2017/9/17. + */ +public class WithdrawRedBillsAdapter extends BillBaseAdapter { + + + public WithdrawRedBillsAdapter(List billItemEntityList) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.list_withdraw_bills_item); + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + RedBagInfo redBagInfo = billItemEntity.mRedBagInfo; + if (redBagInfo == null) return; + baseViewHolder.setText(R.id.tv_diamondNum, "提现" + redBagInfo.getPacketNum() + "金币") + .setText(R.id.tv_date, TimeUtils.getYearMonthDayHourMinuteSecond(redBagInfo.getCreateTime())) +// .setText(R.id.tv_money, "+" + redBagInfo.getMoney() + "元") + ; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/event/DateInfoEvent.java b/app/src/main/java/com/yizhuan/erban/bills/event/DateInfoEvent.java new file mode 100644 index 000000000..7328c9dc5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/event/DateInfoEvent.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.bills.event; + +/** + *

事件日期

+ * Created by Administrator on 2017/11/8. + */ +public class DateInfoEvent { + public long millSeconds; + public int position; + + public DateInfoEvent(long millSeconds, int position) { + this.millSeconds = millSeconds; + this.position = position; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/event/TopEvent.java b/app/src/main/java/com/yizhuan/erban/bills/event/TopEvent.java new file mode 100644 index 000000000..a51eaeca6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/event/TopEvent.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.bills.event; + +public class TopEvent { + + public int position; + + public TopEvent(int position) { + this.position = position; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/fragmemt/BaseBillsFragment.java b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/BaseBillsFragment.java new file mode 100644 index 000000000..5d236f240 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/BaseBillsFragment.java @@ -0,0 +1,132 @@ +package com.yizhuan.erban.bills.fragmemt; + +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.jzxiang.pickerview.TimePickerDialog; +import com.jzxiang.pickerview.data.Type; +import com.jzxiang.pickerview.listener.OnDateSetListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.radish.RadishModel; +import com.yizhuan.xchat_android_library.base.AbstractMvpPresenter; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseBillsFragment> extends BaseMvpFragment + implements View.OnClickListener, OnDateSetListener { + protected RecyclerView mRecyclerView; + protected SwipeRefreshLayout mRefreshLayout; + protected int mCurrentCounter = Constants.PAGE_START; + protected static final int PAGE_SIZE = Constants.BILL_PAGE_SIZE; + protected long time = System.currentTimeMillis(); + protected List mBillItemEntityList = new ArrayList<>(); + private TextView mTvDate; + private ImageView mIvTodaySelect; + private ImageView mIvSelectorDate; + protected TimePickerDialog.Builder mDialogYearMonthDayBuild; + private View mRlyDate; + + @Override + public int getRootLayoutId() { + return R.layout.fragment_gift_income ; + } + + @Override + public void onFindViews() { + mTvDate = mView.findViewById(R.id.tv_date); + mRecyclerView = mView.findViewById(R.id.recyclerView); + mRefreshLayout = mView.findViewById(R.id.swipe_refresh); + mIvTodaySelect = mView.findViewById(R.id.iv_today_select); + mIvSelectorDate = mView.findViewById(R.id.tv_selector_date); + mRlyDate = mView.findViewById(R.id.rly_date); + } + + @Override + public void onSetListener() { + mIvTodaySelect.setOnClickListener(this); + mIvSelectorDate.setOnClickListener(this); + mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mCurrentCounter = Constants.PAGE_START; + RadishModel.get().updateRadishWallet().subscribe(); + loadData(); + } + }); + + } + + @Override + public void initiate() { + initData(); + } + + @Override + public void onDateSet(TimePickerDialog timePickerView, long millseconds) { + this.time = millseconds; + setDate(millseconds); + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + + protected void initData() { + setDate(System.currentTimeMillis()); + mDialogYearMonthDayBuild = new TimePickerDialog.Builder() + .setType(Type.YEAR_MONTH_DAY) + .setTitleStringId("日期选择") + .setThemeColor(getResources().getColor(R.color.line_background)) + .setWheelItemTextNormalColor(getResources().getColor(R.color + .timetimepicker_default_text_color)) + .setWheelItemTextSelectorColor(getResources().getColor(R.color.black)) + .setCallBack(this); + } + + protected long mTime; + protected void setDate(long time) { + mTime = time; + mTvDate.setText(TimeUtils.getDateTimeString(time, "yyyy-MM-dd")); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_today_select: + mCurrentCounter = Constants.PAGE_START; + time = System.currentTimeMillis(); + setDate(time); + showLoading(); + loadData(); + break; + case R.id.tv_selector_date: + mDialogYearMonthDayBuild.build().show(getChildFragmentManager(), "year_month_day"); + break; + default: + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mDialogYearMonthDayBuild != null) { + mDialogYearMonthDayBuild.setCallBack(null); + mDialogYearMonthDayBuild = null; + } + } + + protected void setRlyDateBackground(int color) { + if (mRlyDate != null) + mRlyDate.setBackgroundColor(color); + } + + public abstract void loadData(); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftIncomeFragment.java b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftIncomeFragment.java new file mode 100644 index 000000000..bda86907b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftIncomeFragment.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.bills.fragmemt; + +import android.annotation.SuppressLint; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.erban.bills.adapter.GiftIncomeAdapter; +import com.yizhuan.erban.bills.presenter.GiftIncomePresenter; +import com.yizhuan.erban.bills.view.IGiftIncomeView; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_core.bills.bean.IncomeListInfo; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@CreatePresenter(GiftIncomePresenter.class) +public class GiftIncomeFragment extends BaseBillsFragment implements IGiftIncomeView { + private BillBaseAdapter adapter; + + public static Fragment newInstance() { + Fragment fragment = new GiftIncomeFragment(); + return fragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_gift_income; + } + + @Override + public void initiate () { + super.initiate(); + adapter = new GiftIncomeAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + adapter.addFooterView(View.inflate(getActivity(), R.layout.layout_bills_bottom, null)); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mContext); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + + firstLoadDate(); + } + + @SuppressLint("CheckResult") + public void loadData () { + getMvpPresenter().getGiftIncomeBills(mCurrentCounter, PAGE_SIZE, time); + } + + @Override + public void onGetDataError (String error){ + if (mCurrentCounter == Constants.PAGE_START) { + showNetworkErr(); + } else { + adapter.loadMoreFail(); + } + } + + @Override + public void onGetIncomeBills (IncomeListInfo data){ + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (IncomeInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mGiftInComeInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, XChatConstants.EMPTY_RECORD_AND_THREE_MONTHS_TIPSS); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + + @Override + public void smoothScrollToTop () { + if (mRecyclerView != null) + mRecyclerView.smoothScrollToPosition(0); + } + + private void firstLoadDate () { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftOutputFragment.java b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftOutputFragment.java new file mode 100644 index 000000000..4bcc0a901 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/GiftOutputFragment.java @@ -0,0 +1,142 @@ +package com.yizhuan.erban.bills.fragmemt; + +import android.annotation.SuppressLint; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.erban.bills.adapter.GiftExpendAdapter; +import com.yizhuan.erban.bills.presenter.GiftIncomePresenter; +import com.yizhuan.erban.bills.presenter.GiftOutputPresenter; +import com.yizhuan.erban.bills.view.IGiftIncomeView; +import com.yizhuan.erban.bills.view.IGiftOutputView; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.ExpendInfo; +import com.yizhuan.xchat_android_core.bills.bean.ExpendListInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@CreatePresenter(GiftOutputPresenter.class) +public class GiftOutputFragment extends BaseBillsFragment implements IGiftOutputView { + private BillBaseAdapter adapter; + + public static Fragment newInstance() { + Fragment fragment = new GiftOutputFragment(); + return fragment; + } + + @Override + public void initiate() { + super.initiate(); + adapter = new GiftExpendAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + adapter.addFooterView(View.inflate(getActivity(), R.layout.layout_bills_bottom, null)); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mContext); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + + firstLoadDate(); + } + + private void firstLoadDate() { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + + @SuppressLint("CheckResult") + public void loadData() { + getMvpPresenter().getetExpendBills(mCurrentCounter, PAGE_SIZE, time); + } + + @Override + public void onGetDataError(String error) { + if (mCurrentCounter == Constants.PAGE_START) { + showNetworkErr(); + } else { + adapter.loadMoreFail(); + } + } + + @Override + public void onGetExpendBills(ExpendListInfo data) { + mRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + List billItemEntities = new ArrayList<>(); + int size = mBillItemEntityList.size(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List expendInfos = map.get(key); + if (ListUtils.isListEmpty(expendInfos)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (ExpendInfo temp : expendInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + //目的是为了比较 + billItemEntity.time = key; + billItemEntity.mGiftExpendInfo = temp; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, XChatConstants.EMPTY_RECORD_AND_THREE_MONTHS_TIPSS); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + + @Override + public void smoothScrollToTop() { + if (mRecyclerView != null) + mRecyclerView.smoothScrollToPosition(0); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/fragmemt/RadishGiftFragment.java b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/RadishGiftFragment.java new file mode 100644 index 000000000..5c73d1d67 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/RadishGiftFragment.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.bills.fragmemt; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.text.TextUtils; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.erban.bills.adapter.RadishGiftAdapter; +import com.yizhuan.erban.bills.presenter.RadishGiftPresenter; +import com.yizhuan.erban.bills.view.IRadishGiftView; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RadishGiftInfo; +import com.yizhuan.xchat_android_core.bills.bean.RadishGiftListInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@CreatePresenter(RadishGiftPresenter.class) +public class RadishGiftFragment extends BaseBillsFragment implements IRadishGiftView { + + public static final byte TYPE_RADISH_EXPAND = 1; + public static final byte TYPE_RADISH_INCOME= 2; + private static final String TYPE = "type_radish"; + private BillBaseAdapter mAdapter; + + private byte mType = TYPE_RADISH_INCOME; + + public static Fragment newInstance(byte type) { + Fragment fragment = new RadishGiftFragment(); + Bundle bundle = new Bundle(); + bundle.putByte(TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + @Override + public void loadData() { + getMvpPresenter().getRadishRecord(mCurrentCounter, PAGE_SIZE, mTime, mType); + } + + private void firstLoadDate() { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + + @Override + public void initiate() { + super.initiate(); + + Bundle bundle = getArguments(); + if (bundle != null) { + mType = bundle.getByte(TYPE, TYPE_RADISH_INCOME); + } + + mAdapter = new RadishGiftAdapter(mBillItemEntityList, mType); + mAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mContext); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(mAdapter); + + firstLoadDate(); + + } + + @Override + public void getRadishRecordSuccess(RadishGiftListInfo list) { + mRefreshLayout.setRefreshing(false); + if (null != list) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + mAdapter.setNewData(mBillItemEntityList); + } else { + mAdapter.loadMoreComplete(); + } + List>> billList = list.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (RadishGiftInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mRadishGiftInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + mAdapter.setEnableLoadMore(false); + } + mAdapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, "哼,你们不爱我了,一个礼物都没有"); + } else { + mAdapter.loadMoreEnd(true); + } + } + } + } + + @Override + public void getRadishRecordFail(String message) { + if (mCurrentCounter == Constants.PAGE_START) { + showNetworkErr(); + } else { + mAdapter.loadMoreFail(); + } + + } + + @Override + public void smoothScrollToTop () { + if (mRecyclerView != null) + mRecyclerView.smoothScrollToPosition(0); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/fragmemt/WithdrawBillsFragment.java b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/WithdrawBillsFragment.java new file mode 100644 index 000000000..5aa80f727 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/fragmemt/WithdrawBillsFragment.java @@ -0,0 +1,240 @@ +package com.yizhuan.erban.bills.fragmemt; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.bills.adapter.WithdrawBillsAdapter; +import com.yizhuan.erban.bills.event.DateInfoEvent; +import com.yizhuan.erban.bills.event.TopEvent; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.databinding.FragmentXrexylerviewBinding; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.BillModel; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.IncomeInfo; +import com.yizhuan.xchat_android_core.bills.bean.IncomeListInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + *

提现账单(不包含红包)

+ * Created by Administrator on 2017/11/7. + */ +@ActLayoutRes(R.layout.fragment_xrexylerview) +public class WithdrawBillsFragment extends BaseBindingFragment { + private RecyclerView mRecyclerView; + private SwipeRefreshLayout mSwipeRefreshLayout; + private WithdrawBillsAdapter adapter; + private List mBillItemEntityList = new ArrayList<>(); + private Context mContext; + + protected int mCurrentCounter = Constants.PAGE_START;//当前页 + protected static final int PAGE_SIZE = Constants.BILL_PAGE_SIZE; + protected long time = System.currentTimeMillis(); + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = getContext(); + } + + @Override + public void onFindViews() { + mRecyclerView = mBinding.recyclerView; + mSwipeRefreshLayout = mBinding.swipeRefresh; + } + + @Override + public void onSetListener() { + mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mCurrentCounter = 1; + loadData(); + } + }); + } + + @Override + public void initiate() { + adapter = new WithdrawBillsAdapter(mBillItemEntityList); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + adapter.addFooterView(View.inflate(getActivity(), R.layout.layout_bills_bottom, null)); + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mContext); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(adapter); + showLoading(); + loadData(); + } + + @SuppressLint("CheckResult") + private void loadData() { + BillModel.get() + .getWithdrawBills(mCurrentCounter, PAGE_SIZE, time) + .compose(bindToLifecycle()) + .subscribe((incomedResult, throwable) -> { + if (throwable != null) { + onGetWithdrawBillsError(throwable.getMessage()); + } else if (incomedResult != null && incomedResult.isSuccess()) { + onGetWithdrawBills(incomedResult.getData()); + } else if (incomedResult != null) { + onGetWithdrawBillsError(incomedResult.getError()); + } + }); + } + + public void onGetWithdrawBills(IncomeListInfo data) { + mSwipeRefreshLayout.setRefreshing(false); + if (null != data) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + adapter.setNewData(mBillItemEntityList); + } else { + adapter.loadMoreComplete(); + } + BillItemEntity billItemEntity; + List>> billList = data.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + if (!TextUtils.equals(lastBillItem.time, key)) { //时间不一致才会添加标题 + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (IncomeInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mWithdrawInfo = temp; + billItemEntity.time = key; //目的是为了比较 + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + adapter.setEnableLoadMore(false); + } + adapter.addData(billItemEntities); + } else { + if (mCurrentCounter == 1) { + showNoData(R.drawable.icon_common_failure, XChatConstants.EMPTY_RECORD_AND_THREE_MONTHS_TIPSS); + } else { + adapter.loadMoreEnd(true); + } + } + } + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + public void onGetWithdrawBillsError(String error) { + mSwipeRefreshLayout.setRefreshing(false); + if (mCurrentCounter == Constants.PAGE_START) { + mSwipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + adapter.loadMoreFail(); + } + } + + + @Override + public void onStart() { + super.onStart(); + EventBus.getDefault().register(this); + } + + @Override + public void onStop() { + super.onStop(); + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onDateInfoEvent(DateInfoEvent event) { + if (event != null && event.position == 0) { + time = event.millSeconds; + mCurrentCounter = 1; + showLoading(); + loadData(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onTopEvent(TopEvent event) { + if (event != null && event.position == 0) { + try { + mRecyclerView.smoothScrollToPosition(0); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + mCurrentCounter = 1; + showLoading(); + loadData(); + } + }; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/presenter/BillGiftIncomeGroupPresenter.java b/app/src/main/java/com/yizhuan/erban/bills/presenter/BillGiftIncomeGroupPresenter.java new file mode 100644 index 000000000..4c67832c3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/presenter/BillGiftIncomeGroupPresenter.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.bills.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.bills.view.IBillGiftIncomeGroupView; + +public class BillGiftIncomeGroupPresenter extends BaseMvpPresenter { +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftIncomePresenter.java b/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftIncomePresenter.java new file mode 100644 index 000000000..92539eb99 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftIncomePresenter.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.bills.presenter; + +import android.annotation.SuppressLint; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.bills.view.IGiftIncomeView; +import com.yizhuan.xchat_android_core.bills.BillModel; + +public class GiftIncomePresenter extends BaseMvpPresenter { + + @SuppressLint("CheckResult") + public void getGiftIncomeBills(int pageNo, int pageSize, long time) { + BillModel.get() + .getGiftIncomeBills(pageNo, pageSize, time) + .compose(bindToLifecycle()) + .subscribe((incomedResult, throwable) -> { + if (throwable != null) { + if (mMvpView != null) + mMvpView.onGetDataError(throwable.getMessage()); + } else if (incomedResult != null && incomedResult.isSuccess()) { + if (mMvpView != null) + mMvpView.onGetIncomeBills(incomedResult.getData()); + } else if (incomedResult != null) { + if (mMvpView != null) + mMvpView.onGetDataError(incomedResult.getError()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftOutputPresenter.java b/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftOutputPresenter.java new file mode 100644 index 000000000..1b237ff8e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/presenter/GiftOutputPresenter.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.bills.presenter; + +import android.annotation.SuppressLint; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.bills.view.IGiftOutputView; +import com.yizhuan.xchat_android_core.bills.BillModel; + +public class GiftOutputPresenter extends BaseMvpPresenter { + + @SuppressLint("CheckResult") + public void getetExpendBills(int pageNo, int pageSize, long time) { + BillModel.get() + .getGiftExpendBills(pageNo, pageSize, time) + .compose(bindToLifecycle()) + .subscribe((expendResult, throwable) -> { + if (throwable != null) { + mMvpView.onGetDataError(throwable.getMessage()); + } else if (expendResult != null && expendResult.isSuccess()) { + mMvpView.onGetExpendBills(expendResult.getData()); + } else if (expendResult != null) { + mMvpView.onGetDataError(expendResult.getError()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/presenter/RadishGiftPresenter.java b/app/src/main/java/com/yizhuan/erban/bills/presenter/RadishGiftPresenter.java new file mode 100644 index 000000000..798461aeb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/presenter/RadishGiftPresenter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.bills.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.bills.view.IRadishGiftView; +import com.yizhuan.xchat_android_core.bills.RadishGiftModel; +import com.yizhuan.xchat_android_core.bills.result.RadishGiftResult; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class RadishGiftPresenter extends BaseMvpPresenter { + + public void getRadishRecord(int page, int pageSize, long date, byte type) { + RadishGiftModel.get().getRadishRecord(page, pageSize, date, type) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(RadishGiftResult radishGiftResult) { + if (radishGiftResult != null && radishGiftResult.isSuccess()) { + if (mMvpView != null) + mMvpView.getRadishRecordSuccess(radishGiftResult.getData()); + } else if (radishGiftResult != null){ + if (mMvpView != null) + mMvpView.getRadishRecordFail(radishGiftResult.getError()); + } + } + + @Override + public void onError(Throwable e) { + if (mMvpView != null) + mMvpView.getRadishRecordFail(e.getMessage()); + + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/view/IBillGiftIncomeGroupView.java b/app/src/main/java/com/yizhuan/erban/bills/view/IBillGiftIncomeGroupView.java new file mode 100644 index 000000000..01c1c9a0a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/view/IBillGiftIncomeGroupView.java @@ -0,0 +1,6 @@ +package com.yizhuan.erban.bills.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IBillGiftIncomeGroupView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/view/IGiftIncomeView.java b/app/src/main/java/com/yizhuan/erban/bills/view/IGiftIncomeView.java new file mode 100644 index 000000000..a7f6a287c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/view/IGiftIncomeView.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.bills.view; + +import com.yizhuan.xchat_android_core.bills.bean.IncomeListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IGiftIncomeView extends ISmoothToTopView { + void onGetDataError(String message); + void onGetIncomeBills(IncomeListInfo data); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/view/IGiftOutputView.java b/app/src/main/java/com/yizhuan/erban/bills/view/IGiftOutputView.java new file mode 100644 index 000000000..74916330b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/view/IGiftOutputView.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.bills.view; + +import com.yizhuan.xchat_android_core.bills.bean.ExpendListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IGiftOutputView extends IMvpBaseView { + void smoothScrollToTop(); + void onGetDataError(String message); + void onGetExpendBills(ExpendListInfo data); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/view/IRadishGiftView.java b/app/src/main/java/com/yizhuan/erban/bills/view/IRadishGiftView.java new file mode 100644 index 000000000..42edbe5e1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/view/IRadishGiftView.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.bills.view; + +import com.yizhuan.xchat_android_core.bills.bean.RadishGiftListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IRadishGiftView extends ISmoothToTopView { + void getRadishRecordSuccess(RadishGiftListInfo list); + void getRadishRecordFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/view/ISmoothToTopView.java b/app/src/main/java/com/yizhuan/erban/bills/view/ISmoothToTopView.java new file mode 100644 index 000000000..995be34a2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/view/ISmoothToTopView.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.bills.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface ISmoothToTopView extends IMvpBaseView { + void smoothScrollToTop(); +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/widget/BillGiftIncomeGroupNavigatorAdapter.java b/app/src/main/java/com/yizhuan/erban/bills/widget/BillGiftIncomeGroupNavigatorAdapter.java new file mode 100644 index 000000000..3964b95b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/widget/BillGiftIncomeGroupNavigatorAdapter.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.bills.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.widget.RankNavigatorAdapter; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.ArrayList; +import java.util.List; + +public class BillGiftIncomeGroupNavigatorAdapter extends CommonNavigatorAdapter { + + private List mTitleList = new ArrayList<>(); + + public BillGiftIncomeGroupNavigatorAdapter() { + mTitleList.add("金币礼物"); + mTitleList.add("萝卜礼物"); + } + @Override + public int getCount() { + return mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_999999)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(1.0f); + scaleTransitionPagerTitleView.setTextSize(15); + scaleTransitionPagerTitleView.setText(mTitleList.get(index)); + + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(index); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(context, 4)); + indicator.setRoundRadius(UIUtil.dip2px(context, 2.0)); + indicator.setLineWidth(UIUtil.dip2px(context, 17)); + indicator.setColors(ContextCompat.getColor(context, R.color.appColor)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + //lp.bottomMargin = 0; + indicator.setLayoutParams(lp); + return indicator; + } + + private RankNavigatorAdapter.OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(RankNavigatorAdapter.OnItemSelectListener mOnItemSelectListener) { + this.mOnItemSelectListener = mOnItemSelectListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bills/widget/BillItemView.java b/app/src/main/java/com/yizhuan/erban/bills/widget/BillItemView.java new file mode 100644 index 000000000..d6c4c708f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bills/widget/BillItemView.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.bills.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + *

账单item

+ * Created by Administrator on 2017/11/6. + */ +public class BillItemView extends RelativeLayout { + private ImageView mIvLeftIcon; + private TextView mTvItemText; + private View mViewLine; + private Context mContext; + + public BillItemView(Context context) { + this(context, null); + } + + public BillItemView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public BillItemView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs, defStyle); + } + + private void init(Context context, @Nullable AttributeSet attrs, int defStyle) { + mContext = context; + inflate(context, R.layout.layout_bill_item_view, this); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BillItemView, defStyle, 0); + int leftIcon = a.getResourceId(R.styleable.BillItemView_left_icon, -1); + String itemText = a.getString(R.styleable.BillItemView_item_text); + boolean isHide = a.getBoolean(R.styleable.BillItemView_hide_line, false); + a.recycle(); + mIvLeftIcon = (ImageView) findViewById(R.id.iv_left_icon); + mTvItemText = (TextView) findViewById(R.id.tv_item_text); + mViewLine = findViewById(R.id.view_line); + + setBackgroundResource(R.drawable.bg_common_touch_while); + setData(leftIcon, itemText); + setViewLine(isHide); + } + + public void setData(int leftIconResId, int itemTextResId) { + setData(leftIconResId, mContext.getResources().getString(itemTextResId)); + } + + public void setData(int leftIconResId, String itemText) { + mIvLeftIcon.setImageResource(leftIconResId); + mTvItemText.setText(itemText); + } + + public void setViewLine(boolean isHide) { + mViewLine.setVisibility(!isHide ? VISIBLE : GONE); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bindadapter/BaseAdapter.java b/app/src/main/java/com/yizhuan/erban/bindadapter/BaseAdapter.java new file mode 100644 index 000000000..0c8a48649 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bindadapter/BaseAdapter.java @@ -0,0 +1,51 @@ +package com.yizhuan.erban.bindadapter; + +import android.databinding.DataBindingUtil; +import android.databinding.ViewDataBinding; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.view.View; +import android.view.ViewGroup; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; + + +/** + * Created by fwhm on 2017/7/5. + */ + +public class BaseAdapter extends BaseQuickAdapter { + + private int brid; + + @Nullable + private int[] clickIds; + + public BaseAdapter(@LayoutRes int layoutResId, int brid) { + this(layoutResId, brid, null); + } + + public BaseAdapter(@LayoutRes int layoutResId, int brid, @Nullable int[] clickIds) { + super(layoutResId); + this.clickIds = clickIds; + this.brid = brid; + } + + @Override + protected void convert(BindingViewHolder helper, T item) { + ViewDataBinding binding = helper.getBinding(); + binding.setVariable(brid, item); + binding.executePendingBindings(); + } + @Override + protected View getItemView(int layoutResId, ViewGroup parent) { + ViewDataBinding binding = DataBindingUtil.inflate(mLayoutInflater, layoutResId, parent, false); + if (binding == null) { + return super.getItemView(layoutResId, parent); + } + View view = binding.getRoot(); + view.setTag(R.id.BaseQuickAdapter_databinding_support, binding); + return view; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bindadapter/BindingViewHolder.java b/app/src/main/java/com/yizhuan/erban/bindadapter/BindingViewHolder.java new file mode 100644 index 000000000..1392971f3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bindadapter/BindingViewHolder.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.bindadapter; + +import android.databinding.ViewDataBinding; +import android.view.View; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; + +/** + * Created by fwhm on 2017/3/28. + */ + +public class BindingViewHolder extends BaseViewHolder { + + public BindingViewHolder(View view) { + super(view); + } + + public ViewDataBinding getBinding() { + return (ViewDataBinding) itemView.getTag(R.id.BaseQuickAdapter_databinding_support); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/bindadapter/RvAdapter.java b/app/src/main/java/com/yizhuan/erban/bindadapter/RvAdapter.java new file mode 100644 index 000000000..a122d2c4b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/bindadapter/RvAdapter.java @@ -0,0 +1,52 @@ +package com.yizhuan.erban.bindadapter; + +import android.databinding.BindingAdapter; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.log.LogUtil; + +import java.util.List; + +/** + * Created by huangmeng1 on 2018/5/9. + */ + +public class RvAdapter { + /** + * 实现adapter加载更多的一些处理与rv的映射 + * @param recyclerView + * @param date rv的数据 + * @param newData 每次加载回的数控 + * @param isLode + * @param throwable + * @param pageSize + * @param + */ + @BindingAdapter(value = {"date", "newData", "isLode", "error", "pageSize", "loadMoreListener"}, requireAll = false) + public static void bindRvData(RecyclerView recyclerView, List date, List newData, boolean isLode, + Throwable throwable, int pageSize, BaseQuickAdapter.RequestLoadMoreListener loadMoreListener) { + BaseAdapter adapter = (BaseAdapter) recyclerView.getAdapter(); + if (loadMoreListener != null) { + adapter.setOnLoadMoreListener(loadMoreListener, recyclerView); + } + adapter.setNewData(date); + if (throwable!=null){ + adapter.loadMoreFail(); + return; + } + if ( newData==null || newData.size()() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { + float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); + int width = Math.round(imageView.getContext().getResources().getDimensionPixelOffset(R.dimen.tag_height) / ratio); + int height = imageView.getContext().getResources().getDimensionPixelOffset(R.dimen.tag_height); + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imageView.getLayoutParams(); + params.width = width; + params.height = height; + imageView.setLayoutParams(params); + imageView.setImageDrawable(drawable); + return true; + } + }) + .into(imageView); + } + } + @BindingAdapter(value = {"avatarUrl"},requireAll = false) + public static void setAvatarUrl(ImageView imageView, String url){ + if (TextUtils.isEmpty(url) || url.equals("null")) return; + ImageLoadUtils.loadAvatar(imageView.getContext(), url, imageView); + } + + @BindingAdapter(value = {"roundUrl"},requireAll = false) + public static void setRoundUrl(ImageView imageView, String url){ + if (TextUtils.isEmpty(url)) return; + ImageLoadUtils.loadSmallRoundBackground(imageView.getContext(), url, imageView); + } + + @BindingAdapter(value = {"nomalUrl"},requireAll = false) + public static void setNomalUrl(ImageView imageView, String url){ + if (TextUtils.isEmpty(url)) return; + ImageLoadUtils.loadImage(imageView.getContext(), url, imageView); + } + + @BindingAdapter(value = {"date"},requireAll = false) + public static void setConstellation(TextView textView,long date){ + String star = StarUtils.getConstellation(new Date(date)); + if (null == star) { + textView.setVisibility(View.GONE); + } else { + textView.setText(star); + textView.setVisibility(View.VISIBLE); + } + } + + @BindingAdapter(value = {"isOn"}, requireAll = false) + public static void setIsOn(IOSSwitchView iosSwitchView, boolean isOn) { + iosSwitchView.setOn(isOn); + } + + @BindingAdapter(value = {"drawTime"},requireAll = false) + public static void setTime(TextView tvContent,String time) { + long longTime = 0; + try { + longTime = Long.parseLong(time); + }catch (Exception e){ + e.printStackTrace(); + } + if (longTime == 0) { + tvContent.setVisibility(View.GONE); + return; + } + tvContent.setText(TimeUtils.getPostTimeString(BasicConfig.INSTANCE.getAppContext(),longTime,true,false)); + } + + @BindingAdapter(value = {"circleUrl"},requireAll = false) + public static void setCircleUrl(ImageView imageView, String url){ + // if (TextUtils.isEmpty(url)) return; + ImageLoadUtils.loadCircleImage(imageView.getContext(), url, imageView, R.drawable.default_user_head); + } + + @BindingAdapter(value = {"shape_color", "shape_radius", "shape_stroke_width", "shape_stroke_color"},requireAll = false) + public static void setViewBackground(View view, int color, int radius_dp, + float shape_stroke_width, int shape_stroke_color) { + GradientDrawable drawable = new GradientDrawable(); + drawable.setColor(color); + drawable.setCornerRadius(UIUtil.dip2px(view.getContext(), radius_dp)); + if (shape_stroke_width > 0) { + try { + drawable.setStroke(UIUtil.dip2px(view.getContext(), shape_stroke_width), + shape_stroke_color); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + view.setBackground(drawable); + } + + @BindingAdapter(value = {"selected"}) + public static void setViewSelected(View view, boolean selected) { + view.setSelected(selected); + } + + @BindingAdapter(value = {"ktvRoundCover"},requireAll = false) + public static void setKtvRoundCover(ImageView imageView, String url){ + if (TextUtils.isEmpty(url)){ + imageView.setImageResource(R.drawable.default_cover); + }else { + ImageLoadUtils.loadKtvRoundBackground(imageView.getContext(), url, imageView); + } + } + + @BindingAdapter(value = {"visible"}, requireAll = false) + public static void setAvatarUrl(View view, boolean show) { + view.setVisibility(show ? View.VISIBLE : View.GONE); + } + + @BindingAdapter(value = {"shape_color", "shape_radius",}, requireAll = false) + public static void setViewBackgroundII(View v, int color, int radius) { + GradientDrawable drawable = new GradientDrawable(); + drawable.setColor(color); + drawable.setCornerRadius(UIUtil.dip2px(v.getContext(), radius)); + v.setBackground(drawable); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/AbsStatusFragment.java b/app/src/main/java/com/yizhuan/erban/common/AbsStatusFragment.java new file mode 100644 index 000000000..fa9012a06 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/AbsStatusFragment.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.common; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Toast; + +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.erban.R; + +/** + * Created by xujiexing on 14-7-21. + */ +public abstract class AbsStatusFragment extends Fragment implements IStatusFragment { + protected View.OnClickListener mLoadListener; + + @Override + public void setListener(View.OnClickListener listener) { + this.mLoadListener = listener; + } + + public void checkNetToast(){ + Toast.makeText(BasicConfig.INSTANCE.getAppContext(), R.string.str_network_not_capable, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + view.setOnClickListener(mLoadListener); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mLoadListener = null; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/IStatusFragment.java b/app/src/main/java/com/yizhuan/erban/common/IStatusFragment.java new file mode 100644 index 000000000..ccce09253 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/IStatusFragment.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.common; + +import android.view.View; + +/** + * Created by xujiexing on 14-7-21. + */ +public interface IStatusFragment { + public void setListener(View.OnClickListener listener); +} diff --git a/app/src/main/java/com/yizhuan/erban/common/LoadingFragment.java b/app/src/main/java/com/yizhuan/erban/common/LoadingFragment.java new file mode 100644 index 000000000..e475330d8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/LoadingFragment.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.common; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + + +/** + * Created by xujiexing on 14-4-9. + */ +public class LoadingFragment extends AbsStatusFragment { + private static final String TIP_PARAM = "TIP_PARAM"; + private static final String DRAWABLE_PARAM = "DRAWABLE_PARAM"; + private static final String BACKGROUND_COLOR_PARAM = "BACKGROUND_COLOR_PARAM"; + private int mTip; + private int mDrawable; + private int mBackgroundColor; + + public static LoadingFragment newInstance() { + return new LoadingFragment(); + } + + public static LoadingFragment newInstance(int drawable, int tips) { + Bundle bundle = new Bundle(); + bundle.putInt(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + LoadingFragment fragment = new LoadingFragment(); + fragment.setArguments(bundle); + return fragment; + } + + public static LoadingFragment newInstance(int drawable, int tips, int backgroundColor) { + Bundle bundle = new Bundle(); + bundle.putInt(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + bundle.putInt(BACKGROUND_COLOR_PARAM, backgroundColor); + LoadingFragment fragment = new LoadingFragment(); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_loading, container, false); + if (savedInstanceState != null) { + mTip = savedInstanceState.getInt(TIP_PARAM, R.string.loading); + mDrawable = savedInstanceState.getInt(DRAWABLE_PARAM, R.drawable.loading_icon); + mBackgroundColor = savedInstanceState.getInt(BACKGROUND_COLOR_PARAM, getResources().getColor(R.color.common_color_2)); + } else { + Bundle bundle = getArguments(); + if (bundle != null) { + mTip = bundle.getInt(TIP_PARAM, R.string.loading); + mDrawable = bundle.getInt(DRAWABLE_PARAM, R.drawable.loading_icon); + mBackgroundColor = bundle.getInt(BACKGROUND_COLOR_PARAM, getResources().getColor(R.color.common_color_2)); + } else { + mTip = R.string.loading; + } + } + + if (mTip > 0) { + TextView textView = (TextView) view.findViewById(R.id.loading_text); + textView.setText(getString(mTip)); + textView.setVisibility(View.VISIBLE); + } + if (mDrawable > 0) { + ImageView imageView = (ImageView) view.findViewById(R.id.loadingIv); + imageView.setImageResource(mDrawable); + imageView.setVisibility(View.VISIBLE); + } + if (mBackgroundColor > 0) { + view.setBackgroundColor(mBackgroundColor); + } + + return view; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(TIP_PARAM, mTip); + outState.putInt(DRAWABLE_PARAM, mDrawable); + outState.putInt(BACKGROUND_COLOR_PARAM, mBackgroundColor); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/NetworkErrorFragment.java b/app/src/main/java/com/yizhuan/erban/common/NetworkErrorFragment.java new file mode 100644 index 000000000..1b2dcea64 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/NetworkErrorFragment.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.common; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.erban.R; + +import static com.yizhuan.erban.common.NoDataFragment.LAYOUTID_PARAM; + +/** + * Created by xujiexing on 14-4-9. + */ +public class NetworkErrorFragment extends AbsStatusFragment { + private int mLayout; + + public static NetworkErrorFragment newInstance() { + return new NetworkErrorFragment(); + } + + public static NetworkErrorFragment newInstance(int layoutId) { + Bundle bundle = new Bundle(); + bundle.putInt(LAYOUTID_PARAM, layoutId); + NetworkErrorFragment fragment = new NetworkErrorFragment(); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + Bundle bundle = getArguments(); + if (bundle != null) { + mLayout = bundle.getInt(LAYOUTID_PARAM); + } else { + mLayout = R.layout.fragment_network_error; + } + + if(mLayout <= 0){ + mLayout = R.layout.fragment_network_error; + } + + View view = LayoutInflater.from(getActivity()).inflate(mLayout, container, false); + view.setOnClickListener(mSelfListener); + + return view; + } + + private View.OnClickListener mSelfListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + + if(!NetworkUtils.isNetworkStrictlyAvailable(getActivity())){ + checkNetToast(); + return; + } + + if(mLoadListener != null){ + mLoadListener.onClick(v); + } + } + }; + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/NoDataFragment.java b/app/src/main/java/com/yizhuan/erban/common/NoDataFragment.java new file mode 100644 index 000000000..d73ca4733 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/NoDataFragment.java @@ -0,0 +1,130 @@ +package com.yizhuan.erban.common; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + + +/** + * Created by xujiexing on 14-4-9. + */ +public class NoDataFragment extends AbsStatusFragment { + public static final String LAYOUTID_PARAM = "LAYOUTID"; + private static final String TIP_PARAM = "TIP_PARAM"; + private static final String DRAWABLE_PARAM = "DRAWABLE_PARAM"; + private int mLayout; + private CharSequence mTip; + private int mDrawable; + + private OnNoDataFragmentButtonClickListener onNoDataFragmentButtonClickListener; + + public static NoDataFragment newInstance() { + return new NoDataFragment(); + } + + public static NoDataFragment newInstance(int drawable, CharSequence tips) { + Bundle bundle = new Bundle(); + bundle.putCharSequence(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + NoDataFragment fragment = new NoDataFragment(); + fragment.setArguments(bundle); + return fragment; + } + + public static NoDataFragment newInstance(int layoutId, int drawable, CharSequence tips) { + Bundle bundle = new Bundle(); + bundle.putInt(LAYOUTID_PARAM, layoutId); + bundle.putCharSequence(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + NoDataFragment fragment = new NoDataFragment(); + fragment.setArguments(bundle); + return fragment; + } + + public static NoDataFragment newInstance(int layoutId, int drawable, CharSequence tips, OnNoDataFragmentButtonClickListener onNoDataFragmentButtonClickListener) { + Bundle bundle = new Bundle(); + bundle.putInt(LAYOUTID_PARAM, layoutId); + bundle.putCharSequence(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + NoDataFragment fragment = new NoDataFragment(); + fragment.setArguments(bundle); + fragment.setOnNoDataFragmentButtonClickListener(onNoDataFragmentButtonClickListener); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + if (savedInstanceState != null) { + mLayout = savedInstanceState.getInt(LAYOUTID_PARAM); + mTip = savedInstanceState.getCharSequence(TIP_PARAM); + mDrawable = savedInstanceState.getInt(DRAWABLE_PARAM, R.drawable.icon_common_failure); + } else { + Bundle bundle = getArguments(); + if (bundle != null) { + mLayout = bundle.getInt(LAYOUTID_PARAM, 0); + mTip = bundle.getCharSequence(TIP_PARAM); + mDrawable = bundle.getInt(DRAWABLE_PARAM, R.drawable.icon_common_failure); + } else { + mLayout = R.layout.fragment_no_data_large_iv; + mTip = getString( + R.string.no_list_data); + mDrawable = R.drawable.icon_common_failure; + } + } + if (mTip == null || mTip.length() <= 0) { + mTip = getString(R.string.no_list_data); + } + + if (mDrawable <= 0) { + mDrawable = R.drawable.icon_common_failure; + } + + if (mLayout <= 0) { + mLayout = R.layout.fragment_no_data_large_iv; + } + + View view = LayoutInflater.from(getActivity()).inflate(mLayout, container, false); + view.setOnClickListener(this.mSelfListener); + ImageView imageView = view.findViewById(R.id.no_data_icon); + imageView.setImageDrawable(getResources().getDrawable(mDrawable)); + TextView textView = view.findViewById(R.id.no_data_text); + textView.setText(mTip); + if (view.findViewById(R.id.no_data_button) != null) { + View button = view.findViewById(R.id.no_data_button); + button.setOnClickListener(view1 -> { + if (onNoDataFragmentButtonClickListener != null) { + onNoDataFragmentButtonClickListener.onButtonClick(); + } + }); + } + + return view; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(LAYOUTID_PARAM, mLayout); + outState.putCharSequence(TIP_PARAM, mTip); + outState.putInt(DRAWABLE_PARAM, mDrawable); + } + + private View.OnClickListener mSelfListener = v -> { + if (mLoadListener != null) + mLoadListener.onClick(v); + }; + + public interface OnNoDataFragmentButtonClickListener { + void onButtonClick(); + } + + public void setOnNoDataFragmentButtonClickListener(OnNoDataFragmentButtonClickListener onNoDataFragmentButtonClickListener) { + this.onNoDataFragmentButtonClickListener = onNoDataFragmentButtonClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/ReloadFragment.java b/app/src/main/java/com/yizhuan/erban/common/ReloadFragment.java new file mode 100644 index 000000000..f6d0ddca7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/ReloadFragment.java @@ -0,0 +1,127 @@ +package com.yizhuan.erban.common; + +import android.annotation.TargetApi; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.ColorInt; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; +import com.yizhuan.erban.R; + +import org.jetbrains.annotations.NotNull; + + +/** + * Created by xujiexing on 14-4-9. + */ +public class ReloadFragment extends AbsStatusFragment { + private static final String TIP_PARAM = "TIP_PARAM"; + private static final String DRAWABLE_PARAM = "DRAWABLE_PARAM"; + private static final String BG_PARAM = "BG_PARAM"; + private int mTip; + private int mDrawable; + private int mBgColor = 1; + + public static ReloadFragment newInstance() { + return new ReloadFragment(); + } + + public static ReloadFragment newInstance(int drawable, int tips) { + return newInstance(drawable, tips, -1); + } + + public static ReloadFragment newInstance(int drawable, int tips, @ColorInt int bgColor) { + Bundle bundle = new Bundle(); + bundle.putInt(TIP_PARAM, tips); + bundle.putInt(DRAWABLE_PARAM, drawable); + bundle.putInt(BG_PARAM, bgColor); + ReloadFragment fragment = new ReloadFragment(); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_reload, container, false); + + if (savedInstanceState != null) { + mTip = savedInstanceState.getInt(TIP_PARAM, R.string.click_screen_reload); + mDrawable = savedInstanceState.getInt(DRAWABLE_PARAM, R.drawable.icon_common_failure); + mBgColor = savedInstanceState.getInt(BG_PARAM, mBgColor); + } else { + Bundle bundle = getArguments(); + if (bundle != null) { + mTip = bundle.getInt(TIP_PARAM, R.string.click_screen_reload); + mDrawable = bundle.getInt(DRAWABLE_PARAM, R.drawable.icon_common_failure); + mBgColor = bundle.getInt(BG_PARAM, mBgColor); + } else { + mTip = R.string.click_screen_reload; + mDrawable = R.drawable.icon_common_failure; + } + } + if (mTip <= 0) { + mTip = R.string.click_screen_reload; + } + + if (mDrawable <= 0) { + mDrawable = R.drawable.icon_common_failure; + } + if(mBgColor != 1){ + view.setBackgroundColor(mBgColor); + } + ImageView imageView = (ImageView) view.findViewById(R.id.reload_icon); + imageView.setImageDrawable(getResources().getDrawable(mDrawable)); + TextView textView = (TextView) view.findViewById(R.id.error_text); + textView.setText(getString(mTip)); + view.setOnClickListener(mSelfListener); + return view; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(TIP_PARAM, mTip); + outState.putInt(DRAWABLE_PARAM, mDrawable); + } + + private View.OnClickListener mSelfListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!checkActivityValid()) + return; + if (!NetworkUtils.isNetworkStrictlyAvailable(getActivity())) { + checkNetToast(); + return; + } + + if (mLoadListener != null) { + mLoadListener.onClick(v); + } + } + }; + + @TargetApi(17) + protected boolean checkActivityValid() { + if (getActivity() == null) { + MLog.warn(this, "Fragment " + this + " not attached to Activity"); + return false; + } + + if (getActivity().isFinishing()) { + MLog.warn(this, "activity is finishing"); + return false; + } + + if (Build.VERSION.SDK_INT >= 17 && getActivity().isDestroyed()) { + MLog.warn(this, "activity is isDestroyed"); + return false; + } + return true; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/ViewPagerAdapter.java b/app/src/main/java/com/yizhuan/erban/common/ViewPagerAdapter.java new file mode 100644 index 000000000..2c907ba10 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/ViewPagerAdapter.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.common; + +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + * Created by huangmeng1 on 2018/5/7. + */ + +public class ViewPagerAdapter extends FragmentPagerAdapter { + private List mFragmentList; + private String[] mTitleList; + public ViewPagerAdapter(FragmentManager fm, List mFragmentList, String[] mTitleList) { + super(fm); + this.mFragmentList = mFragmentList; + this.mTitleList = mTitleList; + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList.size(); + } + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return mTitleList[position]; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/permission/EasyPermissions.java b/app/src/main/java/com/yizhuan/erban/common/permission/EasyPermissions.java new file mode 100644 index 000000000..c3f3f30eb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/permission/EasyPermissions.java @@ -0,0 +1,297 @@ +/* + * Copyright Google Inc. All Rights Reserved. + * + * 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.yizhuan.erban.common.permission; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +/** + * Android M (API >= 23). + */ +public class EasyPermissions { + + public static final int SETTINGS_REQ_CODE = 16061; + + private static final String TAG = "EasyPermissions"; + + public interface PermissionCallbacks extends + ActivityCompat.OnRequestPermissionsResultCallback { + + void onPermissionsGranted(int requestCode, List perms); + + void onPermissionsDenied(int requestCode, List perms); + + void onPermissionsAllGranted(); + + } + + /** + + */ + public static boolean hasPermissions(Context context, String... perms) { + // Always return true for SDK < M, let the system deal with the permissions + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return true; + } + + for (String perm : perms) { + boolean hasPerm = (ContextCompat.checkSelfPermission(context, perm) == + PackageManager.PERMISSION_GRANTED); + if (!hasPerm) { + return false; + } + } + + return true; + } + + /** + + */ + public static void requestPermissions(final Object object, String rationale, + final int requestCode, final String... perms) { + requestPermissions(object, rationale, + android.R.string.ok, + android.R.string.cancel, + requestCode, perms); + } + + /** + + */ + public static void requestPermissions(final Object object, String rationale, + @StringRes int positiveButton, + @StringRes int negativeButton, + final int requestCode, final String... perms) { + + checkCallingObjectSuitability(object); + + boolean shouldShowRationale = false; + for (String perm : perms) { + shouldShowRationale = + shouldShowRationale || shouldShowRequestPermissionRationale(object, perm); + } + + if (shouldShowRationale) { + Activity activity = getActivity(object); + if (null == activity) { + return; + } + + AlertDialog dialog = new AlertDialog.Builder(activity) + .setMessage(rationale) + .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + executePermissionsRequest(object, perms, requestCode); + } + }) + .setNegativeButton(negativeButton, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // act as if the permissions were denied + if (object instanceof PermissionCallbacks) { + ((PermissionCallbacks) object).onPermissionsDenied(requestCode, Arrays.asList(perms)); + } + } + }).create(); + dialog.show(); + dialog.getButton(dialog.BUTTON_POSITIVE).setTextColor(Color.BLACK); + dialog.getButton(dialog.BUTTON_NEGATIVE).setTextColor(Color.BLACK); + } else { + executePermissionsRequest(object, perms, requestCode); + } + } + + /** + * + */ + public static void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults, Object object) { + + checkCallingObjectSuitability(object); + + // Make a collection of granted and denied permissions from the request. + ArrayList granted = new ArrayList<>(); + ArrayList denied = new ArrayList<>(); + for (int i = 0; i < permissions.length; i++) { + String perm = permissions[i]; + if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + granted.add(perm); + } else { + denied.add(perm); + } + } + + // Report granted permissions, if any. + if (!granted.isEmpty()) { + // Notify callbacks + if (object instanceof PermissionCallbacks) { + ((PermissionCallbacks) object).onPermissionsGranted(requestCode, granted); + } + } + + // Report denied permissions, if any. + if (!denied.isEmpty()) { + if (object instanceof PermissionCallbacks) { + ((PermissionCallbacks) object).onPermissionsDenied(requestCode, denied); + } + } + + // If 100% successful, call annotated methods + if (!granted.isEmpty() && denied.isEmpty()) { + if (object instanceof PermissionCallbacks) + ((PermissionCallbacks) object).onPermissionsAllGranted(); + } + } + + + public static boolean checkDeniedPermissionsNeverAskAgain(final Object object, + String rationale, + @StringRes int positiveButton, + @StringRes int negativeButton, + List deniedPerms) { + return checkDeniedPermissionsNeverAskAgain(object, rationale, + positiveButton, negativeButton, null, deniedPerms); + } + + + public static boolean checkDeniedPermissionsNeverAskAgain(final Object object, + String rationale, + @StringRes int positiveButton, + @StringRes int negativeButton, + @Nullable DialogInterface.OnClickListener negativeButtonOnClickListener, + List deniedPerms) { + boolean shouldShowRationale; + for (String perm : deniedPerms) { + shouldShowRationale = shouldShowRequestPermissionRationale(object, perm); + if (!shouldShowRationale) { + final Activity activity = getActivity(object); + if (null == activity) { + return true; + } + + AlertDialog dialog = new AlertDialog.Builder(activity) + .setMessage(rationale) + .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", activity.getPackageName(), null); + intent.setData(uri); + startAppSettingsScreen(object, intent); + } + }) + .setNegativeButton(negativeButton, negativeButtonOnClickListener) + .create(); + dialog.show(); + + return true; + } + } + + return false; + } + + @TargetApi(23) + private static boolean shouldShowRequestPermissionRationale(Object object, String perm) { + if (object instanceof Activity) { + return ActivityCompat.shouldShowRequestPermissionRationale((Activity) object, perm); + } else if (object instanceof Fragment) { + return ((Fragment) object).shouldShowRequestPermissionRationale(perm); + } else if (object instanceof android.app.Fragment) { + return ((android.app.Fragment) object).shouldShowRequestPermissionRationale(perm); + } else { + return false; + } + } + + @TargetApi(23) + private static void executePermissionsRequest(Object object, String[] perms, int requestCode) { + checkCallingObjectSuitability(object); + + if (object instanceof Activity) { + ActivityCompat.requestPermissions((Activity) object, perms, requestCode); + } else if (object instanceof Fragment) { + ((Fragment) object).requestPermissions(perms, requestCode); + } else if (object instanceof android.app.Fragment) { + ((android.app.Fragment) object).requestPermissions(perms, requestCode); + } + } + + @TargetApi(11) + private static Activity getActivity(Object object) { + if (object instanceof Activity) { + return ((Activity) object); + } else if (object instanceof Fragment) { + return ((Fragment) object).getActivity(); + } else if (object instanceof android.app.Fragment) { + return ((android.app.Fragment) object).getActivity(); + } else { + return null; + } + } + + @TargetApi(11) + private static void startAppSettingsScreen(Object object, + Intent intent) { + if (object instanceof Activity) { + ((Activity) object).startActivityForResult(intent, SETTINGS_REQ_CODE); + } else if (object instanceof Fragment) { + ((Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE); + } else if (object instanceof android.app.Fragment) { + ((android.app.Fragment) object).startActivityForResult(intent, SETTINGS_REQ_CODE); + } + } + + + private static void checkCallingObjectSuitability(Object object) { + // Make sure Object is an Activity or Fragment + boolean isActivity = object instanceof Activity; + boolean isSupportFragment = object instanceof Fragment; + boolean isAppFragment = object instanceof android.app.Fragment; + boolean isMinSdkM = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + + if (!(isSupportFragment || isActivity || (isAppFragment && isMinSdkM))) { + if (isAppFragment) { + throw new IllegalArgumentException( + "Target SDK needs to be greater than 23 if caller is android.app.Fragment"); + } else { + throw new IllegalArgumentException("Caller must be an Activity or a Fragment."); + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/permission/PermissionActivity.java b/app/src/main/java/com/yizhuan/erban/common/permission/PermissionActivity.java new file mode 100644 index 000000000..227d8271e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/permission/PermissionActivity.java @@ -0,0 +1,134 @@ +package com.yizhuan.erban.common.permission; + + +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; + + +import com.yizhuan.erban.R; + +import java.util.List; + + +/* + * @创建者 Jrking + * @创建时间 2016/4/15 16:18 + * @描述 ${Activity基类 } + * @更新描述 ${适配6.0权限问题} + */ +public class PermissionActivity extends AppCompatActivity implements + EasyPermissions.PermissionCallbacks { + + protected static final int RC_PERM = 123; + + protected static int reSting = R.string.ask_again;//默认提示语句 + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// initStatusBar("#303F9F");//透明状态栏 + } + + public void initStatusBar(String strColor) { + StatusBarCompat.setStatusBarColor(this, Color.parseColor(strColor)); + StatusBarCompat.translucentStatusBar(this); + } + + @Override + protected void onStart() { + super.onStart(); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + + /** + * 权限回调接口 + */ + private CheckPermListener mListener; + + public interface CheckPermListener { + //权限通过后的回调方法 + void superPermission(); + } + + public void checkPermission(CheckPermListener listener, int resString, String... mPerms) { + mListener = listener; + if (EasyPermissions.hasPermissions(this, mPerms)) { + if (mListener != null) + mListener.superPermission(); + } else { + EasyPermissions.requestPermissions(this, getString(resString), + RC_PERM, mPerms); + } + } + + /** + * 用户权限处理, + * 如果全部获取, 则直接过. + * 如果权限缺失, 则提示Dialog. + * + * @param requestCode 请求码 + * @param permissions 权限 + * @param grantResults 结果 + */ + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == EasyPermissions.SETTINGS_REQ_CODE) { + //设置返回 + } + } + + + @Override + public void onPermissionsGranted(int requestCode, List perms) { + //同意了某些权限可能不是全部 + } + + @Override + public void onPermissionsAllGranted() { + if (mListener != null) + mListener.superPermission();//同意了全部权限的回调 + } + + @Override + public void onPermissionsDenied(int requestCode, List perms) { + + EasyPermissions.checkDeniedPermissionsNeverAskAgain(this, + getString(R.string.perm_tip), + R.string.setting, R.string.cancel, null, perms); + } + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/permission/StatusBarCompat.java b/app/src/main/java/com/yizhuan/erban/common/permission/StatusBarCompat.java new file mode 100644 index 000000000..b491c5a9b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/permission/StatusBarCompat.java @@ -0,0 +1,161 @@ +package com.yizhuan.erban.common.permission; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.support.v4.view.ViewCompat; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; + +/** + * Utils for status bar + * Created by qiu on 3/29/16. + */ +public class StatusBarCompat { + + private static final int COLOR_TRANSLUCENT = Color.parseColor("#00000000"); + + public static final int DEFAULT_COLOR_ALPHA = 112; + + /** + * set statusBarColor + * @param statusColor color + * @param alpha 0 - 255 + */ + public static void setStatusBarColor(Activity activity, int statusColor, int alpha) { + setStatusBarColor(activity, calculateStatusBarColor(statusColor, alpha)); + } + + public static void setStatusBarColor(Activity activity, int statusColor) { + Window window = activity.getWindow(); + ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + //First translucent status bar. + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //After LOLLIPOP not translucent status bar + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + //Then call setStatusBarColor. + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(statusColor); + //set child View not fill the system window + View mChildView = mContentView.getChildAt(0); + if (mChildView != null) { + ViewCompat.setFitsSystemWindows(mChildView, true); + } + } else { + ViewGroup mDecorView = (ViewGroup) window.getDecorView(); + if (mDecorView.getTag() != null && mDecorView.getTag() instanceof Boolean && (Boolean)mDecorView.getTag()) { + //if has add fake status bar view + View mStatusBarView = mDecorView.getChildAt(0); + if (mStatusBarView != null) { + mStatusBarView.setBackgroundColor(statusColor); + } + } else { + int statusBarHeight = getStatusBarHeight(activity); + //add margin + View mContentChild = mContentView.getChildAt(0); + if (mContentChild != null) { + ViewCompat.setFitsSystemWindows(mContentChild, false); + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams(); + lp.topMargin += statusBarHeight; + mContentChild.setLayoutParams(lp); + } + //add fake status bar view + View mStatusBarView = new View(activity); + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight); + layoutParams.gravity = Gravity.TOP; + mStatusBarView.setLayoutParams(layoutParams); + mStatusBarView.setBackgroundColor(statusColor); + mDecorView.addView(mStatusBarView, 0); + mDecorView.setTag(true); + } + } + } + } + + public static void translucentStatusBar(Activity activity) { + translucentStatusBar(activity, false); + } + + /** + * change to full screen mode + * @param hideStatusBarBackground hide status bar alpha Background when SDK > 21, true if hide it + */ + public static void translucentStatusBar(Activity activity, boolean hideStatusBarBackground) { + Window window = activity.getWindow(); + ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT); + + //set child View not fill the system window + View mChildView = mContentView.getChildAt(0); + if (mChildView != null) { + ViewCompat.setFitsSystemWindows(mChildView, false); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int statusBarHeight = getStatusBarHeight(activity); + + //First translucent status bar. + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + //After LOLLIPOP just set LayoutParams. + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + if (hideStatusBarBackground) { + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.setStatusBarColor(COLOR_TRANSLUCENT); + } else { + window.setStatusBarColor(calculateStatusBarColor(COLOR_TRANSLUCENT, DEFAULT_COLOR_ALPHA)); + } + //must call requestApplyInsets, otherwise it will have space in screen bottom + if (mChildView != null) { + ViewCompat.requestApplyInsets(mChildView); + } + } else { + ViewGroup mDecorView = (ViewGroup) window.getDecorView(); + if (mDecorView.getTag() != null && mDecorView.getTag() instanceof Boolean && (Boolean)mDecorView.getTag()) { + mChildView = mDecorView.getChildAt(0); + //remove fake status bar view. + mContentView.removeView(mChildView); + mChildView = mContentView.getChildAt(0); + if (mChildView != null) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mChildView.getLayoutParams(); + //cancel the margin top + if (lp != null && lp.topMargin >= statusBarHeight) { + lp.topMargin -= statusBarHeight; + mChildView.setLayoutParams(lp); + } + } + mDecorView.setTag(false); + } + } + } + } + + //Get status bar height + public static int getStatusBarHeight(Context context) { + int result = 0; + int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resId > 0) { + result = context.getResources().getDimensionPixelOffset(resId); + } + return result; + } + + //Get alpha color + private static int calculateStatusBarColor(int color, int alpha) { + float a = 1 - alpha / 255f; + int red = color >> 16 & 0xff; + int green = color >> 8 & 0xff; + int blue = color & 0xff; + red = (int) (red * a + 0.5); + green = (int) (green * a + 0.5); + blue = (int) (blue * a + 0.5); + return 0xff << 24 | red << 16 | green << 8 | blue; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/server/NetworkService.java b/app/src/main/java/com/yizhuan/erban/common/server/NetworkService.java new file mode 100644 index 000000000..65f2f4462 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/server/NetworkService.java @@ -0,0 +1,204 @@ +package com.yizhuan.erban.common.server; + +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.IBinder; +import android.util.Log; + +public class NetworkService extends Service { + + // Class that answers queries about the state of network connectivity. + // 系统网络连接相关的操作管理类. + + private ConnectivityManager connectivityManager; + // Describes the status of a network interface. + // 网络状态信息的实例 + private NetworkInfo info; + + /** + * 当前处于的网络 0 :null 1 :2G/3G 2 :wifi + */ + public static int netState; + + public static final String ACTION_NETWORK_STATE_CHANGE_SUCCESS = "ACTION_NETWORK_STATE_CHANGE_SUCCESS"; // An + // action + public static final String ACTION_NETWORK_STATE_CHANGE_FAILED = "ACTION_NETWORK_STATE_CHANGE_FAILED"; // An + private String TAG = "NetworkService"; + + private int count = -1; + + + /** + * 广播实例 + */ + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + System.out.println("收到网络改变广播!"); + // The action of this intent or null if none is specified. + // action是行动的意思,也许是我水平问题无法理解为什么叫行动,我一直理解为标识(现在理解为意图) + String action = intent.getAction(); // 当前接受到的广播的标识(行动/意图) + + // 当当前接受到的广播的标识(意图)为网络状态的标识时做相应判断 + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + // 获取网络连接管理器 + connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + + // 获取当前网络状态信息 + info = connectivityManager.getActiveNetworkInfo(); + + if (info != null && info.isAvailable()) { + + // 当NetworkInfo不为空且是可用的情况下,获取当前网络的Type状态 + // 根据NetworkInfo.getTypeName()判断当前网络 + String name = info.getTypeName(); + + // 更改NetworkService的静态变量,之后只要在Activity中进行判断就好了 + if (name.equals("WIFI")) { + netState = 2; + } else { + netState = 1; + } + + } else { + // NetworkInfo为空或者是不可用的情况下 + netState = 0; + +// Toast.makeText(context, "没有可用网络!\n请连接网络后刷新本界面", Toast.LENGTH_SHORT).show(); + + /** + * 这里推荐使用本地广播的方式发送: + * LocalBroadcastManager.getInstance(getApplicationContext() + * ).sendBroadcast(intent); + */ + } + + if(netState == 0){ + sendNetBroadCast(ACTION_NETWORK_STATE_CHANGE_FAILED,netState); + Log.d(TAG, "网络已断开"); + }else{ +// if (count != -1) { +// if (!ConnectionManager.getInstance().getConnection().isConnected()) { +// Log.d(TAG, "启动重连服务器!切换网络计数:" + count); +// ChatManager.getInstance().reconnect(ChatManager.getInstance().getWorkHandler());// 重连服务器 +// } +// Log.d(TAG, "网络已链接"); +// } + count++; + } + +// switch (netState) { +// case 2:// WIFI +// Log.d(TAG, "已切换为wifi"); +// if (count != -1) { +// if (!ConnectionManager.getInstance().getConnection().isConnected()) { +// Log.d(TAG, "启动重连服务器!切换网络计数:" + count); +// ChatManager.getInstance().reconnect(ChatManager.getInstance().getWorkHandler());// 重连服务器 +// } +// +// } +// count++; +// break; +// case 1:// other +// Log.d(TAG, "已切换为手机网络"); +// if (count != -1) { +// if (!ConnectionManager.getInstance().getConnection().isConnected()) { +// Log.d(TAG, "启动重连服务器!切换网络计数:" + count); +// ChatManager.getInstance().reconnect(ChatManager.getInstance().getWorkHandler());// 重连服务器 +// } +// +// } +// count++; +// break; +// case 0:// no net +// Log.d(TAG, "网络已断开"); +// break; +// +// default: +// break; +// } + + + } + } + }; + + /** + * 网络链接上的广播 + */ + public void sendNetBroadCast(String action, int netState){ + Intent it = new Intent(); + it.putExtra("networkStatus", netState); + it.setAction(action); + sendBroadcast(it); // 发送无网络广播给注册了当前服务广播的Activity + } + +// private ChatMsgFactory msgFactory; +// private ChatManager chatManager; + + // /** + // * 发送文字消息 + // */ + // private void sendTextReConnected(ChatMsg msg) { + // SendMsg sendMsg = msgFactory.creatSendMsgForGroupText(msg.getToUserId(), + // msg.getChatId(), msg.getContent()); + // chatManager.sendText(sendMsg); + // } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + System.out.println("服务被创建"); +// msgFactory = ChatMsgFactory.getInstance(); +// chatManager = ChatManager.getInstance(); + + // 注册网络状态的广播,绑定到mReceiver + IntentFilter mFilter = new IntentFilter(); + mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + registerReceiver(mReceiver, mFilter); + } + + @Override + public void onDestroy() { + super.onDestroy(); + System.out.println("服务被销毁"); + // 注销接收 + unregisterReceiver(mReceiver); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } + + /** + * 判断网络是否可用 + */ + public static boolean isNetworkAvailable(Context context) { + // 获取网络连接管理器 + ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + // 获取当前网络状态信息 + NetworkInfo[] info = mgr.getAllNetworkInfo(); + if (info != null) { + for (int i = 0; i < info.length; i++) { + if (info[i].getState() == NetworkInfo.State.CONNECTED) { + return true; + } + } + } + + return false; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaCallback.java b/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaCallback.java new file mode 100644 index 000000000..22351687c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaCallback.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.common.svga; + +import com.opensource.svgaplayer.SVGACallback; + +/** + * Created by MadisonRong on 31/03/2018. + */ + +public class SimpleSvgaCallback implements SVGACallback { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaParseCompletion.java b/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaParseCompletion.java new file mode 100644 index 000000000..be02abbba --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/svga/SimpleSvgaParseCompletion.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.common.svga; + +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; + +/** + * Created by MadisonRong on 31/03/2018. + */ + +public class SimpleSvgaParseCompletion implements SVGAParser.ParseCompletion { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + + } + + @Override + public void onError() { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/AgeSexView.java b/app/src/main/java/com/yizhuan/erban/common/widget/AgeSexView.java new file mode 100644 index 000000000..c2fee132c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/AgeSexView.java @@ -0,0 +1,56 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by zhouxiangfeng on 17/2/26. + */ + +public class AgeSexView extends LinearLayout { + + private ImageView sexIv; + private TextView ageTv; + + public AgeSexView(Context context) { + super(context); + init(); + } + + public AgeSexView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public AgeSexView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init(){ + View mView = LayoutInflater.from(getContext()).inflate(R.layout.layout_zone_age_sex_view,this,true); + sexIv = (ImageView)mView.findViewById(R.id.sex_iv); + ageTv = (TextView)mView.findViewById(R.id.age_tv); + } + + + + public AgeSexView setSexImg(int resId){ + sexIv.setImageResource(resId); + return this; + } + + + public AgeSexView setAgeText(int age){ + ageTv.setText(String.valueOf(age)); + return this; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/BadgeView.java b/app/src/main/java/com/yizhuan/erban/common/widget/BadgeView.java new file mode 100644 index 000000000..9f38c8fed --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/BadgeView.java @@ -0,0 +1,447 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.Typeface; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; +import android.widget.TabWidget; +import android.widget.TextView; + +/** + * A simple text label view that can be applied as a "badge" to any given {@link View}. + * This class is intended to be instantiated at runtime rather than included in XML layouts. + * + * @author Jeff Gilfelt + */ +public class BadgeView extends TextView { + + public static final int POSITION_TOP_LEFT = 1; + public static final int POSITION_TOP_RIGHT = 2; + public static final int POSITION_BOTTOM_LEFT = 3; + public static final int POSITION_BOTTOM_RIGHT = 4; + public static final int MY_POSITION_TOP_LEFT = 5; + + private static final int DEFAULT_MARGIN_DIP = 5; + private static final int DEFAULT_LR_PADDING_DIP = 5; + private static final int DEFAULT_CORNER_RADIUS_DIP = 8; + private static final int DEFAULT_POSITION = POSITION_TOP_RIGHT; + private static final int DEFAULT_BADGE_COLOR = Color.RED; + private static final int DEFAULT_TEXT_COLOR = Color.WHITE; + + private static Animation fadeIn; + private static Animation fadeOut; + + private Context context; + private View target; + + private int badgePosition; + private int badgeMargin; + private int badgeColor; + + private boolean isShown; + + private ShapeDrawable badgeBg; + + private int targetTabIndex; + + + public BadgeView(Context context) { + this(context, (AttributeSet) null, android.R.attr.textViewStyle); + } + + public BadgeView(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.textViewStyle); + } + + /** + * Constructor - + * + * create a new BadgeView instance attached to a target {@link View}. + * + * @param context context for this view. + * @param target the View to attach the badge to. + */ + public BadgeView(Context context, View target) { + this(context, null, android.R.attr.textViewStyle, target, 0); + } + + /** + * Constructor - + * + * create a new BadgeView instance attached to a target {@link TabWidget} + * tab at a given index. + * + * @param context context for this view. + * @param target the TabWidget to attach the badge to. + * @param index the position of the tab within the target. + */ + public BadgeView(Context context, TabWidget target, int index) { + this(context, null, android.R.attr.textViewStyle, target, index); + } + + public BadgeView(Context context, AttributeSet attrs, int defStyle) { + this(context, attrs, defStyle, null, 0); + } + + public BadgeView(Context context, AttributeSet attrs, int defStyle, View target, int tabIndex) { + super(context, attrs, defStyle); + init(context, target, tabIndex); + } + + private void init(Context context, View target, int tabIndex) { + + this.context = context; + this.target = target; + this.targetTabIndex = tabIndex; + + // apply defaults + badgePosition = DEFAULT_POSITION; + badgeMargin = dipToPixels(DEFAULT_MARGIN_DIP); + badgeColor = DEFAULT_BADGE_COLOR; + + setTypeface(Typeface.DEFAULT_BOLD); + int paddingPixels = dipToPixels(DEFAULT_LR_PADDING_DIP); + setPadding(paddingPixels, 0, paddingPixels, 0); + setTextColor(DEFAULT_TEXT_COLOR); + + fadeIn = new AlphaAnimation(0, 1); + fadeIn.setInterpolator(new DecelerateInterpolator()); + fadeIn.setDuration(200); + + fadeOut = new AlphaAnimation(1, 0); + fadeOut.setInterpolator(new AccelerateInterpolator()); + fadeOut.setDuration(200); + + isShown = false; + + if (this.target != null) { + applyTo(this.target); + } else { + show(); + } + + } + + private void applyTo(View target) { + + LayoutParams lp = target.getLayoutParams(); + ViewParent parent = target.getParent(); + FrameLayout container = new FrameLayout(context); + + if (target instanceof TabWidget) { + + // set target to the relevant tab child container + target = ((TabWidget) target).getChildTabViewAt(targetTabIndex); + this.target = target; + + ((ViewGroup) target).addView(container, + new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + + this.setVisibility(View.GONE); + container.addView(this); + + } else { + + // TODO verify that parent is indeed a ViewGroup + ViewGroup group = (ViewGroup) parent; + int index = group.indexOfChild(target); + + group.removeView(target); + group.addView(container, index, lp); + + container.addView(target); + + this.setVisibility(View.GONE); + container.addView(this); + + group.invalidate(); + + } + + } + + /** + * Make the badge visible in the UI. + * + */ + public void show() { + show(false, null); + } + + /** + * Make the badge visible in the UI. + * + * @param animate flag to apply the default fade-in animation. + */ + public void show(boolean animate) { + show(animate, fadeIn); + } + + /** + * Make the badge visible in the UI. + * + * @param anim Animation to apply to the view when made visible. + */ + public void show(Animation anim) { + show(true, anim); + } + + /** + * Make the badge non-visible in the UI. + * + */ + public void hide() { + hide(false, null); + } + + /** + * Make the badge non-visible in the UI. + * + * @param animate flag to apply the default fade-out animation. + */ + public void hide(boolean animate) { + hide(animate, fadeOut); + } + + /** + * Make the badge non-visible in the UI. + * + * @param anim Animation to apply to the view when made non-visible. + */ + public void hide(Animation anim) { + hide(true, anim); + } + + /** + * Toggle the badge visibility in the UI. + * + */ + public void toggle() { + toggle(false, null, null); + } + + /** + * Toggle the badge visibility in the UI. + * + * @param animate flag to apply the default fade-in/out animation. + */ + public void toggle(boolean animate) { + toggle(animate, fadeIn, fadeOut); + } + + /** + * Toggle the badge visibility in the UI. + * + * @param animIn Animation to apply to the view when made visible. + * @param animOut Animation to apply to the view when made non-visible. + */ + public void toggle(Animation animIn, Animation animOut) { + toggle(true, animIn, animOut); + } + + private void show(boolean animate, Animation anim) { + if (getBackground() == null) { + if (badgeBg == null) { + badgeBg = getDefaultBackground(); + } + setBackgroundDrawable(badgeBg); + } + applyLayoutParams(); + + if (animate) { + this.startAnimation(anim); + } + this.setVisibility(View.VISIBLE); + isShown = true; + } + + private void hide(boolean animate, Animation anim) { + this.setVisibility(View.GONE); + if (animate) { + this.startAnimation(anim); + } + isShown = false; + } + + private void toggle(boolean animate, Animation animIn, Animation animOut) { + if (isShown) { + hide(animate && (animOut != null), animOut); + } else { + show(animate && (animIn != null), animIn); + } + } + + /** + * Increment the numeric badge label. If the current badge label cannot be converted to + * an integer value, its label will be set to "0". + * + * @param offset the increment offset. + */ + public int increment(int offset) { + CharSequence txt = getText(); + int i; + if (txt != null) { + try { + i = Integer.parseInt(txt.toString()); + } catch (NumberFormatException e) { + i = 0; + } + } else { + i = 0; + } + i = i + offset; + setText(String.valueOf(i)); + return i; + } + + /** + * Decrement the numeric badge label. If the current badge label cannot be converted to + * an integer value, its label will be set to "0". + * + * @param offset the decrement offset. + */ + public int decrement(int offset) { + return increment(-offset); + } + + private ShapeDrawable getDefaultBackground() { + + int r = dipToPixels(DEFAULT_CORNER_RADIUS_DIP); + float[] outerR = new float[] {r, r, r, r, r, r, r, r}; + + RoundRectShape rr = new RoundRectShape(outerR, null, null); + ShapeDrawable drawable = new ShapeDrawable(rr); + drawable.getPaint().setColor(badgeColor); + + return drawable; + + } + + private void applyLayoutParams() { + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + int width = getWidth(); + switch (badgePosition) { + + case MY_POSITION_TOP_LEFT: + lp.gravity = Gravity.LEFT | Gravity.TOP; + lp.setMargins(badgeMargin + target.getWidth()/8+ 15 , badgeMargin, 0, 0); + break; + + case POSITION_TOP_LEFT: + lp.gravity = Gravity.LEFT | Gravity.TOP; + lp.setMargins(badgeMargin, badgeMargin, 0, 0); + break; + case POSITION_TOP_RIGHT: + lp.gravity = Gravity.RIGHT | Gravity.TOP; + lp.setMargins(0, badgeMargin, badgeMargin, 0); + break; + case POSITION_BOTTOM_LEFT: + lp.gravity = Gravity.LEFT | Gravity.BOTTOM; + lp.setMargins(badgeMargin, 0, 0, badgeMargin); + break; + case POSITION_BOTTOM_RIGHT: + lp.gravity = Gravity.RIGHT | Gravity.BOTTOM; + lp.setMargins(0, 0, badgeMargin, badgeMargin); + break; + default: + break; + } + + setLayoutParams(lp); + + } + + /** + * Returns the target View this badge has been attached to. + * + */ + public View getTarget() { + return target; + } + + /** + * Is this badge currently visible in the UI? + * + */ + @Override + public boolean isShown() { + return isShown; + } + + /** + * Returns the positioning of this badge. + * + * one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT. + * + */ + public int getBadgePosition() { + return badgePosition; + } + + /** + * Set the positioning of this badge. + * + * @param layoutPosition one of POSITION_TOP_LEFT, POSITION_TOP_RIGHT, POSITION_BOTTOM_LEFT, POSITION_BOTTOM_RIGHT. + * + */ + public void setBadgePosition(int layoutPosition) { + this.badgePosition = layoutPosition; + } + + /** + * Returns the horizontal/vertical margin from the target View that is applied to this badge. + * + */ + public int getBadgeMargin() { + return badgeMargin; + } + + /** + * Set the horizontal/vertical margin from the target View that is applied to this badge. + * + * @param badgeMargin the margin in pixels. + */ + public void setBadgeMargin(int badgeMargin) { + this.badgeMargin = badgeMargin; + } + + /** + * Returns the color value of the badge background. + * + */ + public int getBadgeBackgroundColor() { + return badgeColor; + } + + /** + * Set the color value of the badge background. + * + * @param badgeColor the badge background color. + */ + public void setBadgeBackgroundColor(int badgeColor) { + this.badgeColor = badgeColor; + badgeBg = getDefaultBackground(); + } + + private int dipToPixels(int dip) { + Resources r = getResources(); + float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, r.getDisplayMetrics()); + return (int) px; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/ChangeColorIconWithText.java b/app/src/main/java/com/yizhuan/erban/common/widget/ChangeColorIconWithText.java new file mode 100644 index 000000000..9321dccd7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/ChangeColorIconWithText.java @@ -0,0 +1,278 @@ +package com.yizhuan.erban.common.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.os.Bundle; +import android.os.Looper; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; + +import com.yizhuan.erban.R; + + +public class ChangeColorIconWithText extends View { + + private int mColor = 0xFF636363; + private Bitmap mIconBitmap; + private String mText = ""; + private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, + getResources().getDisplayMetrics()); + + private Canvas mCanvas; + private Bitmap mBitmap; + private Paint mPaint; + + private float mAlpha; + + private Rect mIconRect; + private Rect mTextBound; + private Paint mTextPaint; + private String TAG = "ChangeColorIconWithText"; + + public ChangeColorIconWithText(Context context) { + this(context, null); + } + + public ChangeColorIconWithText(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /** + * 获取自定义属性的值 + * + * @param context + * @param attrs + * @param defStyleAttr + */ + public ChangeColorIconWithText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChangeColorIconWithText); + + int n = a.getIndexCount(); + + for (int i = 0; i < n; i++) { + int attr = a.getIndex(i); + switch (attr) { + case R.styleable.ChangeColorIconWithText_icon: + BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr); + mIconBitmap = drawable.getBitmap(); + break; + case R.styleable.ChangeColorIconWithText_color: + mColor = a.getColor(attr, 0xFF636363); + break; + case R.styleable.ChangeColorIconWithText_text: + mText = a.getString(attr); + break; + case R.styleable.ChangeColorIconWithText_text_size: + mTextSize = (int) a.getDimension(attr, + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics())); + break; + } + + } + + a.recycle(); + + mTextBound = new Rect(); + mTextPaint = new Paint(); + mTextPaint.setTextSize(mTextSize); + mTextPaint.setColor(mColor); + mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound); + } + + /** + * 图片宽和高的比例 + */ + private float ratio = 1f; + + public void setRatio(float ratio) { + this.ratio = ratio; + } + + @SuppressLint("DrawAllocation") + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + // 父容器传过来的宽度方向上的模式 + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + // 父容器传过来的高度方向上的模式 + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + + // 父容器传过来的宽度的值 + int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() + - getPaddingRight(); + // 父容器传过来的高度的值 + int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingLeft() + - getPaddingRight(); + + if (widthMode == MeasureSpec.EXACTLY + && heightMode != MeasureSpec.EXACTLY) { + // 判断条件为,宽度模式为Exactly,也就是填充父窗体或者是指定宽度; + // 且高度模式不是Exaclty,代表设置的既不是fill_parent也不是具体的值,于是需要具体测量 + // 且图片的宽高比已经赋值完毕,不再是0.0f + // 表示宽度确定,要测量高度 + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, + MeasureSpec.EXACTLY); + } else if (widthMode != MeasureSpec.EXACTLY + && heightMode == MeasureSpec.EXACTLY) { + // 判断条件跟上面的相反,宽度方向和高度方向的条件互换 + // 表示高度确定,要测量宽度 + + widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, + MeasureSpec.EXACTLY); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), + getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - mTextBound.height()); +// Log.d(TAG, String.valueOf(iconWidth)); + int left = getMeasuredWidth() / 2 - iconWidth / 2; + int top = getMeasuredHeight() / 2 - (mTextBound.height() + iconWidth) / 2; + mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth); + + } + + public static int resolveSize(int size, int measureSpec) { + int result = size; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + switch (specMode) { + case MeasureSpec.UNSPECIFIED: + result = size; + break; + case MeasureSpec.AT_MOST: + result = Math.min(size, specSize); + break; + case MeasureSpec.EXACTLY: + result = specSize; + break; + } + return result; + } + + + @Override + protected void onDraw(Canvas canvas) { + if (null != mIconBitmap) { + canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawBitmap(mIconBitmap, null, mIconRect, null); + + int alpha = (int) Math.ceil(255 * mAlpha); + + // 内存去准备mBitmap , setAlpha , 纯色 ,xfermode , 图标 + setupTargetBitmap(alpha); + // 1、绘制原文本 ; 2、绘制变色的文本 + drawSourceText(canvas, alpha); + drawTargetText(canvas, alpha); + // drawCircleText(canvas, alpha); + + canvas.drawBitmap(mBitmap, 0, 0, null); + } + + } + + /** + * 绘制变色的文本 + * + * @param canvas + * @param alpha + */ + private void drawTargetText(Canvas canvas, int alpha) { + mTextPaint.setColor(mColor); + mTextPaint.setAlpha(alpha); + mTextPaint.setAntiAlias(true); + int x = getMeasuredWidth() / 2 - mTextBound.width() / 2; + int y = mIconRect.bottom + mTextBound.height(); + canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawText(mText, x, y, mTextPaint); + + } + + /** + * 绘制原文本 + * + * @param canvas + * @param alpha + */ + private void drawSourceText(Canvas canvas, int alpha) { + mTextPaint.setColor(0xff636363); + mTextPaint.setAlpha(255 - alpha); + mTextPaint.setAntiAlias(true); + int x = getMeasuredWidth() / 2 - mTextBound.width() / 2; + int y = mIconRect.bottom + mTextBound.height(); + canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawText(mText, x, y, mTextPaint); + + } + + /** + * 在内存中绘制可变色的Icon + */ + private void setupTargetBitmap(int alpha) { + mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Config.ARGB_8888); + mCanvas = new Canvas(mBitmap); + mPaint = new Paint(); + mPaint.setColor(mColor); + mPaint.setAntiAlias(true); + mPaint.setDither(true); + mPaint.setAlpha(alpha); + mCanvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + mCanvas.drawRect(mIconRect, mPaint); + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + mPaint.setAlpha(255); + mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint); + } + + private static final String INSTANCE_STATUS = "instance_status"; + private static final String STATUS_ALPHA = "status_alpha"; + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState()); + bundle.putFloat(STATUS_ALPHA, mAlpha); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mAlpha = bundle.getFloat(STATUS_ALPHA); + super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS)); + return; + } + super.onRestoreInstanceState(state); + } + + public void setIconAlpha(float alpha) { + this.mAlpha = alpha; + invalidateView(); + } + + /** + * 重绘 + */ + private void invalidateView() { + if (Looper.getMainLooper() == Looper.myLooper()) { + invalidate(); + } else { + postInvalidate(); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/CircleGradualImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/CircleGradualImageView.java new file mode 100644 index 000000000..b2b65fb20 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/CircleGradualImageView.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RadialGradient; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.util.AttributeSet; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.CircleCrop; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * Created by MadisonRong on 23/04/2018. + */ + +public class CircleGradualImageView extends android.support.v7.widget.AppCompatImageView { + + private static final String TAG = "CircleGradualImageView"; + + private volatile float centreX; + private volatile float centreY; + private volatile float radius; + private float borderWidth; + private int borderColor; + private Paint bitmapPaint; + private Paint borderPaint; + private Shader shader; + private Rect dst; + private Bitmap bitmap; + + public CircleGradualImageView(Context context) { + this(context, null); + } + + public CircleGradualImageView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleGradualImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyle) { + TypedArray typedArray = + context.obtainStyledAttributes(attrs, R.styleable.CircleGradualImageView, + defStyle, 0); + borderColor = typedArray.getColor(R.styleable.CircleGradualImageView_cgiv_border_color, + ContextCompat.getColor(context, R.color.appColor)); + borderWidth = typedArray.getDimension(R.styleable.CircleGradualImageView_cgiv_border_width, + UIUtil.dip2px(context, 2)); + typedArray.recycle(); + + bitmapPaint = new Paint(); + bitmapPaint.setAntiAlias(true); + bitmapPaint.setFilterBitmap(true); + + borderPaint = new Paint(); + borderPaint.setAntiAlias(true); + borderPaint.setFilterBitmap(true); + } + + public void setImage(String url) { + GlideApp.with(getContext().getApplicationContext()).load(url) + .override(getWidth() - (int) borderWidth * 2, getHeight() - (int) borderWidth * 2) + .transform(new CircleCrop() { + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + bitmap = super.transform(pool, toTransform, outWidth, outHeight); + return bitmap; + } + }) + .centerCrop() + .placeholder(R.drawable.default_user_head) + .error(R.drawable.default_cover) + .dontAnimate() + .diskCacheStrategy(DiskCacheStrategy.DATA) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + postInvalidate(); + return true; + } + }) + .into(this); + + } + + @Override + protected void onDraw(Canvas canvas) { + centreX = getMeasuredWidth() / 2; + centreY = getMeasuredHeight() / 2; + radius = centreX > centreY ? centreY : centreX; + radius += borderWidth; + if (shader == null) { + shader = new RadialGradient(centreX, centreY, radius, borderColor, + ContextCompat.getColor(getContext(), R.color.transparent), Shader.TileMode.CLAMP); + } + borderPaint.setShader(shader); + canvas.drawCircle(centreX, centreY, radius, borderPaint); + + if (bitmap != null) { + if (dst == null) { + dst = new Rect((int) borderWidth, (int) borderWidth, + (int) (getWidth() - borderWidth), (int) (getHeight() - borderWidth)); + } + canvas.drawBitmap(bitmap, dst, dst, bitmapPaint); + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/CircleImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/CircleImageView.java new file mode 100644 index 000000000..383806a84 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/CircleImageView.java @@ -0,0 +1,259 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.yizhuan.erban.R; + + +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private boolean mReady; + private boolean mSetupPending; + + public CircleImageView(Context context) { + this(context, null); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_cborder_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_cborder_color, DEFAULT_BORDER_COLOR); + + a.recycle(); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (getDrawable() == null) { + return; + } + + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); + if (mBorderWidth != 0) { + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + mBitmap = bm; + setup(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + mBitmap = getBitmapFromDrawable(drawable); + setup(); + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (OutOfMemoryError e) { + return null; + } + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (mBitmap == null) { + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(0, 0, getWidth(), getHeight()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); + + mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); + mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); + + updateShaderMatrix(); + invalidate(); +// mBitmap = null; + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/CustomImageSpan.java b/app/src/main/java/com/yizhuan/erban/common/widget/CustomImageSpan.java new file mode 100644 index 000000000..d36abc94a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/CustomImageSpan.java @@ -0,0 +1,203 @@ +package com.yizhuan.erban.common.widget; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.text.style.ImageSpan; +import android.widget.TextView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.lang.ref.WeakReference; + +public class CustomImageSpan extends ImageSpan { + + private String url; + private WeakReference reference; + private boolean loading; + private int width; + private int height; + private Drawable drawable; + + public CustomImageSpan(Drawable drawable) { + super(drawable); + this.drawable = drawable; + } + + public CustomImageSpan(Drawable defaultDrawable, TextView textView, String url) { + super(defaultDrawable); + this.url = url; + this.reference = new WeakReference<>(textView); + this.drawable = defaultDrawable; + getDrawable().setBounds(0, 0, UIUtil.dip2px(textView.getContext(), 55), height); + loadPicAsyncNoWidthHeight(); + } + + public CustomImageSpan(Drawable defaultDrawable, TextView textView, String url, int width, int height) { + super(defaultDrawable); + this.url = url; + this.reference = new WeakReference<>(textView); + this.width = width; + this.height = height; + this.drawable = defaultDrawable; + getDrawable().setBounds(0, 0, width, height); + loadPicAsync(); + } + + private void loadPicAsyncNoWidthHeight() { + if (!loading && !TextUtils.isEmpty(url) && reference.get() != null) { + if (isDestroyedActivity(reference.get().getContext())) { + return; + } + try { + loading = true; + GlideApp.with(reference.get()) + .asDrawable() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .dontAnimate() + .dontTransform() + .load(url) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + loading = false; + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + loading = false; + TextView textView = reference.get(); + if (textView == null || resource == null) return true; + CustomImageSpan.this.drawable = resource; + int i = resource.getMinimumHeight() / 15; + CustomImageSpan.this.drawable.setBounds(0, 0, + UIUtil.dip2px(textView.getContext(), resource.getIntrinsicWidth() / i), + UIUtil.dip2px(textView.getContext(), resource.getMinimumHeight() % 15 == 0 ? 15 : 17)); + textView.postInvalidate(); + return true; + } + }) + .submit(); + } catch (Exception e) { + loading = false; + e.printStackTrace(); + } + } + } + + private boolean isDestroyedActivity(Context context) { + return context instanceof Activity && ((Activity) context).isDestroyed(); + } + + private void loadPicAsync() { + if (!loading && !TextUtils.isEmpty(url) && reference.get() != null) { + if (isDestroyedActivity(reference.get().getContext())) { + return; + } + try { + loading = true; + GlideApp.with(reference.get()) + .asDrawable() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .dontAnimate() + .dontTransform() + .override(width, height) + .load(url) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + loading = false; + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + loading = false; + TextView textView = reference.get(); + if (textView == null || resource == null) return true; + CustomImageSpan.this.drawable = resource; + CustomImageSpan.this.drawable.setBounds(0, 0, width, height); + textView.postInvalidate(); + return true; + } + }) + .submit(); + } catch (Exception e) { + loading = false; + e.printStackTrace(); + } + } + } + + @Override + public Drawable getDrawable() { + return drawable; + } + + @Override + public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, + Paint paint) { + Drawable drawable = getDrawable(); + if (drawable == null) return; + canvas.save(); + + //获取画笔的文字绘制时的具体测量数据 + Paint.FontMetricsInt fm = paint.getFontMetricsInt(); + + //系统原有方法,默认是Bottom模式) + int transY = bottom - drawable.getBounds().bottom; + if (mVerticalAlignment == ALIGN_BASELINE) { + transY -= fm.descent; + } else if (mVerticalAlignment == ALIGN_BOTTOM) { + // 此处加入判断, 如果是自定义的居中对齐 + // 与文字的中间线对齐(这种方式不论是否设置行间距都能保障文字的中间线和图片的中间线是对齐的) + // y+ascent得到文字内容的顶部坐标,y+descent得到文字的底部坐标,(顶部坐标+底部坐标)/2=文字内容中间线坐标 + transY = ((y + fm.descent) + (y + fm.ascent)) / 2 - drawable.getBounds().bottom / 2; + } + + canvas.translate(x, transY); + drawable.draw(canvas); + canvas.restore(); + } + + /** + * 重写getSize方法,只有重写该方法后,才能保证不论是图片大于文字还是文字大于图片,都能实现中间对齐 + */ + @Override + public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { + Drawable drawable = getDrawable(); + if (drawable != null) { + Rect rect = drawable.getBounds(); + if (fm != null) { + Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); + int fontHeight = fmPaint.bottom - fmPaint.top; + int drHeight = rect.bottom - rect.top; + + int top = drHeight / 2 - fontHeight / 4; + int bottom = drHeight / 2 + fontHeight / 4; + + fm.ascent = -bottom; + fm.top = -bottom; + fm.bottom = top; + fm.descent = top; + } + return rect.right + Utils.dip2px(BasicConfig.INSTANCE.getAppContext(), 3); + } + return 0; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/DragLayout.java b/app/src/main/java/com/yizhuan/erban/common/widget/DragLayout.java new file mode 100644 index 000000000..8df3d0ad6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/DragLayout.java @@ -0,0 +1,196 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; + + + +/** + * Created by huangmeng1 on 2018/3/7. + * Updated by MadisonRong on 2018/4/23. + */ + +public class DragLayout extends RelativeLayout { + + private static final String TAG = "DragLayout"; + + private int lastMoveX; + private int lastMoveY; + private int lastX; + private int lastY; + private volatile int dx; + private volatile int dy; + private volatile int left; + private volatile int top; + private volatile int right; + private volatile int bottom; + private int parentWidth; + private int parentHeight; + + public DragLayout(Context context) { + this(context, null); + } + + public DragLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + lastMoveX = lastX; + lastMoveY = lastY; + break; + case MotionEvent.ACTION_MOVE: + dx = (int) event.getRawX() - lastX; + dy = (int) event.getRawY() - lastY; + + left = getLeft() + dx; + top = getTop() + dy; + right = getRight() + dx; + bottom = getBottom() + dy; + + ViewGroup parent = (ViewGroup) getParent(); + if (parent != null) { + parentWidth = parent.getWidth(); + parentHeight = parent.getHeight(); + } + + if (left < 0) { + left = 0; + right = left + getWidth(); + } + if (right > parentWidth) { + right = parentWidth; + left = right - getWidth(); + } + if (top < 0) { + top = 0; + bottom = top + getHeight(); + } + + if (bottom > parentHeight) { + + bottom = parentHeight; + top = bottom - getHeight(); + } + + reSetLayoutParams(); + + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + break; + case MotionEvent.ACTION_UP: + if ((int) (Math.abs(event.getRawX() - lastMoveX)) >= 10 || + (int) (Math.abs(event.getRawY() - lastMoveY)) >= 10) { + return true; + } else { + return performClick(); + } + default: + break; + } + return super.onInterceptTouchEvent(event); + } + + private void reSetLayoutParams() { + if (getLayoutParams() instanceof RelativeLayout.LayoutParams) { + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT + ); + layoutParams.leftMargin = left; + layoutParams.topMargin = top; + layoutParams.width = getWidth(); + layoutParams.height = getHeight(); + setLayoutParams(layoutParams); + } else if (getLayoutParams() instanceof FrameLayout.LayoutParams) { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT + ); + layoutParams.leftMargin = left; + layoutParams.topMargin = top; + layoutParams.width = getWidth(); + layoutParams.height = getHeight(); + setLayoutParams(layoutParams); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + lastMoveX = lastX; + lastMoveY = lastY; + break; + case MotionEvent.ACTION_MOVE: + dx = (int) event.getRawX() - lastX; + dy = (int) event.getRawY() - lastY; + + left = getLeft() + dx; + top = getTop() + dy; + right = getRight() + dx; + bottom = getBottom() + dy; + + ViewGroup parent = (ViewGroup) getParent(); + if (parent != null) { + parentWidth = parent.getWidth(); + parentHeight = parent.getHeight(); + } + + if (left < 0) { + left = 0; + right = left + getWidth(); + } + if (right > parentWidth) { + right = parentWidth; + left = right - getWidth(); + } + if (top < 0) { + top = 0; + bottom = top + getHeight(); + } + + if (bottom > parentHeight) { + + bottom = parentHeight; + top = bottom - getHeight(); + } + + reSetLayoutParams(); + + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + break; + case MotionEvent.ACTION_UP: + if ((int) (Math.abs(event.getRawX() - lastMoveX)) >= 10 || + (int) (Math.abs(event.getRawY() - lastMoveY)) >= 10) { + return true; + } else { + return performClick(); + } + default: + break; + } + return true; + } + + @Override + public boolean performClick() { + return super.performClick(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/FloatingLiveMiniView.java b/app/src/main/java/com/yizhuan/erban/common/widget/FloatingLiveMiniView.java new file mode 100644 index 000000000..beaf22e6d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/FloatingLiveMiniView.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * 全局悬浮的最小化控件 + * Created by MadisonRong on 20/04/2018. + */ + +public class FloatingLiveMiniView extends RelativeLayout { + + private int movex; + private int movey; + private int dx; + private int dy; + private int left ; + private int top ; + private int right ; + private int bottom ; + private int screenHeight; + private int lastX; + private int lastY; + + public FloatingLiveMiniView(Context context) { + this(context, null); + } + + public FloatingLiveMiniView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public FloatingLiveMiniView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + inflate(context, R.layout.floating_live_mini_view, this); + screenHeight = getContext().getResources().getDisplayMetrics().heightPixels; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + movex = lastX; + movey = lastY; + break; + case MotionEvent.ACTION_MOVE: + dx = (int) event.getRawX() - lastX; + dy = (int) event.getRawY() - lastY; + + left = getLeft() + dx; + top = getTop() + dy; + right = getRight() + dx; + bottom = getBottom() + dy; + if (left < 0) { + left = 0; + right = left + getWidth(); + } + if (right > UIUtil.getScreenWidth(getContext())) { + right = UIUtil.getScreenWidth(getContext()); + left = right - getWidth(); + } + if (top < 0) { + top = 0; + bottom = top + getHeight(); + } + + if (bottom > screenHeight) { + + bottom = screenHeight; + top = bottom - getHeight(); + } + layout(left, top, right, bottom); + lastX = (int) event.getRawX(); + lastY = (int) event.getRawY(); + break; + case MotionEvent.ACTION_UP: + if ((int) (event.getRawX() - movex) != 0 || (int) (event.getRawY() - movey) != 0) { + return true; + } + break; + default: + break; + } + return super.onTouchEvent(event); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/LimitEditText.java b/app/src/main/java/com/yizhuan/erban/common/widget/LimitEditText.java new file mode 100644 index 000000000..ef2feaf2b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/LimitEditText.java @@ -0,0 +1,93 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.v7.widget.AppCompatEditText; +import android.text.InputFilter; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.utils.LimitInputFliter; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * App内定制的编辑框 + * Created by lvzebiao on 2019/1/28. + */ + +public class LimitEditText extends AppCompatEditText { + /**是否限制空格和换行*/ + private boolean banBlank; + /**限制最长输入*/ + private int length; + + public LimitEditText(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.editTextStyle); + } + + public LimitEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LimitEditText); + //光标设置为APP主题色,默认ture + boolean cursor = array.getBoolean(R.styleable.LimitEditText_let_app_cursor, true); + if (cursor) { + //没有办法java直接改,采用反射 + try { + Field f = TextView.class.getDeclaredField("mCursorDrawableRes"); + f.setAccessible(true); + f.set(this, R.drawable.shape_edit_cursor); + } catch (Exception e) { + e.printStackTrace(); + } + } + //限制空格和换行输入,默认ture + banBlank = array.getBoolean(R.styleable.LimitEditText_let_ban_blank, false); + length = array.getInteger(R.styleable.LimitEditText_let_length, -1); + updateFilters(); + array.recycle(); + } + + /** + * 动态设置是否禁止空白 + */ + public void setBanBlank(boolean isBan) { + this.banBlank = isBan; + updateFilters(); + } + + public void setMaxLength(int length) { + this.length = length; + updateFilters(); + } + + private void updateFilters() { + List list = new ArrayList<>(); + if (banBlank) { + list.add(new LimitInputFliter()); + } + //限制最长输入 + if (length > 0) { + list.add(new InputFilter.LengthFilter(length)); + } + if (list.size() > 0) { + setFilters(list.toArray(new InputFilter[list.size()])); + } + } + + /** + * 设置文本,并且自动移动光标至尾部 + */ + public void setTextAutoCursor(CharSequence text) { + setText(text); + setSelection(getText().toString().length()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/LoadingImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/LoadingImageView.java new file mode 100644 index 000000000..d916ad000 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/LoadingImageView.java @@ -0,0 +1,59 @@ + +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; + +import com.yizhuan.erban.R; + + +/** + * 描述:Loading加载控件 + * + * @author zhengsun + * @since 2014年8月28日 下午4:13:37 + */ +public class LoadingImageView extends ImageView { + + public LoadingImageView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LoadingImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public LoadingImageView(Context context) { + super(context); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(getContext(), + R.anim.comm_loading); + startAnimation(hyperspaceJumpAnimation); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + clearAnimation(); + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (visibility == View.INVISIBLE || visibility == View.GONE) { + clearAnimation(); + return; + } + Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(getContext(), + R.anim.comm_loading); + startAnimation(hyperspaceJumpAnimation); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/MaskImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/MaskImageView.java new file mode 100644 index 000000000..38d1ab41d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/MaskImageView.java @@ -0,0 +1,208 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.util.AttributeSet; + +import com.yizhuan.erban.R; +import android.widget.ImageView; + + +/** + * 可在背景图和前景图显示遮罩效果的ImageView (前提设置了setClickable(true)) + * + * @author huangziwei + * @date 2015.12.29 + */ +public class MaskImageView extends ImageView { + + // 遮罩的范围 + public static final int MASK_LEVEL_BACKGROUND = 1; // 背景图显示遮罩 + public static final int MASK_LEVEL_FOREGROUND = 2; // 前景图显示遮罩 + private boolean mIsIgnoreAlpha = true; // 是否忽略图片的透明度,默认为true,透明部分不显示遮罩 + + private boolean mIsShowMaskOnClick = true; // 点击时是否显示遮罩,默认开启 + private int mShadeColor = 0x00ffffff; // 遮罩颜色(argb,需要设置透明度) + + private int mMaskLevel = MASK_LEVEL_FOREGROUND; // 默认为前景图显示遮罩 + + ColorMatrix mColorMatrix = new ColorMatrix(); // 颜色矩阵 + ColorFilter mColorFilter; + + + public MaskImageView(Context context) { + this(context, null); + } + + public MaskImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public MaskImageView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs); + } + + private void init(AttributeSet attrs) { + + TypedArray a = getContext().obtainStyledAttributes(attrs, + R.styleable.MaskImageView); + + + mIsIgnoreAlpha = a.getBoolean(R.styleable.MaskImageView_miv_is_ignore_alpha, mIsIgnoreAlpha); + mIsShowMaskOnClick = a.getBoolean(R.styleable.MaskImageView_miv_is_show_mask_on_click, mIsShowMaskOnClick); + mShadeColor = a.getColor(R.styleable.MaskImageView_miv_mask_color, mShadeColor); + mMaskLevel = a.getInt(R.styleable.MaskImageView_miv_mask_level, mMaskLevel); + + // 忽略透明度时的颜色矩阵 + float r = Color.alpha(mShadeColor) / 255f; + r = r - (1 - r) * 0.15f; + float rr = (1 - r) * 1.15f; + setColorMatrix(new float[]{ + rr, 0, 0, 0, Color.red(mShadeColor) * r, + 0, rr, 0, 0, Color.green(mShadeColor) * r, + 0, 0, rr, 0, Color.blue(mShadeColor) * r, + 0, 0, 0, 1, 0, + }); + + a.recycle(); + } + + private void setColorMatrix(float[] matrix) { + mColorMatrix.set(matrix); + mColorFilter = new ColorMatrixColorFilter(mColorMatrix); + } + + // all drawables instances loaded from the same resource share getScreenHeight common state + // 从同一个资源文件获取的drawable对象共享一个状态信息,为了避免修改其中一个drawable导致其他drawable被影响,需要调用mutate() + // 因为背景图在draw()阶段绘制,所以修改了背景图状态后必须调用invalidateSelf()刷新 + private void setDrawableColorFilter(ColorFilter colorFilter) { + if (mMaskLevel == MASK_LEVEL_BACKGROUND) { + if (getBackground() != null) { + getBackground().mutate(); + getBackground().setColorFilter(colorFilter); + getBackground().invalidateSelf(); + } + } else if (mMaskLevel == MASK_LEVEL_FOREGROUND) { + if (getDrawable() != null) { + getDrawable().mutate(); + getDrawable().setColorFilter(colorFilter); + getDrawable().invalidateSelf(); + } + } + } + + + /* 忽略透明度,添加遮罩原理 + + 创建新的滤镜 + ColorMatrix colorMatrix = new ColorMatrix(new float[]{ + getScreenHeight,b,c,d,e, + f,g,h,i,j, + k,l,m,n,o, + p,q,r,s,t}); + + 已知一个颜色值ARGB,则经过下面的矩阵运算可得出新的颜色值 + int red = getScreenHeight*R + b*R + c*R + d*R + e; + int green = f*G + g*G + h*G + i*G + j; + int blue = k*B + l*B + m*B + n*B + o; + int alpha = p*A + q*A + r*A + s*A + t; + + 设置图片滤镜 + getDrawable().setColorFilter(new ColorMatrixColorFilter(colorMatrix)); + + 绘图 + mDrawable.draw(canvas) + + */ + @Override + protected void onDraw(Canvas canvas) { + + if (mIsIgnoreAlpha) { // 忽略透明度 + if (mIsShowMaskOnClick && isPressed()) { + // 绘制遮罩层 + setDrawableColorFilter(mColorFilter); + } else { + setDrawableColorFilter(null); + } + super.onDraw(canvas); + } else { // 不忽略透明度 + setDrawableColorFilter(null); + if (mMaskLevel == MASK_LEVEL_BACKGROUND) { // 背景图 + if (mIsShowMaskOnClick && isPressed()) { + // 绘制遮罩层 + canvas.drawColor(mShadeColor); + } + super.onDraw(canvas); + } else { // 前景图 + super.onDraw(canvas); + if (mIsShowMaskOnClick && isPressed()) { + // 绘制遮罩层 + canvas.drawColor(mShadeColor); + } + } + } + + } + + /** + * view状态改变 + */ + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + invalidate(); + } + + public boolean isIsIgnoreAlpha() { + return mIsIgnoreAlpha; + } + + public void setIsIgnoreAlpha(boolean mIsIgnoreAlpha) { + this.mIsIgnoreAlpha = mIsIgnoreAlpha; + invalidate(); + } + + public boolean isIsShowMaskOnClick() { + return mIsShowMaskOnClick; + } + + public void setIsShowMaskOnClick(boolean mIsShowMaskOnClick) { + this.mIsShowMaskOnClick = mIsShowMaskOnClick; + invalidate(); + } + + public int getShadeColor() { + return mShadeColor; + } + + public void setShadeColor(int mShadeColor) { + this.mShadeColor = mShadeColor; + // 忽略透明度时的颜色矩阵 + float r = Color.alpha(mShadeColor) / 255f; + r = r - (1 - r) * 0.15f; + float rr = (1 - r) * 1.15f; + setColorMatrix(new float[]{ + rr, 0, 0, 0, Color.red(mShadeColor) * r, + 0, rr, 0, 0, Color.green(mShadeColor) * r, + 0, 0, rr, 0, Color.blue(mShadeColor) * r, + 0, 0, 0, 1, 0, + }); + invalidate(); + } + + public int getMaskLevel() { + return mMaskLevel; + } + + public void setMaskLevel(int mMaskLevel) { + this.mMaskLevel = mMaskLevel; + invalidate(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/OriginalDrawStatusClickSpan.java b/app/src/main/java/com/yizhuan/erban/common/widget/OriginalDrawStatusClickSpan.java new file mode 100644 index 000000000..a1008cfe6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/OriginalDrawStatusClickSpan.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.common.widget; + +import android.graphics.Color; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.text.TextPaint; +import android.text.style.ClickableSpan; + +public abstract class OriginalDrawStatusClickSpan extends ClickableSpan { + + private final Integer mColor; + + public OriginalDrawStatusClickSpan() { + this(null); + } + + public OriginalDrawStatusClickSpan(@ColorInt Integer color) { + this.mColor = color; + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + if (mColor != null) { + ds.setColor(mColor); + ds.setUnderlineText(true); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/PlayerView.java b/app/src/main/java/com/yizhuan/erban/common/widget/PlayerView.java new file mode 100644 index 000000000..5cdfaa90c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/PlayerView.java @@ -0,0 +1,54 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by zhouxiangfeng on 17/2/26. + */ + +public class PlayerView extends View { + + private ImageView playerIv; + private TextView timeTv; + + private static final int MODE_PLAYING = 1 ; + private static final int MODE_NORMAL = 0 ; + + public PlayerView(Context context) { + super(context); + init(); + } + + public PlayerView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public PlayerView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init(){ + View mView = LayoutInflater.from(getContext()).inflate(R.layout.layout_audio_player_view,null); + playerIv = (ImageView)mView.findViewById(R.id.player_iv); + timeTv = (TextView)mView.findViewById(R.id.time_tv); + } + + public void updateView(int mode){ + if(mode == MODE_NORMAL){ + playerIv.setImageResource(R.drawable.btn_play); + + }else{ + playerIv.setImageResource(R.drawable.btn_pause); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/RectRoundImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/RectRoundImageView.java new file mode 100644 index 000000000..dbc777f26 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/RectRoundImageView.java @@ -0,0 +1,317 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.ImageView; + +import com.yizhuan.erban.R; + +import java.io.InputStream; + + +/** + * 自定义View,实现圆角,圆形等效果 + * + * @author zhy + */ +public class RectRoundImageView extends ImageView { + + /** + * TYPE_CIRCLE / TYPE_ROUND + */ + private int type; + public static final int TYPE_CIRCLE = 0; + public static final int TYPE_ROUND = 1; + + /** + * 图片 + */ + private Bitmap mSrc; + + /** + * 圆角的大小 + */ + private int mRadius = 8; + + /** + * 控件的宽度 + */ + private int mWidth; + /** + * 控件的高度 + */ + private int mHeight; + + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public int getmRadius() { + return mRadius; + } + + public void setmRadius(int mRadius) { + this.mRadius = mRadius; + } + + public RectRoundImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RectRoundImageView(Context context) { + this(context, null); + } + + /** + * 初始化一些自定义的参数 + * + * @param context + * @param attrs + * @param defStyle + */ + public RectRoundImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.getTheme().obtainStyledAttributes(attrs, + R.styleable.RectRoundImageView, defStyle, 0); + + int n = a.getIndexCount(); + for (int i = 0; i < n; i++) { + int attr = a.getIndex(i); + switch (attr) { + case R.styleable.RectRoundImageView_src: +// mSrc = BitmapFactory.decodeResource(getResources(), +// a.getResourceId(attr, 0)); + InputStream is = getResources().openRawResource(a.getResourceId(attr, 0)); + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inTempStorage = new byte[100 * 1024]; + opts.inPreferredConfig = Config.RGB_565; + opts.inPurgeable = true; + opts.inSampleSize = 4; + mSrc = BitmapFactory.decodeStream(is, null, opts); + break; + case R.styleable.RectRoundImageView_type: + type = a.getInt(attr, 0);// 默认为Circle + break; + case R.styleable.RectRoundImageView_borderRadius: + mRadius = a.getDimensionPixelSize(attr, (int) TypedValue + .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, + getResources().getDisplayMetrics()));// 默认为10DP + break; + } + } + setScaleType(ScaleType.CENTER_CROP); + a.recycle(); + } + + + /** + * 计算控件的高度和宽度 + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + Drawable drawable = getDrawable(); + if (null != drawable) { + mSrc = drawableToBitmap(getDrawable()); + } + /** + * 设置宽度 + */ + int specMode = MeasureSpec.getMode(widthMeasureSpec); + int specSize = MeasureSpec.getSize(widthMeasureSpec); + + if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate + { + mWidth = specSize; + } else { + // 由图片决定的宽 + int desireByImg = getPaddingLeft() + getPaddingRight() + + mSrc.getWidth(); + if (specMode == MeasureSpec.AT_MOST)// wrap_content + { + mWidth = Math.min(desireByImg, specSize); + } else + mWidth = desireByImg; + } + + /*** + * 设置高度 + */ + + specMode = MeasureSpec.getMode(heightMeasureSpec); + specSize = MeasureSpec.getSize(heightMeasureSpec); + if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate + { + mHeight = specSize; + } else { + int desire = getPaddingTop() + getPaddingBottom() + + mSrc.getHeight(); + + if (specMode == MeasureSpec.AT_MOST)// wrap_content + { + mHeight = Math.min(desire, specSize); + } else + mHeight = desire; + } + + setMeasuredDimension(mWidth, mHeight); + + } + + /** + * 绘制 + */ + @Override + protected void onDraw(Canvas canvas) { + + switch (type) { + // 如果是TYPE_CIRCLE绘制圆形 + case TYPE_CIRCLE: + int min = Math.min(mWidth, mHeight); + /** + * 长度如果不一致,按小的值进行压缩 + */ + if (null != mSrc) { + mSrc = Bitmap.createScaledBitmap(mSrc, min, min, false); + canvas.drawBitmap(createCircleImage(mSrc, min), 0, 0, null); + } + break; + case TYPE_ROUND: + canvas.drawBitmap(createFramedPhoto(mWidth, mHeight, mSrc, mRadius), 0, 0, null); + break; + } + + } + + + /** + * Drawable → Bitmap + * + * @param drawable + * @return + */ + + public static Bitmap drawableToBitmap(Drawable drawable) { + + + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + + drawable.getIntrinsicHeight(), + + drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 + + : Config.RGB_565); + + Canvas canvas = new Canvas(bitmap); + + //canvas.setBitmap(bitmap); + + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + + drawable.draw(canvas); + + return bitmap; + + } + + /** + * 根据原图和变长绘制圆形图片 + * + * @param source + * @param min + * @return + */ + private Bitmap createCircleImage(Bitmap source, int min) { + final Paint paint = new Paint(); + paint.setAntiAlias(true); + Bitmap target = Bitmap.createBitmap(min, min, Config.RGB_565); + /** + * 产生一个同样大小的画布 + */ + Canvas canvas = new Canvas(target); + /** + * 首先绘制圆形 + */ + canvas.drawCircle(min / 2, min / 2, min / 2, paint); + /** + * 使用SRC_IN,参考上面的说明 + */ + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + /** + * 绘制图片 + */ + canvas.drawBitmap(source, 0, 0, paint); + return target; + } + + /** + * 根据原图添加圆角 + * + * @param source + * @return + */ + private Bitmap createRoundConerImage(Bitmap source) { + final Paint paint = new Paint(); + paint.setAntiAlias(true); + Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888); + Canvas canvas = new Canvas(target); + RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight()); + canvas.drawRoundRect(rect, mRadius, mRadius, paint); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(source, 0, 0, paint); + return target; + } + + /** + * @param x 图像的宽度 + * @param y 图像的高度 + * @param image 源图片 + * @param outerRadiusRat 圆角的大小 + * @return 圆角图片 + */ + Bitmap createFramedPhoto(int x, int y, Bitmap image, float outerRadiusRat) { + //根据源文件新建一个darwable对象 + Drawable imageDrawable = new BitmapDrawable(image); + // 新建一个新的输出图片 + Bitmap output = Bitmap.createBitmap(x, y, Config.ARGB_8888); + + Canvas canvas = new Canvas(output); + + // 新建一个矩形 + RectF outerRect = new RectF(0, 0, x, y); + + // 产生一个红色的圆角矩形 + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.RED); + canvas.drawRoundRect(outerRect, outerRadiusRat, outerRadiusRat, paint); + + // 将源图片绘制到这个圆角矩形上 + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + imageDrawable.setBounds(0, 0, x, y); + canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); + imageDrawable.draw(canvas); + canvas.restore(); + + return output; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/SlideListViewPager.java b/app/src/main/java/com/yizhuan/erban/common/widget/SlideListViewPager.java new file mode 100644 index 000000000..0e257e9ff --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/SlideListViewPager.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.WindowManager; + +public class SlideListViewPager extends ViewPager { + + private Context context; + + public SlideListViewPager(Context context) { + super(context); + // TODO Auto-generated constructor stub + this.context = context; + } + + public SlideListViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + // TODO Auto-generated constructor stub + this.context = context; + } + +// @Override +// public boolean onInterceptTouchEvent(MotionEvent event) {//限制出发滑动的范围 +// if(event.getAction() == MotionEvent.ACTION_DOWN){ +// float x = event.getX(); +// if(x < 10 || x > getScreenWidth(context) - 10){ +// return true; +// }else{ +// return false; +// } +// } +// return super.onInterceptTouchEvent(event); +// } + + // 获取屏幕的宽度 + public static int getScreenWidth(Context context) { + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = manager.getDefaultDisplay(); + return display.getWidth(); + } + + // 获取屏幕的宽度 + public static int getScreenWidths(Context context) { + DisplayMetrics dm = new DisplayMetrics(); + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + manager.getDefaultDisplay().getMetrics(dm); + + int screenWidth = dm.widthPixels; + + int screenHeight = dm.heightPixels; + return screenWidth; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/StatusLayout.java b/app/src/main/java/com/yizhuan/erban/common/widget/StatusLayout.java new file mode 100644 index 000000000..b6af68409 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/StatusLayout.java @@ -0,0 +1,127 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.xchat_android_library.utils.log.MLog; +import com.yizhuan.erban.R; + + +/** + * 状态布局:无数据,网络错误,加载中 + * Created by xujiexing on 14-7-16. + */ +public class StatusLayout extends RelativeLayout { + + private int paddingBottom; + + public StatusLayout(Context context) { + super(context); + } + + public StatusLayout(Context context, AttributeSet attrs) { + super(context, attrs); + initParams(context, attrs); + } + + public StatusLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initParams(context, attrs); + } + + private TextView mLoadingMore; + private View mLoadingContainer; + private View mProgress; + + private void initParams(Context context, AttributeSet attrs) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StatusLayout); + paddingBottom = a.getDimensionPixelOffset(R.styleable.StatusLayout_status_bottom, 0); + a.recycle(); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + addLoadingFooter(); + addStatus(); + } + + private void addLoadingFooter() { + View status = LayoutInflater.from(getContext()).inflate(R.layout.layout_loading_more, null); + LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + params.addRule(ALIGN_PARENT_BOTTOM); + status.setVisibility(View.GONE); + this.addView(status, getChildCount(), params); + mLoadingMore = findViewById(R.id.loading_text); + mLoadingContainer = findViewById(R.id.loading_more); + mProgress = findViewById(R.id.loading_progress); + } + + /** + * 加载,出错,网络错误等状态显示的container + */ + private void addStatus() { + setId(R.id.status_layout); + if (paddingBottom > 0) { + setPadding(0, 0, 0, paddingBottom); + setOnHierarchyChangeListener(new OnHierarchyChangeListener() { + @Override + public void onChildViewAdded(View parent, View child) { + setBackgroundResource(R.color.common_bg_color); + } + + @Override + public void onChildViewRemoved(View parent, View child) { + setBackgroundResource(R.color.transparent); + } + }); + } + setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void showErrorPage(int tips, OnClickListener listener) { + if (mLoadingMore == null) + return; + if (tips <= 0) + tips = R.string.click_or_pull_refresh; + String text = getContext().getString(tips); + + mLoadingMore.setText(text); + mLoadingContainer.setOnClickListener(listener); + mProgress.setVisibility(View.GONE); + mLoadingContainer.setVisibility(View.VISIBLE); + } + + public void showLoadMore() { + mLoadingMore.setText(getContext().getString(R.string.loading)); + mProgress.setVisibility(View.VISIBLE); + mLoadingContainer.setOnClickListener(null); + mLoadingContainer.setVisibility(View.VISIBLE); + } + + public void hideLoadMore() { + try { + mLoadingContainer.setVisibility(View.GONE); + } catch (Exception e) { + MLog.error(this, "hideLoadMore error ", e); + mHandler.sendEmptyMessage(0); + } + + } + + Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + mLoadingContainer.setVisibility(View.GONE); + MLog.info(this, "hideLoadMore in handler", ""); + } + }; +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/TutuSwitchView.java b/app/src/main/java/com/yizhuan/erban/common/widget/TutuSwitchView.java new file mode 100644 index 000000000..798768d59 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/TutuSwitchView.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.common.widget; + +import android.content.Context; +import android.util.AttributeSet; + +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; + +/** + * 开关控件,涉及ui,继承library的 {@link com.yizhuan.xchat_android_library.widget.IOSSwitchView} + * 改写UI + * Created by lvzebiao on 2019/1/25. + */ + +public class TutuSwitchView extends IOSSwitchView { + + public TutuSwitchView(Context context, AttributeSet attrs) { + super(context, attrs); + setNoStrokeColor(true); + setmIsKeepRate(true); + } + + @Override + public int getSelectedColor() { + return 0xFF34EBDE; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsDialog.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsDialog.java new file mode 100644 index 000000000..eff7c01c9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsDialog.java @@ -0,0 +1,182 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatDialogFragment; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.community.publish.view.WorldsChooseFrg; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.community.bean.MiniWorldChooseInfo; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.ArrayList; +import java.util.List; + +public class ChooseWorldsDialog extends AppCompatDialogFragment + implements ChooseWorldsIndicatorAdapter.OnItemSelectListener, WorldsChooseFrg.ChooseWorldCallback { + + private Context context; + private ViewGroup mRootView; + + private FrameLayout flTopButton; + private FrameLayout flDialogWorld; + private MagicIndicator indicator; + private ViewPager viewPager; + + public static ChooseWorldsDialog newInstance(byte type) { + ChooseWorldsDialog chooseWorldsDialog = new ChooseWorldsDialog(); + Bundle bundle = new Bundle(); + bundle.putByte("type", type); + chooseWorldsDialog.setArguments(bundle); + return chooseWorldsDialog; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + context = getContext(); + mRootView = (ViewGroup) View.inflate(getContext(), R.layout.layout_choose_worlds, null); + flTopButton = mRootView.findViewById(R.id.fl_top_button); + flTopButton.setOnClickListener(v -> { + dismissDialog(); + }); + flDialogWorld = mRootView.findViewById(R.id.fl_dialog_world); + flDialogWorld.setOnClickListener(v -> { + dismissDialog(); + }); + indicator = mRootView.findViewById(R.id.indicator); + viewPager = mRootView.findViewById(R.id.viewpager); + + List mTabInfoList = new ArrayList<>(); + mTabInfoList.add(new TabInfo(1, "我加入的")); + mTabInfoList.add(new TabInfo(2, "大家都在聊")); + mTabInfoList.add(new TabInfo(3, "全部")); + + List mTabs = new ArrayList<>(); + mTabs.add(WorldsChooseFrg.newInstance(Constants.TYPE_JOINED).setmChooseWorldCallback(this)); + mTabs.add(WorldsChooseFrg.newInstance(Constants.TYPE_RECOMMEND).setmChooseWorldCallback(this)); + mTabs.add(WorldsChooseFrg.newInstance(Constants.TYPE_ALL).setmChooseWorldCallback(this)); + + ChooseWorldsIndicatorAdapter topMagicIndicatorAdapter = new ChooseWorldsIndicatorAdapter(context, mTabInfoList, 0); + topMagicIndicatorAdapter.setOnItemSelectListener(this); + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + commonNavigator.setAdjustMode(true); + commonNavigator.setAdapter(topMagicIndicatorAdapter); + indicator.setNavigator(commonNavigator); + + viewPager.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), mTabs)); + ViewPagerHelper.bind(indicator, viewPager); + + Bundle bundle = getArguments(); + byte type; + if (bundle != null) { + type = bundle.getByte("type", Constants.TYPE_JOINED); + } else { + type = Constants.TYPE_JOINED; + } + + switch (type) { + case Constants.TYPE_ALL: + viewPager.setCurrentItem(2); + break; + + case Constants.TYPE_JOINED: + viewPager.setCurrentItem(0); + break; + + case Constants.TYPE_RECOMMEND: + viewPager.setCurrentItem(1); + break; + } + + return mRootView; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if (getActivity() != null) { + Dialog dialog = new Dialog(getActivity(), R.style.room_rank_dialog); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.layout_choose_worlds); + dialog.setCanceledOnTouchOutside(true); + + // 设置弹出框布局参数,宽度铺满全屏,底部。 + Window window = dialog.getWindow(); + if (window != null) { + WindowManager.LayoutParams wlp = window.getAttributes(); + wlp.gravity = Gravity.BOTTOM; + wlp.width = WindowManager.LayoutParams.MATCH_PARENT; + wlp.height = WindowManager.LayoutParams.MATCH_PARENT; + window.setDimAmount(0.3f); + window.setAttributes(wlp); + window.setBackgroundDrawableResource(R.drawable.bg_audio_party_list_dialog); + window.setWindowAnimations(R.style.ErbanCommonWindowAnimationStyle); + return dialog; + } else { + return super.onCreateDialog(savedInstanceState); + } + } else { + return super.onCreateDialog(savedInstanceState); + } + } + + @Override + public void onItemSelect(int position) { + viewPager.setCurrentItem(position); + } + + private WorldsChooseFrg.ChooseWorldCallback mChooseWorldCallback; + @Override + public void callback(MiniWorldChooseInfo miniWorldChooseInfo) { + if (mChooseWorldCallback != null) { + mChooseWorldCallback.callback(miniWorldChooseInfo); + } + + mChooseWorldCallback = null; + dismissDialog(); + } + + public void setmChooseWorldCallback(WorldsChooseFrg.ChooseWorldCallback chooseWorldCallback) { + this.mChooseWorldCallback = chooseWorldCallback; + } + + public void dismissDialog() { + //注释这个判断,因为不保留活动情况下,((Activity)mContext).isDestroyed() 为true 导致不执行dismiss一个dialog + //而mDialog.getWindow()不为null,还是可以dismiss一个dialog的。 +// if(!checkActivityValid()) +// return; + //加上一个try,强行吞异常 + try { + Context context = getContext(); + if (getContext() != null) { + if (context instanceof Activity) { + Activity activity = (Activity) context; + if (!activity.isFinishing())//如果dialog在延时比如handler。postDelay中调用,而activity.已经destory,会报异常java.lang.IllegalArgumentException: View not attached to window manager + dismiss(); + } else + dismiss(); + } + } catch (Exception e){ + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsIndicatorAdapter.java new file mode 100644 index 000000000..def6b63ae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ChooseWorldsIndicatorAdapter.java @@ -0,0 +1,76 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +public class ChooseWorldsIndicatorAdapter extends CommonNavigatorAdapter { + + private Context mContext; + private List mTitleList; + private int mBottomMargin; + + public ChooseWorldsIndicatorAdapter(Context context, List titleList, int bottomMargin) { + mContext = context; + mTitleList = titleList; + mBottomMargin = bottomMargin; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_B3B3B3)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(1); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(i).getName()); + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(mContext, 3)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 1.5)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 12)); + indicator.setColors(context.getResources().getColor(R.color.appColor)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CommonPopupDialog.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CommonPopupDialog.java new file mode 100644 index 000000000..c72f8604a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CommonPopupDialog.java @@ -0,0 +1,155 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +import java.util.List; + +/** + * @author xiaoyu + */ +public class CommonPopupDialog extends BottomSheetDialog implements OnClickListener { + private static final int BUTTON_ITEM_ID = 135798642; + + private int mId; + private ViewGroup mRootView; + protected ViewGroup mContentView; + private TextView mMessageTv; + private TextView mCancelBtn; + private View v2; + private int id; + private String title; + private List buttons; + private ButtonItem bottomButton; + private Context context; + private boolean isFullScreen = true; + + public CommonPopupDialog(Context context, String title, List buttons, String cancelBtnText) { + this(0, context, title, buttons, new ButtonItem(cancelBtnText, null)); + } + + public CommonPopupDialog(Context context, String title, List buttons, final ButtonItem bottomButton) { + this(0, context, title, buttons, bottomButton); + } + + public CommonPopupDialog(Context context, String title, List buttons, String cancelBtnText, boolean isFullScreen) { + this(0, context, title, buttons, new ButtonItem(cancelBtnText, null)); + this.isFullScreen = isFullScreen; + } + + public CommonPopupDialog(int id, Context context, String title, List buttons, final ButtonItem bottomButton) { + super(context, R.style.ErbanBottomSheetDialog); + this.context = context; + this.id = id; + this.title = title; + this.buttons = buttons; + this.bottomButton = bottomButton; + setCanceledOnTouchOutside(true); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mId = id; + mRootView = (ViewGroup) View.inflate(getContext(), R.layout.layout_common_popup_dialog, null); + mContentView = mRootView.findViewById(R.id.ll_more); + mMessageTv = mRootView.findViewById(R.id.tv_message); + mCancelBtn = mRootView.findViewById(R.id.btn_cancel); + mCancelBtn.setOnClickListener(v -> { + if (bottomButton != null && bottomButton.mClickListener != null) { + bottomButton.mClickListener.onClick(); + } + dismiss(); + }); + + setContentView(mRootView); + + Window window = getWindow(); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + window.setAttributes(params); + window.setWindowAnimations(R.style.ErbanCommonWindowAnimationStyle); + + int size = buttons == null ? 0 : buttons.size(); + if (size > 0) { + if (title != null && !title.isEmpty()) { + setMessage(title); + } + mContentView.setVisibility(View.VISIBLE); + for (int i = 0; i < size; i++) { + addItem(buttons.get(i)); + } + } + if (bottomButton != null && bottomButton.mText != null && !bottomButton.mText.isEmpty()) { + mCancelBtn.setVisibility(View.VISIBLE); + mCancelBtn.setText(bottomButton.mText); + } + FrameLayout bottomSheet = findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + BottomSheetBehavior.from(bottomSheet).setPeekHeight( + (int) context.getResources().getDimension(R.dimen.dialog_common_button_item_height) * (size + 3) + + Utils.dip2px(context, 5)); + } + } + + public CommonPopupDialog setMessage(String text) { + mMessageTv.setVisibility(View.VISIBLE); + mMessageTv.setText(text); + return this; + } + + public void addItem(final ButtonItem buttonItem) { + TextView item = (TextView) LayoutInflater.from(getContext()).inflate(buttonItem.mLayout, mContentView, false); + if (buttonItem.mTheme != -1) { + item.setTextAppearance(getContext(), buttonItem.mTheme); + } + if (buttonItem.getTextColor() != 0) { + item.setTextColor(buttonItem.getTextColor()); + } + item.setText(buttonItem.mText); + item.setOnClickListener(v -> { + buttonItem.mClickListener.onClick(); + dismiss(); + }); + item.setId(BUTTON_ITEM_ID + mContentView.getChildCount()); + mContentView.addView(item, mContentView.getChildCount()); + } + + public void addDivider() { + View v2 = LayoutInflater.from(getContext()).inflate(R.layout.layout_common_popup_dialog_divider, mContentView, false); + v2.setVisibility(View.VISIBLE); + mContentView.addView(v2, mContentView.getChildCount()); + } + + public int getId() { + return mId; + } + + @Override + public void onClick(View v) { + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CustomPopupDialog.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CustomPopupDialog.java new file mode 100644 index 000000000..f37886964 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/CustomPopupDialog.java @@ -0,0 +1,119 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.app.AlertDialog; +import android.content.Context; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + + +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_library.utils.ResolutionUtils; +import com.yizhuan.erban.R; + +import java.util.List; + +public class CustomPopupDialog extends AlertDialog implements OnClickListener { + + private ViewGroup mRootView; + private ViewGroup mContentView; + private TextView mMessageTv; + private TextView mCancelBtn; + private View v2; + + public CustomPopupDialog(Context context, String title, List buttons) { + super(context); + show(); + + mRootView = (ViewGroup) View.inflate(getContext(), R.layout.layout_custom_popup_dialog, null); + mContentView = (ViewGroup) mRootView.findViewById(R.id.ll_more); + mMessageTv = (TextView) mRootView.findViewById(R.id.tv_message); + /*mCancelBtn = (TextView) mRootView.findViewById(R.id.btn_cancel); + mCancelBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(bottomButton!=null && bottomButton.mClickListener!=null){ + bottomButton.mClickListener.onClick(); + } + dismiss(); + } + });*/ + + Window window = getWindow(); + WindowManager.LayoutParams params = window.getAttributes(); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = (int) (ResolutionUtils.getScreenWidth(context) * 0.85); + window.setGravity( Gravity.CENTER ); + window.setAttributes(params); + window.setBackgroundDrawableResource(android.R.color.transparent); + //window.setWindowAnimations(R.style.DialogAnimation); + window.setContentView(mRootView); + + int size = buttons == null ? 0 : buttons.size(); + if(size > 0){ + if(!TextUtils.isEmpty(title)){ + setMessage(title); + } + mContentView.setVisibility(View.VISIBLE); + for (int i = 0; i < size; i++) { + if (i == 0 && TextUtils.isEmpty(title)) { + addItem(buttons.get(0), 0); + } else { + addDivider(); + addItem(buttons.get(i), i == size - 1 ? 2 : 1); + } + } + } + /*if(bottomButton != null && bottomButton.mText!=null && !bottomButton.mText.isEmpty()){ + mCancelBtn.setVisibility(View.VISIBLE); + mCancelBtn.setText(bottomButton.mText); + }*/ + } + + public CustomPopupDialog setMessage(String text) { + mMessageTv.setVisibility(View.VISIBLE); + mMessageTv.setText(text); + return this; + } + + public void addItem(final ButtonItem buttonItem, int level){ + TextView item = (TextView) LayoutInflater.from(getContext()).inflate(buttonItem.mLayout, mContentView, false); + item.setText(buttonItem.mText); + item.getBackground().setLevel(level); + if (buttonItem.mButtonType == ButtonItem.BUTTON_TYPE_CANCEL) { +// item.setTextColor(getContext().getResources().getColorStateList(R.drawable.dialog_bottom_btn_color)); + item.setTextColor(getContext().getResources().getColor(R.color.text_color_system)); + } + if(buttonItem.mClickListener!=null) { + item.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + buttonItem.mClickListener.onClick(); + dismiss(); + } + }); + }else{ + item.setTextColor(getContext().getResources().getColor(R.color.text_color_system)); + item.setGravity(Gravity.LEFT); + item.setText("  "+buttonItem.mText); + } + mContentView.addView(item, mContentView.getChildCount()); + } + + public void addDivider(){ + View v2 = LayoutInflater.from(getContext()).inflate(R.layout.layout_common_popup_dialog_divider, mContentView, false); + v2.setVisibility(View.VISIBLE); + mContentView.addView(v2, mContentView.getChildCount()); + } + + @Override + public void onClick(View v) { + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogManager.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogManager.java new file mode 100644 index 000000000..5b6b26687 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogManager.java @@ -0,0 +1,1015 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.text.Html; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.text.style.ForegroundColorSpan; +import android.util.Log; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.LinearInterpolator; +import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.Switch; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_library.utils.FP; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.List; + +//import javax.xml.soap.Text; + +public class DialogManager { + + private static final String TAG = "DialogManager"; + + private volatile Dialog mDialog; + private Context mContext; + private AlertDialog.Builder mBuilder; + private boolean mCanceledOnClickBackKey = true; + private boolean mCanceledOnClickOutside = true; + private boolean mReCreate = true; + private TextView mCancel; + /** + * 新增的一种弹框类型,支持只弹一次 + */ + private Switch switchTips; + + public DialogManager(Context context) { + mContext = context; + mBuilder = new AlertDialog.Builder(context, R.style.MyAlertDialogStyle); + mDialog = mBuilder.create(); + } + + public DialogManager(Context context, boolean noCreate) { + mContext = context; + mBuilder = new AlertDialog.Builder(context, R.style.MyAlertDialogStyle); + if (!noCreate) { + mDialog = mBuilder.create(); + } + } + + public DialogManager(Context context, boolean canceledOnClickBackKey, boolean canceledOnClickOutside) { + mContext = context; + mBuilder = new AlertDialog.Builder(context, R.style.MyAlertDialogStyle); + mDialog = mBuilder.create(); + mCanceledOnClickBackKey = canceledOnClickBackKey; + mCanceledOnClickOutside = canceledOnClickOutside; + } + + public Context getContext() { + return mContext; + } + + @TargetApi(17) + public boolean checkActivityValid() { + if (mContext == null) { + MLog.warn(this, "Fragment " + this + " not attached to Activity"); + return false; + } + if (mDialog != null && mDialog.getWindow() == null) { + MLog.warn(this, "window null"); + return false; + } + if (((Activity) mContext).isFinishing()) { + MLog.warn(this, "activity is finishing"); + return false; + } + + if (Build.VERSION.SDK_INT >= 17 && ((Activity) mContext).isDestroyed()) { + MLog.warn(this, "activity is isDestroyed"); + return false; + } + return true; + } + + public void dismissDialog() { + //注释这个判断,因为不保留活动情况下,((Activity)mContext).isDestroyed() 为true 导致不执行dismiss一个dialog + //而mDialog.getWindow()不为null,还是可以dismiss一个dialog的。 +// if(!checkActivityValid()) +// return; + //加上一个try,强行吞异常 + try { + if (mContext != null && mDialog != null && mDialog.getWindow() != null) { + if (mContext instanceof Activity) { + Activity activity = (Activity) mContext; + if (!activity.isFinishing()) { + //如果dialog在延时比如handler。postDelay中调用, + // 而activity.已经destory, + // 会报异常java.lang.IllegalArgumentException: + // View not attached to window manager + mDialog.dismiss(); + } + } else { + mDialog.dismiss(); + } + } + } catch (Exception e){ + + } + } + + public boolean isDialogShowing() { + if (mDialog != null) { + return mDialog.isShowing(); + } + return false; + } + + public void setCanceledOnClickBackKey(boolean cancelable) { + mCanceledOnClickBackKey = cancelable; + } + + public void setCanceledOnClickOutside(boolean cancelable) { + mCanceledOnClickOutside = cancelable; + } + + /** + * 只有确定按钮 + * 带标题 + */ + public void showOkWithTitleDialog(CharSequence title, CharSequence message, + CharSequence okLabel, boolean isCanCancel, OkCancelDialogListener l) { + showOkCancelDialog(title, message, okLabel, null, isCanCancel, l); + } + + public void showOkWithTitleDialog(CharSequence message, boolean isCanCancel) { + showOkWithTitleDialog(getContext().getString(R.string.common_tip), message, + getContext().getString(R.string.text_ok), isCanCancel, null); + } + + public void showOkWithTitleDialog(CharSequence message) { + showOkWithTitleDialog(message, true); + } + + public void showOkDialog(CharSequence message) { + showOkDialog(message, true); + } + + public void showOkDialog(CharSequence message, boolean isCanCancel) { + showOkDialog(message, isCanCancel, null); + } + + public void showOkDialog(CharSequence message, final OkCancelDialogListener l) { + showOkDialog(message, mCanceledOnClickOutside, l); + } + + public void showOkDialog(CharSequence message, boolean isCanCancel, final OkCancelDialogListener l) { + showOkDialog(message, getContext().getString(R.string.text_ok), isCanCancel, l); + } + + public void showOkDialog(CharSequence message, CharSequence okLable, boolean isCanCancel, final OkCancelDialogListener l) { + showOkCancelDialog(message, okLable, null, isCanCancel, l); + } + + public void showCommonPopupDialog(List btnItems) { + showCommonPopupDialog(null, btnItems, ""); + } + + public void showCommonPopupDialog(String cancelBtnText) { + showCommonPopupDialog(null, null, cancelBtnText); + } + + public void showCommonPopupDialog(String title, int layout_bottom_select_dialog, ButtonItem bottomButton) { + showCommonPopupDialog(null, null, bottomButton); + } + + public void showCommonPopupDialog(String title, List btnItems) { + showCommonPopupDialog(title, btnItems, ""); + } + + public void showCommonPopupDialog(List btnItems, String cancelBtnText) { + showCommonPopupDialog(null, btnItems, cancelBtnText); + } + + public void showCommonPopupDialog(List btnItems, String cancelBtnText, boolean isFullscreen) { + showCommonPopupDialog(null, btnItems, cancelBtnText, isFullscreen); + } + + public void showCommonPopupDialog(List btnItems, ButtonItem bottomButton) { + showCommonPopupDialog(null, btnItems, bottomButton); + } + + public void showCommonPopupDialog(String title, List btnItems, ButtonItem bottomButton) { + + if (!checkActivityValid()) { + MLog.info(this, "showCommonPopupDialog ActivityInvalid."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new CommonPopupDialog(mContext, title, btnItems, bottomButton); + mDialog.setCancelable(mCanceledOnClickBackKey); + mDialog.setCanceledOnTouchOutside(mCanceledOnClickOutside); + mDialog.show(); + } + + public void showCommonPopupDialog(String title, List btnItems, String cancelBtnText, boolean isFullScreen) { + + if (!checkActivityValid()) { + MLog.info(this, "showCommonPopupDialog ActivityInvalid.."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new CommonPopupDialog(mContext, title, btnItems, cancelBtnText, isFullScreen); + mDialog.setCancelable(mCanceledOnClickBackKey); + mDialog.setCanceledOnTouchOutside(true); + mDialog.show(); + } + + public void showCommonPopupDialog(String title, List btnItems, String cancelBtnText) { + + if (!checkActivityValid()) { + MLog.info(this, "showCommonPopupDialog ActivityInvalid.."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new CommonPopupDialog(mContext, title, btnItems, cancelBtnText); + mDialog.setCancelable(mCanceledOnClickBackKey); + mDialog.setCanceledOnTouchOutside(true); + mDialog.show(); + } + + public void showCustomPopupDialog(String title, List btnItems) { + if (!checkActivityValid()) { + MLog.info(this, "showCommonPopupDialog ActivityInvalid..."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new CustomPopupDialog(mContext, title, btnItems); + mDialog.setCancelable(mCanceledOnClickBackKey); + mDialog.setCanceledOnTouchOutside(mCanceledOnClickOutside); + mDialog.show(); + } + + public void showCommonPopupDialog(int id, String title, List btnItems, ButtonItem bottomButton) { + if (!checkActivityValid()) { + MLog.info(this, "showCommonPopupDialog ActivityInvalid...."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = new CommonPopupDialog(id, mContext, title, btnItems, bottomButton); + mDialog.setCancelable(mCanceledOnClickBackKey); + mDialog.setCanceledOnTouchOutside(mCanceledOnClickOutside); + mDialog.show(); + } + + public int getShowingDialogId() { + if (mDialog.isShowing() && mDialog instanceof CommonPopupDialog) { + return ((CommonPopupDialog) mDialog).getId(); + } + return 0; + } + + public Dialog getDialog() { + return mDialog; + } + + public interface DynamicTokenLoginDialogListener { + public void onOK(String token); + + public void onCancle(); + } + + public interface InputPwdDialogListener { + public void onConfirm(); + + public void onCancel(); + } + + public interface OkCancelDialogListener { + + default void onCancel() { + //默认空实现 + } + + void onOk(); + } + + public static abstract class AbsOkDialogListener implements OkCancelDialogListener { + public void onCancel() { + //do nothing + } + + public abstract void onOk(); + } + + public void showOkCancelDialog(CharSequence message, boolean cancelable, final OkCancelDialogListener l) { + showOkCancelDialog(message, getContext().getString(R.string.text_ok), + getContext().getString(R.string.text_canle), cancelable, l); + } + + public void showOkCancelDialog(CharSequence message, CharSequence okLabel, final OkCancelDialogListener l) { + showOkCancelDialog(message, okLabel, getContext().getString(R.string.text_canle), true, l); + } + + public void showOkCancelDialog(CharSequence message, final OkCancelDialogListener l) { + showOkCancelDialog(message, getContext().getString(R.string.text_ok), + getContext().getString(R.string.text_canle), true, l); + } + + public void showOkCancelDialog(CharSequence message, CharSequence okLabel, CharSequence cancelLabel, final OkCancelDialogListener l) { + showOkCancelDialog(message, okLabel, cancelLabel, true, l); + } + + public void showTipsDialog(String message, OkCancelDialogListener l) { + showOkCancelWithTitleDialog(getContext().getString(R.string.common_tip), new SpannableString(message), + getContext().getString(R.string.text_ok), getContext().getString(R.string.text_canle), l); + } + + public void showTipsDialog(CharSequence message, String okLabel, OkCancelDialogListener l) { + showOkCancelWithTitleDialog(getContext().getString(R.string.common_tip), message, + okLabel, getContext().getString(R.string.text_canle), l); + } + + public void showOkCancelWithTitleDialog(CharSequence message, + final OkCancelDialogListener l) { + showOkCancelWithTitleDialog(message, getContext().getString(R.string.text_ok), + mCanceledOnClickOutside, l); + } + + public void showOkCancelWithTitleDialog(CharSequence message, CharSequence okLabel, + final OkCancelDialogListener l) { + showOkCancelWithTitleDialog(message, okLabel, mCanceledOnClickOutside, l); + } + + public void showOkCancelWithTitleDialog(CharSequence message, + CharSequence okLabel, + boolean isCanCancel, + final OkCancelDialogListener l) { + showOkCancelWithTitleDialog(getContext().getString(R.string.common_tip), message, okLabel, + isCanCancel, l); + } + + public void showOkCancelWithTitleDialog(CharSequence titleStr, CharSequence message, + CharSequence okLabel, boolean isCanCancel, + final OkCancelDialogListener l) { + showOkCancelDialog(titleStr, message, okLabel, getContext().getString(R.string.text_canle), + isCanCancel, l); + } + + public void showOkCancelWithTitleDialog(CharSequence titleStr, CharSequence message, + CharSequence okLabel, CharSequence cancelLabel, + final OkCancelDialogListener l) { + showOkCancelDialog(titleStr, message, okLabel, cancelLabel, l); + } + + + public void showOkCancelWithTitleDialog(CharSequence titleStr, CharSequence message, + CharSequence okLabel, CharSequence cancelLabel, + boolean isCanCancel, + final OkCancelDialogListener l) { + showOkCancelDialog(titleStr, message, okLabel, cancelLabel, isCanCancel, l); + } + + public void showOkCancelDialog(CharSequence title, CharSequence message, CharSequence okLabel, CharSequence cancelLabel, + final OkCancelDialogListener l) { + showOkCancelDialog(title, message, okLabel, cancelLabel, mCanceledOnClickOutside, l); + } + + public void showOkCancelDialog(CharSequence title, CharSequence message, CharSequence okLabel, + CharSequence cancelLabel, boolean isCanCancel, + final OkCancelDialogListener l) { + showOkCancelDialog(title, message, okLabel, cancelLabel, isCanCancel, true, l); + } + + /** + * 1、轻寻通用的dialog设置,以后尽量所有的dialog都引到这个方法,方便以后改版 + * 2、如果UI要求弹框是完全自定义的,再重新写过 + * @param title 标题,空则隐藏 (ui说,有些弹框带标题,有些不带,两种情况共存) + * @param message 内容,不能为空,配合{@link com.yizhuan.erban.utils.SpannableBuilder} 变色使用 + * @param okLabel ok按钮,不能隐藏,默认为 text="确定" + * @param cancelLabel 取消按钮,空则隐藏,一般现在都用text="取消" + * @param l 点击监听 + * @param isCanCancel 点击返回键是否可以取消,默认=false,dialog初始化的时候,为false + * (ui说,ture和false根据情况而定,一般自己根据理解选择) + * @param canceledOnTouchOutside ture的话,点击背景消失 + * @param isAutoHide 默认ture,点击按钮的时候,自动隐藏dialog,(暂时用不到属性,放着先) + * @param backListener 弹窗返回键的监听 + * @param dismissAfterBack 点击返回键是否自动dismiss + */ + public void showOkCancelDialog(CharSequence title, CharSequence message, CharSequence okLabel, + CharSequence cancelLabel, boolean isCanCancel, boolean canceledOnTouchOutside, + final boolean isAutoHide, final OkCancelDialogListener l, + final OnKeyBackListener backListener, boolean dismissAfterBack) { + + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelDialog ActivityInvalid...."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + mDialog.show(); + + setDialog(mDialog, title, message, okLabel, cancelLabel, isCanCancel, + canceledOnTouchOutside, isAutoHide, l, backListener, dismissAfterBack); + + } + + public void showOkCancelDialog(CharSequence title, CharSequence message, CharSequence okLabel, + CharSequence cancelLabel, boolean isCanCancel, + final boolean isAutoHide, final OkCancelDialogListener l) { + //一般情况,点击背景和返回键一起处理 + showOkCancelDialog(title, message, okLabel, cancelLabel, isCanCancel, isCanCancel, + isAutoHide, l, null, false); + } + + public void showOkCancelDialog(CharSequence message, CharSequence okLabel, CharSequence cancelLabel, + boolean cancelable, final OkCancelDialogListener l) { + showOkCancelDialog(null, message, okLabel, cancelLabel, cancelable, l); + } + + + public void showOkCancelDialog(CharSequence title, CharSequence[] messages, + final OkCancelDialogListener l) { + showOkCancelDialog(title, messages, getContext().getString(R.string.text_ok), + getContext().getString(R.string.text_canle), mCanceledOnClickOutside, l); + } + + /** + * @param title 不需要则传空 + * @param messages 黑色文字和主题色文字轮着来的一个字符串数组 + */ + public void showOkCancelDialog(CharSequence title, CharSequence[] messages, + CharSequence okLable, CharSequence cancelLable, + boolean isCanCancel, + final OkCancelDialogListener l) { + SpannableBuilder builder = new SpannableBuilder(); + for (int i = 0; i < messages.length; i++) { + if (i % 2 == 0) { + builder.append(messages[i]); + } else { + builder.append(messages[i], new ForegroundColorSpan( + getContext().getResources().getColor(R.color.appColor))); + } + } + showOkCancelDialog(title, builder.build(), okLable, + cancelLable, isCanCancel, l); + } + + /** + * @param messages 黑色文字和主题色文字轮着来的一个字符串数组 + */ + public void showOkCancelWithTitleDialog(CharSequence [] messages, + final OkCancelDialogListener l) { + showOkCancelDialog(getContext().getString(R.string.common_tip), messages, l); + } + + public void showOkCancelWithTitleDialog(CharSequence[] messages, String okLable, boolean isCanCancel, + final OkCancelDialogListener l) { + showOkCancelDialog(getContext().getString(R.string.common_tip), messages, okLable, + getContext().getString(R.string.text_canle), isCanCancel, l); + } + + public void showBuyCarSucDialog(String msg) { + + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelDialog ActivityInvalid.."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + + mDialog.setCancelable(true); + mDialog.setCanceledOnTouchOutside(mCanceledOnClickOutside); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setContentView(R.layout.dialog_buy_decoration); + TextView view = window.findViewById(R.id.tv_msg); + view.setText(msg); + window.setGravity(Gravity.CENTER); + window.findViewById(R.id.tv_iknow).setOnClickListener(v -> mDialog.dismiss()); + } + + public void showLuckyMoneyConfirmToPayDialog(String amount, String fee, String coinName, View.OnClickListener listener) { + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelDialog ActivityInvalid.."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + mDialog.setCancelable(false); + mDialog.setCanceledOnTouchOutside(false); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setContentView(R.layout.dialog_lucky_money_confirm_to_pay); + window.setGravity(Gravity.CENTER); + TextView subTitle = window.findViewById(R.id.tv_sub_title_pay_lucky_money); + subTitle.setText(mContext.getString(R.string.lucky_money_pay_sub_title, coinName)); + TextView amountTextView = window.findViewById(R.id.tv_lucky_money_amount); + amountTextView.setText(amount); + TextView amountCoinName = window.findViewById(R.id.tv_coin_name); + amountCoinName.setText(coinName); + TextView feeTextView = window.findViewById(R.id.tv_lucky_money_fee); + feeTextView.setText(fee); + TextView feeCoinName = window.findViewById(R.id.tv_lucky_money_fee_coin_name); + feeCoinName.setText(coinName); + window.findViewById(R.id.iv_close).setOnClickListener(v -> mDialog.dismiss()); + Button btn = window.findViewById(R.id.btn_ready_to_pay); + btn.setOnClickListener(v -> { + mDialog.dismiss(); + listener.onClick(v); + }); + } + + public void showInAppSharingConfirmDialog(String avatar, String nick, String msg, OkCancelDialogListener l) { + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelDialog ActivityInvalid...."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + + mDialog.setCancelable(true); + mDialog.setCanceledOnTouchOutside(true); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setGravity(Gravity.CENTER); + window.setContentView(R.layout.dialog_in_app_sharing_confirm); + + ImageView avatarView = window.findViewById(R.id.iv_avatar); + ImageLoadUtils.loadAvatar(getContext().getApplicationContext(), avatar, avatarView, true); + + TextView nickView = window.findViewById(R.id.tv_nick); + nickView.setText(nick); + + TextView tvMessage = (TextView) window.findViewById(R.id.message); + tvMessage.setText(msg); + + TextView ok = window.findViewById(R.id.btn_ok); + ok.setOnClickListener(v -> { + mDialog.dismiss(); + if (l != null) { + l.onOk(); + } + }); + + TextView cancel = window.findViewById(R.id.btn_cancel); + cancel.setOnClickListener(v -> { + mDialog.dismiss(); + if (l != null) { + l.onCancel(); + } + }); + } + + public void showCustomViewDialog(View contentView) { + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelColorDialog ActivityInvalid...."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setContentView(contentView); + + } + + public void showCustomViewDialog(int id) { + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelColorDialog ActivityInvalid...."); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setContentView(id); + + } + + public void showOkCancelSwitchDialog(CharSequence message, OkCancelDialogListener l) { + if (!ActivityUtil.isValidContext(mContext)) { + return; + } + showOkCancelSwitchDialog(mContext.getString(R.string.common_tip), message, + mContext.getString(R.string.text_ok), mContext.getString(R.string.text_canle), + mCanceledOnClickOutside, l); + } + + public void showOkCancelSwitchDialog(CharSequence title, CharSequence message, CharSequence okLabel, + CharSequence cancelLabel, boolean isCanCancel, OkCancelDialogListener l) { + if (!ActivityUtil.isValidContext(mContext)) { + return; + } + View contentView = View.inflate(mContext, R.layout.dialog_custom_one_show_tips, null); + TextView tvTitle = contentView.findViewById(R.id.tv_title); + if (TextUtils.isEmpty(title)) { + tvTitle.setVisibility(View.GONE); + } else { + tvTitle.setVisibility(View.VISIBLE); + tvTitle.setText(title); + } + TextView tvMessage = contentView.findViewById(R.id.message); + tvMessage.setText(message); + switchTips = contentView.findViewById(R.id.switch_tips); + showOkCancelCustomDialog(contentView, okLabel, cancelLabel, isCanCancel, l); + } + + + public void showOkCancelCustomDialog(View customView, boolean isCanCancel, OkCancelDialogListener l) { + showOkCancelCustomDialog(customView, getContext().getString(R.string.text_ok), + getContext().getString(R.string.text_canle), isCanCancel, true, l); + } + + + public void showOkCancelCustomDialog(View customView, CharSequence okLabel, CharSequence cancelLabel, + boolean isCanCancel, OkCancelDialogListener l) { + showOkCancelCustomDialog(customView, okLabel, cancelLabel, isCanCancel, true, l); + } + + public void showOkCancelCustomDialog(View customView, CharSequence okLabel, CharSequence cancelLabel, + boolean isCanCancel, boolean isAutoHide, OkCancelDialogListener l) { + if (!checkActivityValid()) { + MLog.info(this, "showOkCancelDialog ActivityInvalid...."); + return; + } + + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = mBuilder.create(); + + mDialog.setCancelable(isCanCancel); + mDialog.setCanceledOnTouchOutside(isCanCancel); + mDialog.show(); + Window window = mDialog.getWindow(); + window.setContentView(R.layout.layout_custom_ok_cancel_dialog); + FrameLayout flContent = window.findViewById(R.id.fl_content); + flContent.addView(customView, new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT + )); + TextView ok = (TextView) window.findViewById(R.id.btn_ok); + if (!TextUtils.isEmpty(okLabel)) { + ok.setText(okLabel); + } + ok.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (isAutoHide) { + mDialog.dismiss(); + } + if (l != null) { + l.onOk(); + } + } + }); + + TextView cancel = (TextView) window.findViewById(R.id.btn_cancel); + if (!TextUtils.isEmpty(cancelLabel)) { + cancel.setText(cancelLabel); + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (isAutoHide) { + mDialog.dismiss(); + } + if (l != null) { + l.onCancel(); + } + } + }); + } else { + cancel.setVisibility(View.GONE); + } + + } + + + public void setReCreate(boolean reCreate) { + mReCreate = reCreate; + } + + public void showProgressDialog(Context context) { + showProgressDialog(context, "请稍后...", mCanceledOnClickBackKey); + } + + public void showProgressDialog(Context context, boolean cancelable) { + showProgressDialog(context, "请稍后...", cancelable); + } + + public void showProgressDialog(Context context, String msg) { + showProgressDialog(context, msg, mCanceledOnClickBackKey); + } + + public void showProgressDialog(Context context, String msg, boolean cancelable) { + showProgressDialog(context, msg, cancelable, null); + } + + public void showProgressDialog(Context context, String msg, boolean cancelable, DialogInterface.OnDismissListener listener) { + showProgressDialog(context, msg, cancelable, mCanceledOnClickOutside, listener); + } + + public void showProgressDialog(Context context, String msg, boolean cancelable, boolean outSideCancelable, + DialogInterface.OnDismissListener listener, DialogInterface.OnCancelListener cancelListener) { + showProgressDialog(context, msg, cancelable, outSideCancelable, listener); + if (cancelListener != null) { + mDialog.setOnCancelListener(cancelListener); + } + } + + /** + * @param context + * @param msg + * @param cancelable 点击返回键是否可取消 + * @param outSideCancelable 点击对话框外部是否可取消 + * @param listener + */ + public void showProgressDialog(Context context, String msg, boolean cancelable, boolean outSideCancelable, DialogInterface.OnDismissListener listener) { + if (!checkActivityValid()) { + MLog.info(this, "showProgressDialog ActivityInvalid"); + return; + } + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + if (mReCreate) { + mDialog = mBuilder.create(); + } + mDialog.setCancelable(cancelable); + mDialog.setCanceledOnTouchOutside(outSideCancelable); + if (null != mContext) { + mDialog.show(); + } + mDialog.setContentView(R.layout.layout_progress_dialog); + TextView tvTip = (TextView) mDialog.findViewById(R.id.tv_tip); + //tvTip.setText(msg); + //叶彬说统一文案,用loading... + tvTip.setText(R.string.common_loading_tips); + + mDialog.setOnDismissListener(dialog -> { + if (listener != null) { + listener.onDismiss(dialog); + } + }); + } + + private int mProgressMax = 0; + private String mTip; + + public void setText(String text) { + mTip = text; + } + + public void setMax(int max) { + mProgressMax = max; + } + + public void setProgress(int progress) { + if (mDialog != null && mDialog.isShowing() && mProgressMax > 0) { + ((TextView) mDialog.findViewById(R.id.tv_tip)).setText(mTip + progress * 100 / mProgressMax + "%"); + } + } + + public void hideProgressDialog() { + if (mDialog != null) { + mDialog.hide(); + } + } + + /** + * 加好友或群验证码的对话框 + */ + public void showInputPwdDialog(String title, String okLabel, String cancelLabel, final String resultCode, final InputPwdDialogListener listener) { + + if (!checkActivityValid()) { + MLog.info(this, "showPicAddFriendGroupDialog ActivityInvalid...."); + return; + } + + if (mDialog.isShowing()) { + mDialog.hide(); + } + mDialog.show(); + + Window window = mDialog.getWindow(); + window.setContentView(R.layout.layout_pic_login_dialog); + TextView titleView = (TextView) window.findViewById(R.id.pic_login_title); + final EditText input = (EditText) window.findViewById(R.id.pic_login_input); + final TextView failMsg = (TextView) window.findViewById(R.id.pic_login_fail_msg); + TextView confirm = (TextView) window.findViewById(R.id.btn_confirm); + TextView mCancel = (TextView) window.findViewById(R.id.btn_cancel); + mDialog.setCancelable(false); + mDialog.setCanceledOnTouchOutside(false); + + //只用下面这一行弹出对话框时需要点击输入框才能弹出软键盘 + window.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + //加上下面这一行弹出对话框时软键盘随之弹出 + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + if (!TextUtils.isEmpty(title)) + titleView.setText(title); + if (!TextUtils.isEmpty(cancelLabel)) + mCancel.setText(cancelLabel); + if (!TextUtils.isEmpty(okLabel)) + confirm.setText(okLabel); + + confirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!StringUtil.isEmpty(resultCode)) { + if (resultCode.equals(input.getText().toString())) { + if (listener != null) { + listener.onConfirm(); + mDialog.dismiss(); + } + } else { + failMsg.setVisibility(View.VISIBLE); + } + } else { + failMsg.setVisibility(View.VISIBLE); + } + } + }); + + mCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onCancel(); + mDialog.dismiss(); + } + } + }); + } + + public interface OnClickListener { + public void onClick(View view, int btnIndex); + } + + private String getTicketProtcol(long channelId, long subChannelId, String title) { + return "yy://pd-[sid=" + channelId + "&subid=" + subChannelId + "]\n" + title; + } + + private String getTicketProtcol(long channelId, long subChannelId) { + return "yy://pd-[sid=" + channelId + "&subid=" + subChannelId + "]"; + } + + public interface OnInputPasswordClickListener { + void onOk(String password); + + void onCancel(); + } + + public static boolean isHtmlAlertDialog(String html) { + try { + return html.matches(".*<([^>]*)>.*"); + } catch (Exception e) { + return false; + } + } + + public AlertDialog.Builder getBuilder() { + return mBuilder; + } + + public interface LambdaOkDialogListener extends OkCancelDialogListener { + default void onCancel() { + //do nothing + } + } + + public boolean isOpenSwitch() { + return switchTips != null && switchTips.isChecked(); + } + + public interface OnKeyBackListener{ + void onBack(); + } + + /** + * 注释 见 {@link DialogManager#showOkCancelDialog( + * CharSequence, CharSequence, CharSequence, CharSequence, boolean, + * boolean, boolean, OkCancelDialogListener, OnKeyBackListener, boolean)} + */ + public static void setDialog(Dialog dialog, CharSequence title, CharSequence message, CharSequence okLabel, + CharSequence cancelLabel, boolean isCanCancel, boolean canceledOnTouchOutside, + final boolean isAutoHide, final OkCancelDialogListener l, + final OnKeyBackListener backListener, boolean dismissAfterBack) { + dialog.setCancelable(isCanCancel); + dialog.setCanceledOnTouchOutside(canceledOnTouchOutside); + + Window window = dialog.getWindow(); + window.setContentView(R.layout.layout_common_ok_cancel_dialog); + //标题 + TextView tvTilte = window.findViewById(R.id.tv_title); + if (tvTilte != null) { + if (!TextUtils.isEmpty(title)) { + tvTilte.setVisibility(View.VISIBLE); + tvTilte.setText(title); + } else { + tvTilte.setVisibility(View.GONE); + } + } + //内容 + TextView tip = window.findViewById(R.id.message); + tip.setText(message); + + TextView ok = (TextView) window.findViewById(R.id.btn_ok); + if (!TextUtils.isEmpty(okLabel)) { + ok.setText(okLabel); + } + ok.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (isAutoHide) { + dialog.dismiss(); + } + if (l != null) { + l.onOk(); + } + } + }); + + TextView cancel = (TextView) window.findViewById(R.id.btn_cancel); + if (!TextUtils.isEmpty(cancelLabel)) { + cancel.setText(cancelLabel); + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (isAutoHide) { + dialog.dismiss(); + } + if (l != null) { + l.onCancel(); + } + } + }); + } else { + cancel.setVisibility(View.GONE); + } + + if (backListener != null) { + dialog.setOnKeyListener((dialog1, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 + && event.getAction() == KeyEvent.ACTION_DOWN) { + if (dismissAfterBack) { + dialog.dismiss(); + } + backListener.onBack(); + return true; + } + return false; + }); + } + } + + public static Dialog createDialog(Context context) { + AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.MyAlertDialogStyle); + return builder.create(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogUiHelper.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogUiHelper.java new file mode 100644 index 000000000..818c79e2d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/DialogUiHelper.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.content.Context; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.radish.task.activity.TaskCenterActivity; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * 弹框帮助类,减少一些的代码的冗余 + * create by lvzebiao @2019/3/22 + */ +public class DialogUiHelper { + + public static String CHARGE_FROM = ""; + + /** + * 萝卜不足统一弹框处理 + */ + public static void showRadishNotEnoughDialog(Context context, DialogManager dialogManager) { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + String[] messages = new String[]{"您的萝卜不足,请前往任务中心\n", "完成任务获取更多的萝卜"}; + dialogManager.showOkCancelWithTitleDialog(messages, "前往", true, () -> { + if (!ActivityUtil.isValidContext(context)) { + return; + } + TaskCenterActivity.start(context, TaskCenterActivity.FromPage.RADISH_NOT_ENOUGH_DIALOG); + }); + } + + public static void showNeedCharge(Context context, DialogManager dialogManager) { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + dialogManager.showOkCancelDialog("余额不足,请充值", + true, () -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_NOT_ENOUGH_TO_RECHARGE, + "余额不足_去充值:" + CHARGE_FROM); + ChargeActivity.start(context); + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ListViewMenuItem.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ListViewMenuItem.java new file mode 100644 index 000000000..02a2f219f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/ListViewMenuItem.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.common.widget.dialog; + +/** + * Creator: Chanry + * Date:2016/7/20 + * Time: 17:31 + *

+ * Description: 列表长按出现的菜单 + */ +public class ListViewMenuItem { + + public String mTitle; + public OnClickListener mClickListener; + + public interface OnClickListener { + void onClick(); + } + + public void setTitle(String title) { + mTitle = title; + } + + public void setOnClickListener(OnClickListener listener) { + this.mClickListener = listener; + } + + public ListViewMenuItem(String mTitle, OnClickListener mClickListener) { + this.mTitle = mTitle; + this.mClickListener = mClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoadingImageView.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoadingImageView.java new file mode 100644 index 000000000..c00873a44 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoadingImageView.java @@ -0,0 +1,56 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.animation.ObjectAnimator; +import android.content.Context; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; +import android.view.animation.LinearInterpolator; + +/** + * create by lvzebiao @2019/12/5 + */ +public class LoadingImageView extends AppCompatImageView { + + private ObjectAnimator loadingAnim; + + public LoadingImageView(Context context) { + this(context, null); + } + + public LoadingImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LoadingImageView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + startAnim(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + stopAnim(); + } + + public void startAnim() { + stopAnim(); + loadingAnim = ObjectAnimator.ofFloat(this, "rotation", 0f, 360f); + loadingAnim.setDuration(1000); + loadingAnim.setRepeatCount(-1); + loadingAnim.setInterpolator(new LinearInterpolator()); + loadingAnim.start(); + } + + private void stopAnim() { + if (loadingAnim != null) { + loadingAnim.cancel(); + loadingAnim = null; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoginPopupDialog.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoginPopupDialog.java new file mode 100644 index 000000000..8d25c80d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/LoginPopupDialog.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.common.widget.dialog; + + +import android.app.Dialog; +import android.content.Context; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; + + +public class LoginPopupDialog extends Dialog implements OnClickListener { + + private ViewGroup mContentView; + private View mBtnRegister; + private View mBtnLogin; + private View mQQLogin; + private View mSinaLogin; + private View mWeChatLogin; + + private OnLoginPopupDialogListener mL; + + public LoginPopupDialog(Context context, final OnLoginPopupDialogListener l) { + super(context, R.style.Dialog_Fullscreen); + mL = l; + mContentView = (ViewGroup) View.inflate(getContext(), R.layout.layout_login_popup_dialog, null); + //mTvTitle = (TextView) mContentView.findViewById(R.id.tv_title); + mBtnRegister = mContentView.findViewById(R.id.btn_register); + mBtnLogin = mContentView.findViewById(R.id.btn_login); +// mQQLogin = mContentView.findViewById(R.id.qq_login); +// mSinaLogin = mContentView.findViewById(R.id.sina_login); +// mWeChatLogin = mContentView.findViewById(R.id.wechat_login); + mBtnRegister.setOnClickListener(this); + mBtnLogin.setOnClickListener(this); +// mQQLogin.setOnClickListener(this); +// mSinaLogin.setOnClickListener(this); +// mWeChatLogin.setOnClickListener(this); + + setContentView(mContentView); + setCanceledOnTouchOutside(true); + + Window window = getWindow(); + WindowManager.LayoutParams params = window.getAttributes(); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setGravity( Gravity.BOTTOM ); + window.setAttributes(params); + window.setWindowAnimations(R.style.DialogAnimation); + } + + @Override + public void onClick(View arg0) { + if(arg0 == mBtnRegister){ + mL.onClickRegister(); + } else if(arg0 == mBtnLogin){ + mL.onClickLogin(); + } else if (arg0 == mQQLogin) { + mL.onClickQQ(); + } else if (arg0 == mSinaLogin) { + mL.onClickWeibo(); + } else if (arg0 == mWeChatLogin) { + mL.onClickWeChat(); + } + dismiss(); + } + + public interface OnLoginPopupDialogListener{ + void onClickRegister(); + void onClickLogin(); + void onClickWeibo(); + void onClickQQ(); + void onClickWeChat(); + void dismissDialog(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/common/widget/dialog/TimeOutProgressDialog.java b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/TimeOutProgressDialog.java new file mode 100644 index 000000000..d877a8149 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/common/widget/dialog/TimeOutProgressDialog.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.common.widget.dialog; + +import android.app.Activity; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import com.yizhuan.erban.R; + +/** + * Created by qinbo on 2014/7/2. + */ +public class TimeOutProgressDialog { + private Activity mContext; + private String msg; + + private long time; + + private DialogManager dialogManager; + /** + * + * @param context + * @param msg + * @param time 单位微妙 + */ + public TimeOutProgressDialog(Activity context, String msg, long time){ + this.mContext = context; + this.msg = msg; + this.time = time; + + dialogManager = new DialogManager(mContext); + } + + public TimeOutProgressDialog(Activity context){ + this.mContext = context; + dialogManager = new DialogManager(mContext); + } + + public void setTime(long time) { + this.time = time; + } + + + private Handler handler = new Handler(Looper.myLooper()); + + public void showProcessProgress() { + /*if (dialogManager == null && mContext != null) { + dialogManager = new DialogManager(mContext); + }else{ + MLog.error(this, "parent activity not instance of ActivitySupport."); + }*/ + if (dialogManager != null&&mContext != null) { + hideProcessProgress(); + dialogManager.showProgressDialog(mContext, msg, false, false, null); + handler.postDelayed(processProgressTimeoutTask, time); + } + } + + public void showProcessProgress(String tip, long seconds) { + if (dialogManager != null && mContext != null) { + hideProcessProgress(); + dialogManager.showProgressDialog(mContext, tip, false, false, null); + handler.postDelayed(processProgressTimeoutTask, seconds); + } + } + + public void hideProcessProgress() { + handler.removeCallbacks(processProgressTimeoutTask); + if (dialogManager != null) { + dialogManager.dismissDialog(); + } + } + + private Runnable processProgressTimeoutTask = new Runnable() { + @Override + public void run() { + //if (mContext != null) { + if (dialogManager != null) { + dialogManager.dismissDialog(); + } +// if (!NetworkUtils.isNetworkAvailable(mContext)) { +// Toast.makeText(mContext,R.string.str_network_not_capable, Toast.LENGTH_LONG).show(); +// } else { + Toast.makeText(mContext, R.string.str_network_not_capable, Toast.LENGTH_LONG).show(); + //} + //} + } + }; +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/constants/BundleKeys.java b/app/src/main/java/com/yizhuan/erban/constants/BundleKeys.java new file mode 100644 index 000000000..b1e117c51 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/constants/BundleKeys.java @@ -0,0 +1,19 @@ +package com.yizhuan.erban.constants; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class BundleKeys { + public final static String KEY_OBJ = "KEY_OBJ"; + + public final static String KEY_EXTRA_1 = "KEY_EXTRA_1"; + public final static String KEY_EXTRA_2 = "KEY_EXTRA_2"; + public final static String KEY_EXTRA_3 = "KEY_EXTRA_3"; + public final static String KEY_EXTRA_4 = "KEY_EXTRA_4"; + public final static String KEY_EXTRA_5 = "KEY_EXTRA_5"; + + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/adapter/CarShopAdapter.java b/app/src/main/java/com/yizhuan/erban/decoration/adapter/CarShopAdapter.java new file mode 100644 index 000000000..b78199d3a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/adapter/CarShopAdapter.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.decoration.adapter; + +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemCarShopBinding; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +/** + * Created by huangmeng1 on 2018/5/9. + */ +public class CarShopAdapter extends BaseAdapter { + private int selectPosition; + + public int getSelectPosition() { + return selectPosition; + } + + public void setSelectPosition(int selectPosition) { + this.selectPosition = selectPosition; + } + + public CarShopAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, CarInfo item) { + super.convert(helper, item); + helper.addOnClickListener(R.id.tv_try_drive); + + ItemCarShopBinding binding = (ItemCarShopBinding) helper.getBinding(); + boolean isSelect = selectPosition == helper.getAdapterPosition(); + binding.llCarHolder.setSelected(isSelect); + binding.setSelectPosition(isSelect); + + if (item.getLabelType() == CarInfo.TAG_TYPE_NORMAL) { + binding.ivTag.setVisibility(View.GONE); + + } else if (CarInfo.TAG_TYPE_NEW == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_new); + + } else if (CarInfo.TAG_TYPE_DISCOUNT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_discount); + + } else if (CarInfo.TAG_TYPE_LIMIT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_limit); + + } else if (CarInfo.TAG_TYPE_EXCLUSIVE == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_exclusive); + } + } + + public void setCarInfoHasBeenBought(CarInfo carInfo) { + if (carInfo.getCarId() <= 0 || ListUtils.isListEmpty(mData)) return; + int index = mData.indexOf(carInfo); + if (index == -1) return; + mData.get(index).setStatus(CarInfo.STATUS_USER_CAN_USE); + mData.get(index).setRemainingDay(carInfo.getDays()); + notifyItemChanged(index); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/adapter/HeadWearShopAdapter.java b/app/src/main/java/com/yizhuan/erban/decoration/adapter/HeadWearShopAdapter.java new file mode 100644 index 000000000..a08c1cbba --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/adapter/HeadWearShopAdapter.java @@ -0,0 +1,72 @@ +package com.yizhuan.erban.decoration.adapter; + +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemHeadWearBinding; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +/** + * Created by huangmeng1 on 2018/5/10. + */ + +public class HeadWearShopAdapter extends BaseAdapter { + private int selectPosition; + + public int getSelectPosition() { + return selectPosition; + } + + public void setSelectPosition(int selectPosition) { + notifyItemChanged(this.selectPosition); + this.selectPosition = selectPosition; + notifyItemChanged(this.selectPosition); + } + + public HeadWearShopAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, HeadWearInfo item) { + super.convert(helper, item); + ItemHeadWearBinding binding = (ItemHeadWearBinding) helper.getBinding(); + binding.llRoot.setSelected(selectPosition == helper.getAdapterPosition()); + NobleUtil.loadHeadWears(item.getPic(), binding.ivHeadWear); + binding.setSelectPosition(selectPosition == helper.getAdapterPosition()); + + if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) { + binding.ivTag.setVisibility(View.GONE); + + } else if (HeadWearInfo.LABEL_TYPE_NEW == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_new); + + } else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_discount); + + } else if (HeadWearInfo.LABEL_TYPE_LIMIT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_limit); + + } else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_exclusive); + } + + binding.tvHeadName.setText(item.getName() + ""); + } + + public void setCarInfoHasBeenBought(HeadWearInfo carInfo) { + if (carInfo.getHeadwearId() <= 0 || ListUtils.isListEmpty(mData)) return; + int index = mData.indexOf(carInfo); + if (index == -1) return; + mData.get(index).setStatus(HeadWearInfo.STATUS_IN_USED); + notifyItemChanged(index); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyCarAdapter.java b/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyCarAdapter.java new file mode 100644 index 000000000..fb0a92965 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyCarAdapter.java @@ -0,0 +1,168 @@ +package com.yizhuan.erban.decoration.adapter; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemCarGarageNormalBinding; +import com.yizhuan.xchat_android_core.decoration.bean.BaseDecoration; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +/** + * Created by yudi + * on 2018/3/2. + */ +public class MyCarAdapter extends BaseAdapter { + + public MyCarAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, CarInfo item) { + super.convert(helper, item); + + ItemCarGarageNormalBinding binding = (ItemCarGarageNormalBinding) helper.getBinding(); + + GlideApp.with(binding.ivCarCover) + .load(item.getPic()) + .dontAnimate() + .dontTransform() + .fitCenter() + .into(binding.ivCarCover); + + helper.addOnClickListener(R.id.tv_buy); + helper.addOnClickListener(R.id.tv_used); + + // 倒计时 + int remainingDay = item.getRemainingDay(); + int status = item.getStatus(); + boolean canUse; + + binding.tvCarPrice.setText(item.getPriceStr()); + if (remainingDay >= 0 && status == CarInfo.STATUS_USER_CAN_USE) { + // 一定是续费按钮 + binding.tvBuy.setVisibility(View.VISIBLE); + binding.tvBuy.setText("续费"); + binding.tvBuy.setBackgroundResource(R.drawable.bg_my_head_renew); + + canUse = true; + } else { + canUse = false; + // 根据状态显示倒计时 + // 根据状态判断是购买按钮还是隐藏按钮 + if (status == CarInfo.STATUS_OFF_SHELF) { + // 隐藏购买按钮 + binding.tvBuy.setVisibility(View.GONE); + } else if (status == CarInfo.STATUS_OUT_OF_DATE) { + // 续费或购买按钮 + binding.tvBuy.setVisibility(View.VISIBLE); + binding.tvBuy.setText("购买"); + binding.tvBuy.setBackgroundResource(R.drawable.bg_my_head_buy); + } + } + + // 时间 + if (remainingDay >= 0 && status == CarInfo.STATUS_USER_CAN_USE) { + binding.tvCounters.setText(String.format(binding.tvCounters.getResources().getString(R.string.decoration_status_wrapper), + binding.tvCounters.getResources().getString(R.string.decoration_remainder) + remainingDay + "天")); + } else { + if (status == CarInfo.STATUS_OFF_SHELF || status == CarInfo.STATUS_OUT_OF_DATE) { + binding.tvCounters.setText(String.format(binding.tvCounters.getResources().getString(R.string.decoration_status_wrapper), + binding.tvCounters.getResources().getString(R.string.past_due))); + } + } + + + setUseButton(binding.tvUsed, canUse, item.isUsing()); + updateTag(item, binding.ivTag, binding.tvBuy); + + if (status == CarInfo.STATUS_OFF_SHELF) { + binding.tvNoSeal.setVisibility(View.VISIBLE); + binding.tvNoSeal.setText("已下架"); + } else if (CarInfo.TAG_TYPE_LIMIT == item.getLabelType() || CarInfo.TAG_TYPE_EXCLUSIVE == item.getLabelType()) { + binding.tvNoSeal.setVisibility(View.VISIBLE); + binding.tvNoSeal.setText("暂不出售"); + } else + binding.tvNoSeal.setVisibility(View.GONE); + } + + private void setUseButton(TextView tvUsed, boolean canUse, boolean isUsing) { + + if (!canUse) { + tvUsed.setVisibility(View.GONE); + tvUsed.setText("使用"); + tvUsed.setBackgroundResource(R.drawable.bg_my_head_invalid); + tvUsed.setEnabled(false); + } else if (isUsing) { + tvUsed.setVisibility(View.VISIBLE); + tvUsed.setText("取消使用"); + tvUsed.setBackgroundResource(R.drawable.bg_my_head_invalid); + tvUsed.setEnabled(true); + } else { + tvUsed.setVisibility(View.VISIBLE); + tvUsed.setText("使用"); + tvUsed.setBackgroundResource(R.drawable.bg_my_head_buy); + tvUsed.setEnabled(true); + } + + } + + private void updateTag(CarInfo carInfo, ImageView ivTag, TextView tvBuy) { + if (CarInfo.TAG_TYPE_NORMAL == carInfo.getLabelType()) { + ivTag.setVisibility(View.GONE); + + } else if (CarInfo.TAG_TYPE_NEW == carInfo.getLabelType()) { + ivTag.setVisibility(View.VISIBLE); + ivTag.setImageResource(R.drawable.ic_mark_new); + + } else if (CarInfo.TAG_TYPE_DISCOUNT == carInfo.getLabelType()) { + ivTag.setVisibility(View.VISIBLE); + ivTag.setImageResource(R.drawable.ic_mark_discount); + + } else if (CarInfo.TAG_TYPE_LIMIT == carInfo.getLabelType()) { + ivTag.setVisibility(View.VISIBLE); + ivTag.setImageResource(R.drawable.ic_mark_limit); + tvBuy.setVisibility(View.GONE); + + } else if (CarInfo.TAG_TYPE_EXCLUSIVE == carInfo.getLabelType()) { + ivTag.setVisibility(View.VISIBLE); + ivTag.setImageResource(R.drawable.ic_mark_exclusive); + tvBuy.setVisibility(View.GONE); + } + } + + public void check(CarInfo selectedCarInfo) { + if (ListUtils.isListEmpty(mData)) return; + // 数据上改变那个using字段 + for (int i = 0; i < mData.size(); i++) { + CarInfo carInfo = mData.get(i); + if (selectedCarInfo.getCarId() == carInfo.getCarId()) { + carInfo.setUsing(1); + } else { + carInfo.setUsing(0); + } + } + notifyDataSetChanged(); + } + + public void setCarInfoHasBeenRenew(CarInfo carInfo) { + if (carInfo.getCarId() <= 0 || ListUtils.isListEmpty(mData)) return; + int index = mData.indexOf(carInfo); + if (index == -1) return; + if (mData.get(index).getRemainingDay() > 0) { + mData.get(index).setRemainingDay(mData.get(index).getRemainingDay() + carInfo.getDays()); + } else { + mData.get(index).setRemainingDay(carInfo.getDays()); + } + mData.get(index).setStatus(CarInfo.STATUS_USER_CAN_USE); + notifyItemChanged(index); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyHeadWearAdapter.java b/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyHeadWearAdapter.java new file mode 100644 index 000000000..42223cf07 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/adapter/MyHeadWearAdapter.java @@ -0,0 +1,99 @@ +package com.yizhuan.erban.decoration.adapter; + +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemMyHeadWearBinding; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +/** + * Created by huangmeng1 on 2018/5/11. + */ + +public class MyHeadWearAdapter extends BaseAdapter { + + public MyHeadWearAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, HeadWearInfo item) { + super.convert(helper, item); + ItemMyHeadWearBinding binding = (ItemMyHeadWearBinding) helper.getBinding(); + NobleUtil.loadHeadWear(item.getPic(), binding.ivCarCover); + helper.addOnClickListener(R.id.tv_buy); + helper.addOnClickListener(R.id.tv_used); + + if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) { + binding.ivTag.setVisibility(View.GONE); + + } else if (HeadWearInfo.LABEL_TYPE_NEW == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_new); + + } else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_discount); + + } else if (HeadWearInfo.LABEL_TYPE_LIMIT == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_limit); + + } else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == item.getLabelType()) { + binding.ivTag.setVisibility(View.VISIBLE); + binding.ivTag.setImageResource(R.drawable.ic_mark_exclusive); + } + + // 过期状态不可使用 + if (item.getStatus() == 2) { + binding.tvUsed.setVisibility(View.GONE); + binding.tvUsed.setEnabled(false); + binding.tvUsed.setBackgroundResource(R.drawable.bg_my_head_invalid); + binding.tvUsed.setText("使用"); + } else { + binding.tvUsed.setVisibility(View.VISIBLE); + binding.tvUsed.setEnabled(true); + } + + if (!item.isEnableStatus()) { + binding.tvBuy.setVisibility(View.GONE); + binding.tvNoSeal.setVisibility(View.VISIBLE); + binding.tvNoSeal.setText("已下架"); + + } else if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) { + binding.tvBuy.setVisibility(View.VISIBLE); + binding.tvNoSeal.setVisibility(View.GONE); + + } else if (HeadWearInfo.LABEL_TYPE_NEW == item.getLabelType()) { + binding.tvBuy.setVisibility(View.VISIBLE); + binding.tvNoSeal.setVisibility(View.GONE); + + } else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == item.getLabelType()) { + binding.tvBuy.setVisibility(View.VISIBLE); + binding.tvNoSeal.setVisibility(View.GONE); + + } else if (HeadWearInfo.LABEL_TYPE_LIMIT == item.getLabelType()) { + binding.tvBuy.setVisibility(View.GONE); + binding.tvNoSeal.setText("暂不出售"); + binding.tvNoSeal.setVisibility(View.VISIBLE); + + } else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == item.getLabelType()) { + binding.tvBuy.setVisibility(View.GONE); + binding.tvNoSeal.setText("暂不出售"); + binding.tvNoSeal.setVisibility(View.VISIBLE); + } + + // 日期展示 + if (item.getStatus() == 2) { // 过期 + binding.tvCounters.setText(mContext.getString(R.string.past_due)); + } else { + binding.tvCounters.setText(mContext.getString(R.string.decoration_remainder) + item.getExpireDays() + mContext.getString(R.string.day)); + } + + binding.tvCarPrice.setText(item.getPriceStr()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationDialogHelper.java b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationDialogHelper.java new file mode 100644 index 000000000..c9b9e20f1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationDialogHelper.java @@ -0,0 +1,363 @@ +package com.yizhuan.erban.decoration.helper; + +import android.content.Context; +import android.view.View; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.common.widget.dialog.DialogUiHelper; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.decoration.bean.BaseDecoration; +import com.yizhuan.xchat_android_core.decoration.bean.CurrencyType; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.headwear.HeadwearModel; +import com.yizhuan.xchat_android_core.utils.net.BalanceNotEnoughExeption; +import com.yizhuan.xchat_android_core.utils.net.RadishNotEnoughException; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import io.reactivex.functions.BiConsumer; +import lombok.Data; + +/** + * 装扮弹框统一处理 + * 赠送弹框,购买弹框 + * 4种情况 {@link DecorationSaleType} {@link Options} 引入 + * + * create by lvzebiao @2019/3/22 + */ +public class DecorationDialogHelper { + + private Context context; + + private RadioButton rbRadish; + + private Options options; + + private DialogManager dialogManager; + + public DecorationDialogHelper(Context context, DialogManager dialogManager, Options options) { + this.context = context; + this.options = options; + if (this.options == null) { + throw new IllegalArgumentException("option is null"); + } + this.dialogManager = dialogManager; + if (this.dialogManager == null) { + this.dialogManager = new DialogManager(context); + } + } + + /** + * 购买或者赠送弹框 + */ + public void showBuyOrDonateDialog() { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + View view = getBuyContentView(); + if (view == null) { + return; + } + dialogManager.showOkCancelCustomDialog(view, "确定", "取消", false, this::handleDialogOkClick); + } + + private View getBuyContentView() { + int type = options.getType(); + BaseDecoration decoration = options.getDecoration(); + String nick = options.getNick(); + View customViewGoldRadish = View.inflate(context, R.layout.custom_view_gold_radish, null); + TextView tvBuyTitle = customViewGoldRadish.findViewById(R.id.tv_buy_title); + TextView tvBuyContent = customViewGoldRadish.findViewById(R.id.tv_buy_content); + RadioGroup rgBuyUnit = customViewGoldRadish.findViewById(R.id.rg_buy_unit); + TextView tvSingleUnit = customViewGoldRadish.findViewById(R.id.tv_single_unit); + RadioButton rbGold = customViewGoldRadish.findViewById(R.id.rb_gold); + rbRadish = customViewGoldRadish.findViewById(R.id.rb_radish); + + String content = ""; + if (type == DecorationSaleType.BUY_HEAD_WEAR) { + int formatMsgId; + if (decoration.isRenew()) { + formatMsgId = R.string.renew_decoration_info_text; + } else { + formatMsgId = R.string.buy_decoration_info_text; + } + content = context.getResources().getString(formatMsgId, + decoration.getName(), String.valueOf(decoration.getDays())); + } else if (type == DecorationSaleType.BUY_CAR) { + int formatMsgId; + if (decoration.isRenew()) { + formatMsgId = R.string.renew_decoration_info_text; + } else { + formatMsgId = R.string.buy_decoration_info_text; + } + content = context.getResources().getString(formatMsgId, + decoration.getName(), String.valueOf(decoration.getDays())); + } else if (type == DecorationSaleType.SEND_HEAD_WEAR) { + content = context.getResources().getString(R.string.donate_decoration_info_text, + DecorationHelper.getSimpleNick(nick), + decoration.getName(), String.valueOf(decoration.getDays())); + } else if (type == DecorationSaleType.SEND_CAR) { + content = context.getResources().getString(R.string.donate_decoration_info_text, + DecorationHelper.getSimpleNick(nick), + decoration.getName(), String.valueOf(decoration.getDays())); + } + int titleRes; + if (type == DecorationSaleType.SEND_CAR || type == DecorationSaleType.SEND_HEAD_WEAR) { + titleRes = R.string.donate_tips_text; + } else { + titleRes = R.string.buy_tips_text; + + } + tvBuyTitle.setText(titleRes); + tvBuyContent.setText(content); + //显示价格 + //赠送的话只显示price + //购买的话需要区分price和renewPrice + int price; + int radishPrice; + if (type == DecorationSaleType.SEND_CAR || type == DecorationSaleType.SEND_HEAD_WEAR) { + price = decoration.getPrice(); + radishPrice = decoration.getRadishPrice(); + } else { + price = decoration.getRealPrice(); + radishPrice = decoration.getRealRadishPrice(); + } + if (decoration.isOnlyGoldSale()) { + rgBuyUnit.setVisibility(View.GONE); + tvSingleUnit.setVisibility(View.VISIBLE); + tvSingleUnit.setText(context.getResources().getString(R.string.how_much_gold, + price)); + } else if (decoration.isOnlyRadishSale()) { + rgBuyUnit.setVisibility(View.GONE); + tvSingleUnit.setVisibility(View.VISIBLE); + tvSingleUnit.setText(context.getResources().getString(R.string.how_much_radish, + radishPrice)); + } else if (decoration.isGoldAndRadishSale()) { + rgBuyUnit.setVisibility(View.VISIBLE); + tvSingleUnit.setVisibility(View.GONE); + rbGold.setText(context.getResources().getString(R.string.how_much_gold, + price)); + rbRadish.setText(context.getResources().getString(R.string.how_much_radish, + radishPrice)); + } else { + return null; + } + return customViewGoldRadish; + } + + /** + * 识别支付币类型 + */ + private int calcCurrencyType() { + int currencyType = CurrencyType.GOLD; + BaseDecoration decoration = options.getDecoration(); + if (decoration == null) { + return currencyType; + } + if (decoration.isGoldAndRadishSale()) { + if (rbRadish != null && rbRadish.isChecked()) { + currencyType = CurrencyType.RADISH; + } + } else if (decoration.isOnlyRadishSale()) { + currencyType = CurrencyType.RADISH; + } + return currencyType; + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + private void handleDialogOkClick() { + switch (options.getType()) { + case DecorationSaleType.BUY_HEAD_WEAR: + dialogManager.showProgressDialog(context, "", true); + DialogUiHelper.CHARGE_FROM = "买头饰"; + HeadwearModel.get().buyHeadWearV2(options.getDecoration().getDecorationId(), calcCurrencyType()) + .compose(RxHelper.bindContext(context)) + .map(s -> { + if (options.getDecoration().isRenew()) { + return "续费成功"; + } + return "购买成功"; + }) + .subscribe(new DecorationConsumer()); + + break; + + case DecorationSaleType.BUY_CAR: + DialogUiHelper.CHARGE_FROM = "买座驾"; + dialogManager.showProgressDialog(context, "", true); + CarModel.get().buyThisCarV2(options.getDecoration().getDecorationId(), calcCurrencyType()) + .compose(RxHelper.bindContext(context)) + .map(s -> { + if (options.getDecoration().isRenew()) { + return "续费成功"; + } + return "购买成功"; + }) + .subscribe(new DecorationConsumer()); + break; + + case DecorationSaleType.SEND_CAR: + DialogUiHelper.CHARGE_FROM = "买座驾"; + CarModel.get().sendCarV2( + String.valueOf(options.getTargetUid()), + String.valueOf(options.getDecoration().getDecorationId()), + calcCurrencyType()) + .compose(RxHelper.bindContext(context)) + .map(s -> "赠送成功") + .subscribe(new DecorationConsumer()); + break; + + case DecorationSaleType.SEND_HEAD_WEAR: + DialogUiHelper.CHARGE_FROM = "买头饰"; + HeadwearModel.get().sendHeadWearV2( + calcCurrencyType(), + String.valueOf(options.getDecoration().getDecorationId()), + String.valueOf(options.getTargetUid())) + .compose(RxHelper.bindContext(context)) + .map(s -> "赠送成功") + .subscribe(new DecorationConsumer()); + break; + } + } + + public class DecorationConsumer implements BiConsumer { + + @Override + public void accept(String string, Throwable throwable) throws Exception { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialogManager.isDialogShowing()) { + dialogManager.dismissDialog(); + } + if (throwable == null) { + if (!options.isCustomSuccessCallback()) { + dialogManager.showBuyCarSucDialog(string); + } + if (listener != null) { + if (options.getType() == DecorationSaleType.BUY_HEAD_WEAR) { + listener.onBuyHeadwearSuccess(); + } else if (options.getType() == DecorationSaleType.BUY_CAR) { + listener.onBuyCarSuccess(); + } else if (options.getType() == DecorationSaleType.SEND_CAR) { + listener.onSendCarSuccess(); + } else if (options.getType() == DecorationSaleType.SEND_HEAD_WEAR) { + listener.onSendHeadwearSuccess(); + } + } + } else { + if (throwable instanceof BalanceNotEnoughExeption) { + DialogUiHelper.showNeedCharge(context, dialogManager); + } else if (throwable instanceof RadishNotEnoughException) { + DialogUiHelper.showRadishNotEnoughDialog(context, dialogManager); + } else { +// Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(throwable.getMessage()); + } + } + } + } + + public void setOptions(Options options) { + this.options = options; + } + + @Data + public static class Options { + private BaseDecoration decoration; + /** + * 弹框类型 + * {@link DecorationSaleType} + */ + private int type; + + private String nick; + + private long targetUid; + /** + * ture的话,完全自定义购买成功回调 + */ + private boolean customSuccessCallback; + + public String getNick() { + if (nick == null) { + nick = ""; + } + return nick; + } + } + + public static class Builder { + + private Options options; + + public Builder() { + options = new Options(); + } + + public Builder setDecoration(BaseDecoration decoration) { + options.setDecoration(decoration); + return this; + } + + public Builder setType(int type) { + options.setType(type); + return this; + } + + public Builder setNick(String nick) { + options.setNick(nick); + return this; + } + + public Builder setTargetUid(long targetUid) { + options.setTargetUid(targetUid); + return this; + } + + public Builder setCustomSuccessCallback(boolean customSuccessCallback) { + options.setCustomSuccessCallback(customSuccessCallback); + return this; + } + + public Options create() { + return options; + } + + } + + private OnOpDecorationListener listener; + + public void setOnOpDecorationListener(OnOpDecorationListener listener) { + this.listener = listener; + } + + public static abstract class OnOpDecorationListener { + + public void onBuyHeadwearSuccess() { + + } + + public void onSendHeadwearSuccess() { + + } + + public void onBuyCarSuccess() { + + } + + public void onSendCarSuccess() { + + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationHelper.java b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationHelper.java new file mode 100644 index 000000000..b2dc471b2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationHelper.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.decoration.helper; + +import android.text.TextUtils; + +/** + * create by lvzebiao @2019/3/21 + */ +public class DecorationHelper { + + /** + * 超过5位时省略显示 + * + * @param nick + * @return + */ + public static String getSimpleNick(String nick) { + if (TextUtils.isEmpty(nick)) { + return ""; + } + if (nick.length() <= 5) { + return nick; + } + try { + return nick.substring(0, 4) + "…"; + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationSaleType.java b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationSaleType.java new file mode 100644 index 000000000..ad5aa4895 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/helper/DecorationSaleType.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.decoration.helper; + +/** + * 购买 赠送 头饰 座驾的区分 + * create by lvzebiao @2019/3/22 + */ +public interface DecorationSaleType { + + int BUY_HEAD_WEAR = 1;//购买头饰 + int BUY_CAR = 2; //购买座驾 + int SEND_HEAD_WEAR = 3; //赠送头饰 + int SEND_CAR = 4; //赠送座驾 + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/CarShopFragment.java b/app/src/main/java/com/yizhuan/erban/decoration/view/CarShopFragment.java new file mode 100644 index 000000000..99b04eca0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/CarShopFragment.java @@ -0,0 +1,116 @@ +package com.yizhuan.erban.decoration.view; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; + +import com.netease.nim.uikit.common.ui.recyclerview.decoration.SpacingDecoration; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.databinding.FragmentRexylerviewBindBinding; +import com.yizhuan.erban.decoration.adapter.CarShopAdapter; +import com.yizhuan.erban.decoration.viewmodel.CarShopVm; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; + +import java.util.List; + +/** + * Created by huangmeng1 on 2018/5/7. + */ +@ActLayoutRes(R.layout.fragment_rexylerview_bind) +public class CarShopFragment extends BaseBindingFragment { + private CarShopVm carShopVm; + private CarShopAdapter carShopAdapter; + + private DecorationStoreActivity activity; + + public CarShopAdapter getCarShopAdapter() { + return carShopAdapter; + } + + public static CarShopFragment newInstance(int position, String uid) { + CarShopFragment carShopFragment = new CarShopFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(Constants.KEY_POSITION, position); + bundle.putString(BundleKeys.KEY_EXTRA_1, uid); + carShopFragment.setArguments(bundle); + return carShopFragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + this.activity = (DecorationStoreActivity) activity; + } + + @Override + public void initiate() { + carShopVm = new CarShopVm(); + if (getArguments() != null) { + carShopVm.setUid(getArguments().getString(BundleKeys.KEY_EXTRA_1)); + } + mBinding.setViewmodel(carShopVm); + + carShopAdapter = new CarShopAdapter(R.layout.item_car_shop, BR.carInfo); + carShopAdapter.setOnItemChildClickListener((adapter, view, position) -> { + if (activity != null) { + activity.showCarDetail((CarInfo) adapter.getData().get(position)); + } + }); + carShopAdapter.setOnItemClickListener((adapter, view, position) -> { + carShopAdapter.setSelectPosition(position); + carShopAdapter.notifyDataSetChanged(); + if (activity != null) { + activity.showCarPrice((CarInfo) adapter.getData().get(position)); + } + }); + carShopAdapter.setOnLoadMoreListener(() -> loadData(true, false)); + mBinding.swipeRefresh.setOnRefreshListener(() -> loadData(false, false)); + + mBinding.recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2)); + int heightSpace = Utils.dip2px(mContext, 10); + mBinding.recyclerView.setAdapter(carShopAdapter); + mBinding.recyclerView.addItemDecoration(new SpacingDecoration(heightSpace, heightSpace, true)); + + loadData(false, getArguments().getInt(Constants.KEY_POSITION) == 1); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser && activity != null) { + activity.setCar(true); + List list = carShopAdapter.getData(); + int selectPosition = carShopAdapter.getSelectPosition(); + if (!ListUtils.isListEmpty(list) && selectPosition < list.size()) { + activity.showCarPrice(list.get(selectPosition)); + } + } + } + + private boolean isLoading = false; + + private void loadData(boolean isLode, boolean isFirst) { + if (isLoading) { + return; + } + isLoading = true; + + carShopVm.loadData(isLode).compose(bindToLifecycle()) + .doAfterTerminate(() -> setUserVisibleHint(isFirst)) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List carInfos, String error) { + super.accept(carInfos, error); + isLoading = false; + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/DecorationStoreActivity.java b/app/src/main/java/com/yizhuan/erban/decoration/view/DecorationStoreActivity.java new file mode 100644 index 000000000..d17a7ebb8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/DecorationStoreActivity.java @@ -0,0 +1,480 @@ +package com.yizhuan.erban.decoration.view; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Paint; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.view.View; + +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityDecorationStoreBinding; +import com.yizhuan.erban.decoration.helper.DecorationDialogHelper; +import com.yizhuan.erban.decoration.helper.DecorationSaleType; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.ui.user.decorationsend.DecorationSendActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.decoration.bean.BaseDecoration; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.functions.Consumer; + +@ActLayoutRes(R.layout.activity_decoration_store) +public class DecorationStoreActivity extends BaseBindingActivity implements CarMagicIndicator.OnItemSelectListener { + public final static int TAB_HEAD_WEAR = 0; + public final static int TAB_CAR = 1; + + private SVGAParser mSVGAParser; + private long userId; + private boolean isCar; + private CarInfo buyCarInfo; + private HeadWearInfo wearInfo; + private UserInfo cacheLoginUserInfo; + private HeadWearFragment wearFragment; + private CarShopFragment shopFragment; + private boolean isBuy; + + private final static String IS_CHECK_MY_DECORATION = "IS_CHECK_MY_DECORATION"; + + public static void start(Context context, long userId) { + Intent intent = new Intent(context, DecorationStoreActivity.class); + intent.putExtra("userId", userId); + context.startActivity(intent); + } + + public static void start(Context context, long userId, int position) { + Intent intent = new Intent(context, DecorationStoreActivity.class); + intent.putExtra("userId", userId); + intent.putExtra(Constants.KEY_POSITION, position); + context.startActivity(intent); + } + + public void setCar(boolean car) { + isCar = car; + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @SuppressLint("CheckResult") + @Override + protected void init() { + + userId = getIntent().getLongExtra("userId", 0); + int currentItem = getIntent().getIntExtra(Constants.KEY_POSITION, TAB_HEAD_WEAR); + + mBinding.setClick(this); + mSVGAParser = new SVGAParser(this); + + wearFragment = HeadWearFragment.newInstance(currentItem, userId + ""); + shopFragment = CarShopFragment.newInstance(currentItem, userId + ""); + + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(0, "头饰")); + tabInfoList.add(new TabInfo(1, "座驾")); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mBinding.tabLayout.setNavigator(commonNavigator); + + ViewPagerHelper.bind(mBinding.tabLayout, mBinding.viewpager); + + mBinding.viewpager.setOffscreenPageLimit(2); + mBinding.viewpager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public int getCount() { + return 2; + } + + @Override + public Fragment getItem(int position) { + if (position == 0) { + return wearFragment; + } else if (position == 1) { + return shopFragment; + } + return wearFragment; + } + }); + + mBinding.viewpager.setCurrentItem(currentItem); + + UserModel.get().getUserInfo(userId).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + cacheLoginUserInfo = userInfo; + if (cacheLoginUserInfo != null) { + mBinding.setIsSelf(cacheLoginUserInfo.getUid() == AuthModel.get().getCurrentUid()); + ImageLoadUtils.loadImage(DecorationStoreActivity.this, cacheLoginUserInfo.getAvatar(), mBinding.ivAvatar); + if (cacheLoginUserInfo.getUserHeadwear() != null && !TextUtils.isEmpty(cacheLoginUserInfo.getUserHeadwear().getPic())) { + // 头饰 + NobleUtil.loadHeadWear(cacheLoginUserInfo.getUserHeadwear().getPic(), mBinding.ivHeadWear); + } else if (cacheLoginUserInfo.getNobleInfo() != null && !TextUtils.isEmpty(cacheLoginUserInfo.getNobleInfo().getHeadWear())) { + // 头饰 + NobleUtil.loadResource(cacheLoginUserInfo.getNobleInfo().getHeadWear(), mBinding.ivHeadWear); + } + } + } + }); + + + Boolean isCheckMyDecoration = (Boolean) SharedPreferenceUtils.get(DecorationStoreActivity.IS_CHECK_MY_DECORATION, true); + if (isCheckMyDecoration != null && isCheckMyDecoration) { + mBinding.tvRedTip.setVisibility(View.INVISIBLE); + } else { + mBinding.tvRedTip.setVisibility(View.VISIBLE); + } + + mBinding.rlCarDetail.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + case R.id.tv_edit: + startActivity(new Intent(this, MyDecorationActivity.class)); + mBinding.tvRedTip.setVisibility(View.INVISIBLE); + SharedPreferenceUtils.put(DecorationStoreActivity.IS_CHECK_MY_DECORATION, true); + break; + case R.id.tv_buy: + if (isCar && buyCarInfo != null) { + showSureDialog(DecorationSaleType.BUY_CAR); + } else if (!isCar && wearInfo != null) { + showSureDialog(DecorationSaleType.BUY_HEAD_WEAR); + } + break; + case R.id.tv_go_send: + if (isCar && buyCarInfo != null) { + DecorationSendActivity.start(this, buyCarInfo); + } else if (!isCar && wearInfo != null) { + DecorationSendActivity.start(this, wearInfo); + } + break; + case R.id.tv_send: + if (isCar && buyCarInfo != null) { + showSureDialog(DecorationSaleType.SEND_CAR); + } else if (!isCar && wearInfo != null) { + showSureDialog(DecorationSaleType.SEND_HEAD_WEAR); + } + + break; + } + } + + + private void showSureDialog(int type) { + if (cacheLoginUserInfo == null) return; + BaseDecoration decoration; + if (type == DecorationSaleType.BUY_CAR || type == DecorationSaleType.SEND_CAR) { + decoration = buyCarInfo; + } else { + decoration = wearInfo; + } + if (decoration == null) { + return; + } + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setTargetUid(cacheLoginUserInfo.getUid()) + .setNick(cacheLoginUserInfo.getNick()) + .setType(type) + .setDecoration(decoration) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(context, getDialogManager(), options); + helper.showBuyOrDonateDialog(); + helper.setOnOpDecorationListener(new DecorationDialogHelper.OnOpDecorationListener() { + @Override + public void onBuyCarSuccess() { + // 更新商店这辆车的数据 + if (shopFragment != null && shopFragment.getCarShopAdapter() != null) + shopFragment.getCarShopAdapter().setCarInfoHasBeenBought(buyCarInfo); + + setPrice(buyCarInfo, true); + isBuy = false; + setBuyButton(isBuy); + setGoSendButton(isBuy); + + mBinding.tvRedTip.setVisibility(View.VISIBLE); + SharedPreferenceUtils.put(DecorationStoreActivity.IS_CHECK_MY_DECORATION, false); + } + + @Override + public void onBuyHeadwearSuccess() { + // 更新商店头饰的数据 + if (wearFragment != null && wearFragment.getShopAdapter() != null) { + wearFragment.getShopAdapter().setCarInfoHasBeenBought(wearInfo); + } + setPrice(wearInfo, true); + isBuy = false; + setBuyButton(isBuy); + setGoSendButton(isBuy); + + mBinding.tvRedTip.setVisibility(View.VISIBLE); + SharedPreferenceUtils.put(DecorationStoreActivity.IS_CHECK_MY_DECORATION, false); + + //更新用户信息 + UserModel.get().updateCurrentUserInfo().subscribe(); + } + }); + + } + + @Override + public void onBackPressed() { + if (mBinding.rlCarDetail.getVisibility() == View.VISIBLE) { + dismissCarDetail(); + } else { + super.onBackPressed(); + } + } + + public void showCarPrice(CarInfo carInfo) { + if (carInfo == null || carInfo.getCarId() <= 0) return; + //座驾标签 + if (carInfo.getLabelType() == CarInfo.TAG_TYPE_NORMAL) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.GONE); + + } else if (CarInfo.TAG_TYPE_NEW == carInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.GONE); + + } else if (CarInfo.TAG_TYPE_DISCOUNT == carInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.VISIBLE); + setOriginalPrice(carInfo); + + } else if (CarInfo.TAG_TYPE_LIMIT == carInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.VISIBLE); + mBinding.tvLimitDesc.setText(carInfo.getLimitDesc()); + if (TextUtils.isEmpty(carInfo.getRedirectLink())) { + mBinding.tvGoWeb.setVisibility(View.GONE); + } else { + mBinding.tvGoWeb.setVisibility(View.VISIBLE); + mBinding.tvGoWeb.setOnClickListener(v -> { + CommonWebViewActivity.start(DecorationStoreActivity.this, carInfo.getRedirectLink()); + }); + } + return; + + } else if (CarInfo.TAG_TYPE_EXCLUSIVE == carInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.VISIBLE); + mBinding.tvLimitDesc.setText(carInfo.getLimitDesc()); + if (TextUtils.isEmpty(carInfo.getRedirectLink())) { + mBinding.tvGoWeb.setVisibility(View.GONE); + } else { + mBinding.tvGoWeb.setVisibility(View.VISIBLE); + mBinding.tvGoWeb.setOnClickListener(v -> CommonWebViewActivity.start(DecorationStoreActivity.this, carInfo.getRedirectLink())); + } + return; + + } + + buyCarInfo = carInfo; + boolean buyState = carInfo.getRemainingDay() > 0 && carInfo.getStatus() == CarInfo.STATUS_USER_CAN_USE; + setPrice(carInfo, buyState); + isBuy = !buyState; + + setBuyButton(isBuy); + setGoSendButton(isBuy); + } + + private void setBuyButton(boolean isBuy) { + if (isBuy) { + mBinding.tvBuy.setBackgroundResource(R.drawable.bg_button_buy); + mBinding.tvBuy.setText("购买"); + + } else { + mBinding.tvBuy.setBackgroundResource(R.drawable.bg_button_remain); + mBinding.tvBuy.setText("续费"); + + } + } + + private void setGoSendButton(boolean isBuy) { + mBinding.tvGoSend.setBackgroundResource(R.drawable.bg_left_button_buy); + mBinding.tvGoSend.setTextColor(ContextCompat.getColor(this, R.color.color_333333)); +// if (isBuy) { +// mBinding.tvGoSend.setBackgroundResource(R.drawable.bg_left_button_buy); +// mBinding.tvGoSend.setTextColor(ContextCompat.getColor(this, R.color.color_333333)); +// +// } else { +// mBinding.tvGoSend.setBackgroundResource(R.drawable.bg_left_button_remain); +// mBinding.tvGoSend.setTextColor(ContextCompat.getColor(this, R.color.color_FC6E6D)); +// } + } + + private void setPrice(BaseDecoration bean, boolean isRenewPrice) { + + StringBuilder price = new StringBuilder(); + + if (bean.isGoldSale()) { + price.append(isRenewPrice ? String.valueOf(bean.getRenewPrice()) : String.valueOf(bean.getPrice())); + price.append("金币"); + } + + if (bean.isGoldAndRadishSale()) + price.append("/"); + + if (bean.isRadishSale()) { + price.append(isRenewPrice ? String.valueOf(bean.getRadishRenewPrice()) : String.valueOf(bean.getRadishPrice())); + price.append("萝卜"); + } + + mBinding.tvPrice.setText(com.yizhuan.xchat_android_core.utils.TextUtils.textTwoColors(price.toString(), "(" + bean.getDays() + "天)", + ContextCompat.getColor(this, R.color.appColor), + ContextCompat.getColor(this, R.color.color_999999))); + } + + private void setOriginalPrice(BaseDecoration bean) { + StringBuilder price = new StringBuilder(); + + if (bean.isGoldSale()) { + price.append(bean.getOriginalPrice()); + price.append("金币"); + } + + if (bean.isGoldAndRadishSale()) + price.append("/"); + + if (bean.isRadishSale()) { + price.append(bean.getRadishOriginalPrice()); + price.append("萝卜"); + } + mBinding.tvOriginalPrice.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); //中划线 + mBinding.tvOriginalPrice.setText(price + "(" + bean.getDays() + "天)"); + } + + public void showHeadWearPrice(HeadWearInfo headWearInfo) { + if (headWearInfo == null || headWearInfo.getHeadwearId() <= 0) return; + NobleUtil.loadHeadWear(headWearInfo.getPic(), mBinding.ivHeadWear); + //头饰标签 + if (HeadWearInfo.LABEL_TYPE_NORMAL == headWearInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.GONE); + } else if (HeadWearInfo.LABEL_TYPE_NEW == headWearInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.GONE); + } else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == headWearInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.GONE); + mBinding.tvOriginalPrice.setVisibility(View.VISIBLE); + setOriginalPrice(headWearInfo); + } else if (HeadWearInfo.LABEL_TYPE_LIMIT == headWearInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.VISIBLE); + mBinding.tvLimitDesc.setText(headWearInfo.getLimitDesc()); + if (TextUtils.isEmpty(headWearInfo.getRedirectLink())) { + mBinding.tvGoWeb.setVisibility(View.GONE); + } else { + mBinding.tvGoWeb.setVisibility(View.VISIBLE); + mBinding.tvGoWeb.setOnClickListener(v -> { + CommonWebViewActivity.start(DecorationStoreActivity.this, headWearInfo.getRedirectLink()); + }); + } + return; + } else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == headWearInfo.getLabelType()) { + mBinding.llLimitContainer.setVisibility(View.VISIBLE); + mBinding.tvLimitDesc.setText(headWearInfo.getLimitDesc()); + if (TextUtils.isEmpty(headWearInfo.getRedirectLink())) { + mBinding.tvGoWeb.setVisibility(View.GONE); + } else { + mBinding.tvGoWeb.setVisibility(View.VISIBLE); + mBinding.tvGoWeb.setOnClickListener(v -> CommonWebViewActivity.start(DecorationStoreActivity.this, headWearInfo.getRedirectLink())); + } + return; + } + + wearInfo = headWearInfo; + boolean buyState = headWearInfo.getStatus() == HeadWearInfo.STATUS_IN_USED; + setPrice(headWearInfo, buyState); + isBuy = !buyState; + + setBuyButton(isBuy); + setGoSendButton(isBuy); + } + + public void showCarDetail(CarInfo carInfo) { + if (carInfo == null || carInfo.getCarId() <= 0) return; + + mBinding.rlCarDetail.setVisibility(View.VISIBLE); + + showSvgaAnimation(carInfo.getEffect()); + mBinding.tvBuyCancel.setOnClickListener(v -> dismissCarDetail()); + + } + + private void showSvgaAnimation(String effect) { + //effect = TextUtils.isEmpty(effect) && BuildConfig.DEBUG ? "https://img.erbanyy.com/svga/Noble_OpenEffect_7_1.svga" : effect; + try { + URL url = new URL(effect); + mSVGAParser.parse(url, new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + if (mBinding.rlCarDetail.getVisibility() == View.GONE) return; + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + mBinding.svgaCarPlay.setLoops(-1); + mBinding.svgaCarPlay.setImageDrawable(drawable); + mBinding.svgaCarPlay.startAnimation(); + mBinding.svgaCarPlay.setClearsAfterStop(true); + } + + @Override + public void onError() { +// Toast.makeText(DecorationStoreActivity.this, "网络异常", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("网络异常"); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void dismissCarDetail() { + if (mBinding.rlCarDetail != null) { + mBinding.svgaCarPlay.stopAnimation(true); + mBinding.svgaCarPlay.setImageDrawable(null); + mBinding.rlCarDetail.setVisibility(View.GONE); + } + } + + @Override + public void onItemSelect(int position) { + mBinding.viewpager.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/HeadWearFragment.java b/app/src/main/java/com/yizhuan/erban/decoration/view/HeadWearFragment.java new file mode 100644 index 000000000..4f50236f3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/HeadWearFragment.java @@ -0,0 +1,107 @@ +package com.yizhuan.erban.decoration.view; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; + +import com.netease.nim.uikit.common.ui.recyclerview.decoration.SpacingDecoration; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.FragmentRexylerviewBindBinding; +import com.yizhuan.erban.decoration.adapter.HeadWearShopAdapter; +import com.yizhuan.erban.decoration.viewmodel.HeadWearVm; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +/** + * Created by huangmeng1 on 2018/5/7. + */ +@ActLayoutRes(R.layout.fragment_rexylerview_bind) +public class HeadWearFragment extends BaseBindingFragment { + private HeadWearVm headWearVm; + private HeadWearShopAdapter shopAdapter; + private DecorationStoreActivity activity; + + public HeadWearShopAdapter getShopAdapter() { + return shopAdapter; + } + + public static HeadWearFragment newInstance(int position, String uid) { + HeadWearFragment headWearFragment = new HeadWearFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(Constants.KEY_POSITION, position); + bundle.putString("uid", uid); + headWearFragment.setArguments(bundle); + return headWearFragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + this.activity = (DecorationStoreActivity) activity; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser && activity != null) { + activity.setCar(false); + if (!ListUtils.isListEmpty(shopAdapter.getData())) { + activity.showHeadWearPrice(shopAdapter.getData().get(shopAdapter.getSelectPosition())); + } + } + } + + @Override + public void initiate() { + + headWearVm = new HeadWearVm(); + headWearVm.setUid(getArguments().getString("uid")); + mBinding.setViewmodel(headWearVm); + shopAdapter = new HeadWearShopAdapter(R.layout.item_head_wear, BR.headWearInfo); + + shopAdapter.setOnItemClickListener((adapter, view, position) -> { + shopAdapter.setSelectPosition(position); + if (activity != null) { + activity.showHeadWearPrice((HeadWearInfo) adapter.getData().get(position)); + } + }); + + shopAdapter.setOnLoadMoreListener(() -> loadData(true, false)); + mBinding.swipeRefresh.setOnRefreshListener(() -> loadData(false, false)); + + mBinding.recyclerView.setAdapter(shopAdapter); + mBinding.recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3)); + int heightSpace = Utils.dip2px(mContext, 10); + mBinding.recyclerView.addItemDecoration(new SpacingDecoration(heightSpace, heightSpace, true)); + + loadData(false, getArguments().getInt(Constants.KEY_POSITION) == 0); + } + + private boolean isLoading = false; + + private void loadData(boolean isLode, boolean isFirst) { + if (isLoading) { + return; + } + isLoading = true; + headWearVm.loadData(isLode).compose(bindToLifecycle()) + .doAfterSuccess(headWearInfos -> { + setUserVisibleHint(isFirst); + }) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List headWearInfos, String error) { + super.accept(headWearInfos, error); + isLoading = false; + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/ICarView.java b/app/src/main/java/com/yizhuan/erban/decoration/view/ICarView.java new file mode 100644 index 000000000..c78219957 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/ICarView.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.decoration.view; + +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * Created by yudi + * on 2018/3/1. + */ + +public interface ICarView extends IMvpBaseView { + + /** + * 点击购买按钮 + * + * @param carInfo - + */ + void showDetail(CarInfo carInfo); + + /** + * 点击购买按钮 + * + * @param carInfo - + */ + default void showCarPrice(CarInfo carInfo) { + // + } + /** + * 更新车库需不需要更新的字段 + * + * @param needUpdate - + */ + void setCarGarageNeedUpdate(boolean needUpdate); + + /** + * 车库需不需要更新 + */ + boolean getCarGarageNeedUpdate(); +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/MyCarFragment.java b/app/src/main/java/com/yizhuan/erban/decoration/view/MyCarFragment.java new file mode 100644 index 000000000..01e39b431 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/MyCarFragment.java @@ -0,0 +1,179 @@ +package com.yizhuan.erban.decoration.view; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.databinding.FrgMyDecorationCommonBinding; +import com.yizhuan.erban.decoration.adapter.MyCarAdapter; +import com.yizhuan.erban.decoration.viewmodel.MyCarVm; +import com.yizhuan.erban.ui.widget.LoadingDialog; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +/** + * Created by yudi + * on 2018/3/2. + */ + +@ActLayoutRes(R.layout.frg_my_decoration_common) +public class MyCarFragment extends BaseBindingFragment { + + private ICarView mCarView; + private MyCarAdapter mCarGarageAdapter; + private boolean first = true; + + private MyCarVm myCarVm; + + public static MyCarFragment instance(ICarView carView) { + MyCarFragment fragment = new MyCarFragment(); + fragment.mCarView = carView; + return fragment; + } + + @Override + public void onFindViews() { + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (first && getUserVisibleHint()) { + first = false; + } + } + + @Override + public void onSetListener() { + } + + @Override + public void initiate() { + myCarVm = new MyCarVm(); + mBinding.setViewmodel(myCarVm); + + mCarGarageAdapter = new MyCarAdapter(R.layout.item_car_garage_normal, BR.carInfo); + mCarGarageAdapter.setOnItemChildClickListener((adapter, view, position) -> { + + switch (view.getId()) { + case R.id.tv_buy: + mCarView.showDetail(mCarGarageAdapter.getItem(position)); + break; + + case R.id.tv_used: + startDriving(mCarGarageAdapter.getItem(position)); + break; + + } + }); + + mBinding.swipeRefresh.setOnRefreshListener(() -> getData()); + + mBinding.recyclerView.setAdapter(mCarGarageAdapter); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + getData(); + } + + public MyCarAdapter getAdapter() { + return mCarGarageAdapter; + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser && mCarView != null && mCarView.getCarGarageNeedUpdate()) { + getData(); + } + } + + @SuppressLint("CheckResult") + private void getData() { + + if (myCarVm == null) + return; + + myCarVm.loadData(false).compose(bindToLifecycle()) + .doAfterTerminate(() -> { + if (ListUtils.isListEmpty(mCarGarageAdapter.getData())) { + showNoData(R.drawable.icon_common_failure, "亲爱的用户,你还没有座驾哦!"); + } + + List list = mCarGarageAdapter.getData(); + + for (CarInfo item : list) { + if (item.getCarId() == 0) { + list.remove(item); + break; + } + } + + mCarGarageAdapter.notifyDataSetChanged(); + }) + .subscribe(); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_middle_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @SuppressLint("CheckResult") + private void startDriving(CarInfo carInfo) { + final int id = carInfo.isUsing() ? 0 : carInfo.getCarId(); + LoadingDialog loadingDialog = new LoadingDialog(mContext); + loadingDialog.show(); + + CarModel.get().driveThisCar(id) + .subscribe((voidServiceResult, throwable) -> { + loadingDialog.dismiss(); + if (voidServiceResult != null && voidServiceResult.isSuccess()) { + //更换座驾状态,需要更新缓存 + UserModel.get().onlyUpdateLoginUserInfoCache(); + List list = mCarGarageAdapter.getData(); + for (CarInfo item : list) { + if (id == item.getCarId()) { + item.setUsing(1); + } else { + item.setUsing(0); + } + } + mCarGarageAdapter.notifyDataSetChanged(); + + } else if (voidServiceResult != null && !voidServiceResult.isSuccess()) { +// Toast.makeText(mContext, "驾驶失败: 网络异常!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } else if (throwable != null) { +// Toast.makeText(mContext, "驾驶失败: 网络异常!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } else { +// Toast.makeText(mContext, "驾驶失败: 网络异常!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/MyDecorationActivity.java b/app/src/main/java/com/yizhuan/erban/decoration/view/MyDecorationActivity.java new file mode 100644 index 000000000..443885643 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/MyDecorationActivity.java @@ -0,0 +1,219 @@ +package com.yizhuan.erban.decoration.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewStub; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityMyDecorationBinding; +import com.yizhuan.erban.decoration.helper.DecorationDialogHelper; +import com.yizhuan.erban.decoration.helper.DecorationSaleType; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by yudi + * on 2018/3/1. + */ +@ActLayoutRes(R.layout.activity_my_decoration) +public class MyDecorationActivity extends BaseBindingActivity + implements ICarView, View.OnClickListener, CarMagicIndicator.OnItemSelectListener { + + private ViewPager viewPager; + private ViewStub vbCarDetail; + private RelativeLayout rlCarDetail; + private SVGAParser mSVGAParser; + private SVGAImageView svgaCarEffect; + private TextView tvBuy; + private int mPosition; + private boolean carGarageNeedUpdate = true; + private MyHeadWearFragment myHeadWearFragment; + private MyCarFragment mMyCarFragment; + private MagicIndicator mMagicIndicator; + + public static void start(Context context, int position) { + Intent intent = new Intent(context, MyDecorationActivity.class); + intent.putExtra(Constants.KEY_POSITION, position); + context.startActivity(intent); + } + + @Override + protected void init() { + mSVGAParser = new SVGAParser(this); + mPosition = getIntent().getIntExtra(Constants.KEY_POSITION, 0); + initViews(); + } + + @Override + protected boolean needSteepStateBar() { + return false; + } + + private void initViews() { + viewPager = mBinding.viewpager; + vbCarDetail = mBinding.vsCarDetail.getViewStub(); + mMagicIndicator = mBinding.viewIndicator; + + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(1, "头饰")); + tabInfoList.add(new TabInfo(2, "座驾")); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mMagicIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mMagicIndicator, viewPager); + + mBinding.ivBack.setOnClickListener(this); + myHeadWearFragment = new MyHeadWearFragment(); + mMyCarFragment = MyCarFragment.instance(this); + viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public int getCount() { + return 2; + } + + @Override + public Fragment getItem(int position) { + return position == 0 ? myHeadWearFragment : mMyCarFragment; + } + }); + viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + super.onPageSelected(position); + if (position == 1) { + mMagicIndicator.findViewById(R.id.car_badge_garage).setVisibility(View.GONE); + } + } + }); + viewPager.setCurrentItem(mPosition); + } + + @Override + public void onBackPressed() { + if (rlCarDetail != null && rlCarDetail.getVisibility() == View.VISIBLE) { + svgaCarEffect.clearAnimation(); + svgaCarEffect.setImageDrawable(null); + rlCarDetail.setVisibility(View.GONE); + } else { + if (rlCarDetail != null && svgaCarEffect != null) { + svgaCarEffect.clearAnimation(); + svgaCarEffect.setImageDrawable(null); + rlCarDetail.setVisibility(View.GONE); + } + super.onBackPressed(); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.iv_back) { + finish(); + dismissCarDetail(); + } else if (v.getId() == R.id.tv_buy_cancel) { + dismissCarDetail(); + } + } + + private void dismissCarDetail() { + if (rlCarDetail != null) { + svgaCarEffect.stopAnimation(true); + svgaCarEffect.setImageDrawable(null); + rlCarDetail.setVisibility(View.GONE); + } + } + + private void showCarDetail(CarInfo carInfo) { + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setType(DecorationSaleType.BUY_CAR) + .setDecoration(carInfo) + .setCustomSuccessCallback(true) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(context, getDialogManager(), options); + helper.showBuyOrDonateDialog(); + helper.setOnOpDecorationListener(new DecorationDialogHelper.OnOpDecorationListener() { + @Override + public void onBuyCarSuccess() { + super.onBuyCarSuccess(); + // 更新车库中这辆车的使用日期 + if (mMyCarFragment != null && mMyCarFragment.getAdapter() != null) + mMyCarFragment.getAdapter().setCarInfoHasBeenRenew(carInfo); + // 更新商店这辆车的数据 + if (myHeadWearFragment != null && myHeadWearFragment.getShopAdapter() != null) + // mCarShopFragment.getAdapter().setCarInfoHasBeenBought(carInfo); + // 购买成功才需要告知车库要更新,续费成功不需要 + if (tvBuy.getText().equals("购买")) + setCarGarageNeedUpdate(true); + // 提示是否需要立即驾驶 + //noinspection ResultOfMethodCallIgnored + getDialogManager().showOkCancelDialog("购买成功,是否立即驾驶?", + true, + () -> CarModel.get().driveThisCar(carInfo.getCarId()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe((voidServiceResult, throwable1) -> { + if (voidServiceResult != null && voidServiceResult.isSuccess()) { +// Toast.makeText(MyDecorationActivity.this, "驾驶成功", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶成功"); + // 实时更新座驾被选中 + mMyCarFragment.getAdapter().check(carInfo); + } else if (voidServiceResult != null && !voidServiceResult.isSuccess()) { +// Toast.makeText(MyDecorationActivity.this, "驾驶失败: 网络异常!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } else if (throwable1 != null) { +// Toast.makeText(MyDecorationActivity.this, "驾驶失败: 网络异常!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } else { +// Toast.makeText(MyDecorationActivity.this, "驾驶失败: 未知错误!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("驾驶失败: 网络异常!"); + } + })); + } + }); + + } + + public void showDetail(CarInfo carInfo) { + showCarDetail(carInfo); + } + + public void setCarGarageNeedUpdate(boolean needUpdate) { + this.carGarageNeedUpdate = needUpdate; + if (needUpdate) { + mMagicIndicator.findViewById(R.id.car_badge_garage).setVisibility(View.VISIBLE); + } + } + + public boolean getCarGarageNeedUpdate() { + boolean needUpdate = carGarageNeedUpdate; + carGarageNeedUpdate = false; + return needUpdate; + } + + @Override + public void onItemSelect(int position) { + viewPager.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/MyHeadWearFragment.java b/app/src/main/java/com/yizhuan/erban/decoration/view/MyHeadWearFragment.java new file mode 100644 index 000000000..f3e20f5d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/MyHeadWearFragment.java @@ -0,0 +1,167 @@ +package com.yizhuan.erban.decoration.view; + +import android.app.Activity; +import android.support.v7.widget.LinearLayoutManager; +import android.util.Log; +import android.view.View; + +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.databinding.FrgMyDecorationCommonBinding; +import com.yizhuan.erban.decoration.adapter.MyHeadWearAdapter; +import com.yizhuan.erban.decoration.helper.DecorationDialogHelper; +import com.yizhuan.erban.decoration.helper.DecorationSaleType; +import com.yizhuan.erban.decoration.viewmodel.DecorationVm; +import com.yizhuan.erban.decoration.viewmodel.HeadWearVm; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +/** + * Created by huangmeng1 on 2018/5/7. + */ +@ActLayoutRes(R.layout.frg_my_decoration_common) +public class MyHeadWearFragment extends BaseBindingFragment { + private HeadWearVm headWearVm; + private MyHeadWearAdapter shopAdapter; + private DecorationVm decorationVm; + + public MyHeadWearAdapter getShopAdapter() { + return shopAdapter; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + } + + @Override + public void initiate() { + headWearVm = new HeadWearVm(); + decorationVm = new DecorationVm(); + headWearVm.setMyHeadWear(true); + mBinding.setViewmodel(headWearVm); + + shopAdapter = new MyHeadWearAdapter(R.layout.item_my_head_wear, BR.headWearInfo); + shopAdapter.setOnItemChildClickListener((adapter, view, position) -> { + + switch (view.getId()) { + case R.id.tv_buy: + showSureDialog(position); + break; + + case R.id.tv_used: + setUsedStatus(position); + break; + + } + }); + + mBinding.swipeRefresh.setOnRefreshListener(() -> loadData()); + + mBinding.recyclerView.setAdapter(shopAdapter); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); +// int heightSpace = Utils.dip2px(mContext, 10); +// mBinding.recyclerView.addItemDecoration(new SpacingDecoration(heightSpace, heightSpace, true)); + + loadData(); + } + + private void loadData() { + headWearVm.loadData(false).compose(bindToLifecycle()) + .doAfterTerminate(() -> { + if (ListUtils.isListEmpty(shopAdapter.getData())) { + showNoData(R.drawable.icon_common_failure, "亲爱的用户,你还没有头饰哦!"); + } + + List list = shopAdapter.getData(); + + for (HeadWearInfo item : list) { + if (item.getHeadwearId() == 0) { + list.remove(item); + break; + } + } + + shopAdapter.notifyDataSetChanged(); + }) + .subscribe(); + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + private void setUsedStatus(int position) { + HeadWearInfo headWearInfo = shopAdapter.getData().get(position); + + Log.i("MyHeadWearFragment", "name:" + headWearInfo.getHeadwearName()); + + // id == 0标识不使用头饰 + final int id = headWearInfo.isUsed() ? 0 : headWearInfo.getHeadwearId(); + + headWearVm.userHeadWear(String.valueOf(id)) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .doOnError(throwable -> { + toast(throwable.getMessage()); + }) + .subscribe(s -> { + for (int i = 0; i < shopAdapter.getData().size(); i++) { + if (id == shopAdapter.getData().get(i).getHeadwearId()) { + shopAdapter.getData().get(i).setUsed(true); + } else { + shopAdapter.getData().get(i).setUsed(false); + } + } + shopAdapter.notifyDataSetChanged(); + //更新用户信息 + UserModel.get().updateCurrentUserInfo().subscribe(); + }); + + } + + private void showSureDialog(int position) { + HeadWearInfo wearInfo = shopAdapter.getItem(position); + if (wearInfo == null) { + return; + } + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setDecoration(wearInfo) + .setType(DecorationSaleType.BUY_HEAD_WEAR) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(mContext, getDialogManager(), options); + helper.showBuyOrDonateDialog(); + helper.setOnOpDecorationListener(new DecorationDialogHelper.OnOpDecorationListener() { + @Override + public void onBuyHeadwearSuccess() { + if (wearInfo.getExpireDays() > 0) { + wearInfo.setExpireDays(wearInfo.getExpireDays() + wearInfo.getDays()); + } else { + wearInfo.setExpireDays(wearInfo.getDays()); + } + wearInfo.setStatus(HeadWearInfo.STATUS_IN_USED); + shopAdapter.getData().set(position, wearInfo); + shopAdapter.notifyItemChanged(position); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/BadgeScaleTransitionPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/BadgeScaleTransitionPagerTitleView.java new file mode 100644 index 000000000..67b0a0c6f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/BadgeScaleTransitionPagerTitleView.java @@ -0,0 +1,97 @@ +package com.yizhuan.erban.decoration.view.widgets; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + + +/** + * 带颜色渐变和缩放的指示器标题 + * 博客: http://hackware.lucode.net + * + * @author hackware + * @date 2016/6/26 + */ +public class BadgeScaleTransitionPagerTitleView extends RelativeLayout implements IPagerTitleView { + private ScaleTransitionPagerTitleView mPagerTitleView; + private Context mContext; + private View mBadge; + + public BadgeScaleTransitionPagerTitleView(Context context) { + this(context, null); + } + + public BadgeScaleTransitionPagerTitleView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BadgeScaleTransitionPagerTitleView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + this.mContext = context; + mPagerTitleView = new ScaleTransitionPagerTitleView(context); + mBadge = new View(context); + mBadge.setBackground(context.getResources().getDrawable(R.drawable.bg_car_tab_badge)); + LayoutParams params = new LayoutParams(20, 20); + params.addRule(ALIGN_RIGHT, R.id.car_indicator); + params.leftMargin = 10; + params.addRule(CENTER_VERTICAL, 1); + mBadge.setLayoutParams(params); + mBadge.setId(R.id.car_badge); + mBadge.setVisibility(GONE); + addView(mBadge); + LayoutParams params1 = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + params1.addRule(CENTER_IN_PARENT); + mPagerTitleView.setLayoutParams(params1); + mPagerTitleView.setId(R.id.car_indicator); + addView(mPagerTitleView); + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + mPagerTitleView.onEnter(index, totalCount, enterPercent, leftToRight); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + mPagerTitleView.onLeave(index, totalCount, leavePercent, leftToRight); + } + + @Override + public void onSelected(int index, int totalCount) { + mPagerTitleView.onSelected(index, totalCount); + } + + @Override + public void onDeselected(int index, int totalCount) { + mPagerTitleView.onDeselected(index, totalCount); + } + + public void setMinScale(float minScale) { + mPagerTitleView.setMinScale(minScale); + } + + public void setNormalColor(int color) { + mPagerTitleView.setNormalColor(color); + } + + public void setSelectedColor(int color) { + mPagerTitleView.setSelectedColor(color); + } + + public void setTextSize(float size) { + mPagerTitleView.setTextSize(size); + } + + public void setText(String text) { + mPagerTitleView.setText(text); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/CarMagicIndicator.java b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/CarMagicIndicator.java new file mode 100644 index 000000000..3e1329401 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/CarMagicIndicator.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.decoration.view.widgets; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + *

公共多个滑动tab样式

+ * + * @author Administrator + * @date 2017/11/15 + */ +public class CarMagicIndicator extends CommonNavigatorAdapter { + + private Context mContext; + private List mTitleList; + private int mBottomMargin; + + public CarMagicIndicator(Context context, List titleList, int bottomMargin) { + mContext = context; + mTitleList = titleList; + mBottomMargin = bottomMargin; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_999999)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(1); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(i).getName()); + if (mTitleList.get(i).getName().equals("座驾")) { + scaleTransitionPagerTitleView.findViewById(R.id.car_badge).setId(R.id.car_badge_garage); + } + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(mContext, 2.5)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 1.25)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 16)); + indicator.setColors(context.getResources().getColor(R.color.appColor)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/ShowCarGuideDialog.java b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/ShowCarGuideDialog.java new file mode 100644 index 000000000..daea5e1d2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/view/widgets/ShowCarGuideDialog.java @@ -0,0 +1,117 @@ +package com.yizhuan.erban.decoration.view.widgets; + +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatButton; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; + +import com.opensource.svgaplayer.SVGAImageView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.MyDecorationActivity; + +/** + *

座驾指引对话框

+ * + * @author jiahui + * date 2018/3/6 + */ +public class ShowCarGuideDialog extends DialogFragment implements View.OnClickListener { + private AppCompatButton mBtnCarGoShop; + private ImageView mIvCarClose; + private SVGAImageView mSVGAImageView; + +// private SVGAParser mSVGAParser; + private String effect; + + public static ShowCarGuideDialog newInstance(String effect) { + ShowCarGuideDialog showCarGuideDialog = new ShowCarGuideDialog(); + Bundle bundle = new Bundle(); + bundle.putString("effect", effect); + showCarGuideDialog.setArguments(bundle); + return showCarGuideDialog; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle arguments = getArguments(); + if (arguments != null) { + effect = arguments.getString("effect"); + } + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.car_dialog_show_guide, container, false); + mBtnCarGoShop = view.findViewById(R.id.btn_car_go_shop); + mIvCarClose = view.findViewById(R.id.iv_car_dialog_close); + mSVGAImageView = view.findViewById(R.id.svga_car_dialog_guide); + + mBtnCarGoShop.setOnClickListener(this); + mIvCarClose.setOnClickListener(this); + + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + Window window = getDialog().getWindow(); + if (window != null) + window.requestFeature(Window.FEATURE_NO_TITLE); + super.onActivityCreated(savedInstanceState); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(0x80000000)); + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); + } +// if (!TextUtils.isEmpty(effect)) { +// mSVGAParser = new SVGAParser(getActivity()); +// try { +// mSVGAParser.parse(new URL(effect), new SVGAParser.ParseCompletion() { +// @Override +// public void onComplete(SVGAVideoEntity svgaVideoEntity) { +// mSVGAImageView.setImageDrawable(new SVGADrawable(svgaVideoEntity)); +// mSVGAImageView.startAnimation(); +// } +// +// @Override +// public void onError() { +// +// } +// }); +// } catch (MalformedURLException e) { +// e.printStackTrace(); +// } +// } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_car_go_shop: + MyDecorationActivity.start(getActivity(), 0); + dismiss(); + break; + case R.id.iv_car_dialog_close: + dismiss(); + break; + } + } + + @Override + public void onDismiss(DialogInterface dialog) { + if (mSVGAImageView.isAnimating()) { + mSVGAImageView.clearAnimation(); + mSVGAImageView = null; + } + super.onDismiss(dialog); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/CarShopVm.java b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/CarShopVm.java new file mode 100644 index 000000000..59a3bff6d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/CarShopVm.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.decoration.viewmodel; + +import com.yizhuan.erban.base.BaseListViewModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by huangmeng1 on 2018/5/9. + */ + +public class CarShopVm extends BaseListViewModel { + + private String uid; + public void setUid(String uid) { + this.uid = uid; + } + + @Override + public Single>> getSingle() { + return CarModel.get() + .getStoreCarsV2(Long.parseLong(uid), String.valueOf(page), String.valueOf(pageSize)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/DecorationVm.java b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/DecorationVm.java new file mode 100644 index 000000000..c7ca3a0e3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/DecorationVm.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.decoration.viewmodel; + +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.decoration.headwear.HeadwearModel; + +import io.reactivex.Single; + +/** + * Created by huangmeng1 on 2018/5/7. + */ + +public class DecorationVm extends BaseViewModel{ + + public DecorationVm() { + } + + public Single buyHeadWearV2(long headWearId, int currencyType) { + return HeadwearModel.get().buyHeadWearV2(headWearId, currencyType); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/HeadWearVm.java b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/HeadWearVm.java new file mode 100644 index 000000000..bedea2efb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/HeadWearVm.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.decoration.viewmodel; + +import com.yizhuan.erban.base.BaseListViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.HeadwearModel; + +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by huangmeng1 on 2018/5/10. + */ + +public class HeadWearVm extends BaseListViewModel { + private boolean isMyHeadWear; + private String uid; + + public void setUid(String uid) { + this.uid = uid; + } + + public void setMyHeadWear(boolean myHeadWear) { + isMyHeadWear = myHeadWear; + } + + public HeadWearVm() { + } + + @Override + public Single>> getSingle() { + if (isMyHeadWear) { + return HeadwearModel.get().getHeadWearListV2(AuthModel.get().getCurrentUid()); + } + return HeadwearModel.get().getStoreHeadWearListV2(Long.parseLong(uid), page + "", pageSize + ""); + } + + public Single userHeadWear(String headWearId) { + return HeadwearModel.get().userMyHeadWear(headWearId); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/MyCarVm.java b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/MyCarVm.java new file mode 100644 index 000000000..421cd316b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/decoration/viewmodel/MyCarVm.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.decoration.viewmodel; + +import com.yizhuan.erban.base.BaseListViewModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; + +import java.util.List; + +import io.reactivex.Single; + +public class MyCarVm extends BaseListViewModel { + private String uid; + + public void setUid(String uid) { + this.uid = uid; + } + + public MyCarVm() { + } + + @Override + public Single>> getSingle() { + return CarModel.get().getMyCars(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/event/OpenRoomIntroEvent.java b/app/src/main/java/com/yizhuan/erban/event/OpenRoomIntroEvent.java new file mode 100644 index 000000000..06baa9326 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/event/OpenRoomIntroEvent.java @@ -0,0 +1,4 @@ +package com.yizhuan.erban.event; + +public class OpenRoomIntroEvent { +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyAttentionFragmentView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyAttentionFragmentView.java new file mode 100644 index 000000000..85d603a6c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyAttentionFragmentView.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public interface IFamilyAttentionFragmentView extends IMvpBaseView{ + void onRefreshData(List attentionInfoList); + + void onLoadMoreData(List attentionInfoList); + + void onRefreshDataFail(String error); + + void onLoadMoreDataFail(String error); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencySearchView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencySearchView.java new file mode 100644 index 000000000..2b8b6fe20 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencySearchView.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/30 + */ + +public interface IFamilyCurrencySearchView extends IMvpBaseView { + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencyView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencyView.java new file mode 100644 index 000000000..f799c9e6a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyCurrencyView.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public interface IFamilyCurrencyView extends IMvpBaseView { + void onLoadData(List billItemInfos, int page, int dataSize); + + void showErrorView(String message); + + void refreshData(); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFansListFragmentView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFansListFragmentView.java new file mode 100644 index 000000000..94bbe5da7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFansListFragmentView.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.user.bean.FansListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public interface IFamilyFansListFragmentView extends IMvpBaseView { + void onRefreshData(FansListInfo fansListInfo); + + void onLoadMoreData(FansListInfo fansListInfo); + + void onRefreshDataFail(String message); + + void onLoadMoreDataFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFriendListFragmentView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFriendListFragmentView.java new file mode 100644 index 000000000..c57260313 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyFriendListFragmentView.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public interface IFamilyFriendListFragmentView extends IMvpBaseView { + + void onRefreshData(List userInfos); + + void onLoadMoreData(List userInfos); + + void onRefreshDataFail(String message); + + void onLoadMoreDataFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyGameListActivityView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyGameListActivityView.java new file mode 100644 index 000000000..e1b72c803 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyGameListActivityView.java @@ -0,0 +1,19 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/23 + */ + +public interface IFamilyGameListActivityView extends IMvpBaseView { + + void onLoadData(List data, int page); + + void onLoadDataFail(String error, int page); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyInfoView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyInfoView.java new file mode 100644 index 000000000..aee9a426a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyInfoView.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public interface IFamilyInfoView extends IMvpBaseView { + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyManageActivityView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyManageActivityView.java new file mode 100644 index 000000000..bc3c6d4dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyManageActivityView.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/25 + */ + +public interface IFamilyManageActivityView extends IMvpBaseView { + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberListView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberListView.java new file mode 100644 index 000000000..d3c47f47d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberListView.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public interface IFamilyMemberListView extends IMvpBaseView { + void onLoadData(List memberInfoList); + + void reloadFamilyMember(); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberSearchView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberSearchView.java new file mode 100644 index 000000000..599b218b7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyMemberSearchView.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public interface IFamilyMemberSearchView extends IMvpBaseView { + + void update(List memberInfos); +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyPlazaActivityView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyPlazaActivityView.java new file mode 100644 index 000000000..ad66b3313 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilyPlazaActivityView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/23 + */ + +public interface IFamilyPlazaActivityView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySearchView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySearchView.java new file mode 100644 index 000000000..a92f1e3ca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySearchView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/2 + */ + +public interface IFamilySearchView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySelectFriendActivityView.java b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySelectFriendActivityView.java new file mode 100644 index 000000000..987dad727 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/contract/viewinterface/IFamilySelectFriendActivityView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.family.contract.viewinterface; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public interface IFamilySelectFriendActivityView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyAttentionPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyAttentionPresenter.java new file mode 100644 index 000000000..76811eef5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyAttentionPresenter.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyAttentionFragmentView; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public class FamilyAttentionPresenter extends BaseMvpPresenter { + private int mPage = Constants.PAGE_START; + private boolean isLoading = false; + + public void refreshData() { + loadData(Constants.PAGE_START); + } + public void loadMoreData() { + loadData(mPage + 1); + } + + private void loadData(int targetPage){ + if (isLoading){ + if (getMvpView() == null){ + return; + } + if (mPage == Constants.PAGE_START) { + getMvpView().onRefreshDataFail("正在加载,请稍后..."); + } else { + getMvpView().onLoadMoreDataFail("正在加载,请稍后..."); + } + return; + } + this.mPage = targetPage; + isLoading = true; + AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + mPage, + Constants.PAGE_SIZE + ) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List attentionInfos) { + isLoading = false; + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshData(attentionInfos); + }else { + getMvpView().onLoadMoreData(attentionInfos); + } + } + + @Override + public void onError(Throwable e) { + isLoading = false; + if (mPage == Constants.PAGE_START) { + getMvpView().onRefreshDataFail(e.getMessage()); + } else { + getMvpView().onLoadMoreDataFail(e.getMessage()); + } + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyCurrencyPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyCurrencyPresenter.java new file mode 100644 index 000000000..064953839 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyCurrencyPresenter.java @@ -0,0 +1,282 @@ +package com.yizhuan.erban.family.presenter; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyCurrencyView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.BillDateDivInfo; +import com.yizhuan.xchat_android_core.family.bean.TransactionRecordInfo; +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.FamilyMoneyManagementInfo; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.MonthlyRecord; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.TradeMoneyRecord; +import com.yizhuan.xchat_android_core.family.event.FamilyCurrencyUpdateEvent; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyCurrencyPresenter extends BaseMvpPresenter { + + private FamilyMoneyManagementInfo familyMoneyManagementInfo; + private List monthlyRecordList = new ArrayList<>(); + private List billItemInfos = new ArrayList<>(); + + private int page = Constants.PAGE_START; + private boolean isLoading = false; + + private SimpleDateFormat monthDateFormat = new SimpleDateFormat("yyyy年MM月", Locale.getDefault()); + private SimpleDateFormat dayDateFormat = new SimpleDateFormat("MM月dd日 HH:mm:ss", Locale.getDefault()); + + private CompositeDisposable compositeDisposable; + + public FamilyMoneyManagementInfo getFamilyMoneyManagementInfo() { + return familyMoneyManagementInfo; + } + + public List getBillItemInfos() { + return billItemInfos; + } + + public FamilyCurrencyPresenter() { + + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + this.compositeDisposable = new CompositeDisposable(); + addRxEvent(); + } + + + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (this.compositeDisposable != null) { + this.compositeDisposable.dispose(); + this.compositeDisposable = null; + } + } + + private void addRxEvent() { + /** + * 转让或者贡献家族币后更新家族币信息 + */ + RxBusHelper.doOnMainThread(FamilyCurrencyUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyCurrencyUpdateEvent familyCurrencyUpdateEvent) throws Exception { + getMvpView().refreshData(); + } + }); + } + + /** + * 获取家族币 头部卡片信息 + * @return + */ + public Single loadData() { + + return FamilyModel.Instance().loadFamilyBillSummary() + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>() { + @Override + public SingleSource apply(FamilyMoneyManagementInfo response) throws Exception { + familyMoneyManagementInfo = response; + return Single.just(familyMoneyManagementInfo); + } + }); + + } + + + + public void onRefreshRecordList(@NonNull String timeMillis){ + loadMemberRecordList(timeMillis,Constants.PAGE_START); + } + + public void onLoadMoreRecordList(@NonNull String timeMillis){ + loadMemberRecordList(timeMillis, this.page); + } + + /** + * 获取某个成员家族币流水 + * @param timeMillis + */ + private void loadMemberRecordList(@NonNull String timeMillis, int targetPage){ + long uid = AuthModel.get().getCurrentUid(); + if (uid <= 0){ + if (getMvpView() == null){ + return; + } + getMvpView().showErrorView("找不到uid"); + return; + } + if (isLoading){ + if (getMvpView() == null){ + return; + } + getMvpView().showErrorView("正在加载数据,请稍后..."); + return; + } + page = targetPage; + isLoading = true; + FamilyModel.Instance().loadFamilyMemberBillRecordList( + String.valueOf(uid), + String.valueOf(page), + String.valueOf(Constants.PAGE_SIZE), + timeMillis + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(TradeMoneyRecord tradeMoneyRecord) { + isLoading = false; + if (page == Constants.PAGE_START){ + monthlyRecordList.clear(); + billItemInfos.clear(); + } + if (tradeMoneyRecord.getRecordMonVos().size() > 0) { + transferToViewModel(tradeMoneyRecord.getRecordMonVos()); + } + int recordSize = 0; + for (MonthlyRecord monthlyRecord : tradeMoneyRecord.getRecordMonVos()) { + recordSize += monthlyRecord.getList().size(); + } + if (page == Constants.PAGE_START && billItemInfos.isEmpty()) { + showNoData(Long.parseLong(timeMillis)); + } + getMvpView().onLoadData(billItemInfos, page, recordSize); + page ++; + } + + @Override + public void onError(Throwable e) { + isLoading = false; + getMvpView().showErrorView(e.getMessage()); + } + }); + + } + + /** + * 整合月份数据,转换数据 + * @param + * @return + */ + @NonNull + private void transferToViewModel(List recordMonVos) { + if (ListUtils.isListEmpty(recordMonVos)){ + return; + } + List recordList = new ArrayList<>(recordMonVos); + if (monthlyRecordList.size() == 0){ + monthlyRecordList.addAll(recordList); + }else{ + //分页的时候跨越月份了,整合起来 + MonthlyRecord monthlyRecord = monthlyRecordList.get(monthlyRecordList.size() - 1); + if (monthlyRecord.getMonth() == recordList.get(0).getMonth()){ + MonthlyRecord monthlyRecord1 = recordList.remove(0); + monthlyRecord.getList().addAll(monthlyRecord1.getList()); + for (MonthlyRecord.RecordItem recordItem : monthlyRecord1.getList()) { + VMBillItemInfo item = new VMBillItemInfo<>(VMBillItemInfo.TYPE_TRANSACTION_RECORD); + TransactionRecordInfo transactionRecordInfo = new TransactionRecordInfo(); + transactionRecordInfo.setAvatar(recordItem.getAvatar()); + transactionRecordInfo.setTitle(recordItem.getTitle()); + transactionRecordInfo.setData(recordItem.getAmount()); + transactionRecordInfo.setDate(dayDateFormat.format(new Date(recordItem.getTime()))); + transactionRecordInfo.setDesc("["+recordItem.getSource()+"]"); + transactionRecordInfo.setMoneyName(monthlyRecord.getMoneyName()); + transactionRecordInfo.setType(recordItem.getType()); + transactionRecordInfo.setUid(recordItem.getUid()); + item.setData(transactionRecordInfo); + billItemInfos.add(item); + } + } + monthlyRecordList.addAll(recordList); + } + + for (MonthlyRecord monthlyRecord : recordList) { + VMBillItemInfo dataItem = new VMBillItemInfo<>(VMBillItemInfo.TYPE_DATE_DIV); + BillDateDivInfo billDateDivInfo = new BillDateDivInfo(); + billDateDivInfo.setMoneyName(monthlyRecord.getMoneyName()); + billDateDivInfo.setDate(monthDateFormat.format(new Date(monthlyRecord.getMonth()))); + billDateDivInfo.setIncome(monthlyRecord.getIncome()); + billDateDivInfo.setExpend(monthlyRecord.getCost()); + dataItem.setData(billDateDivInfo); + billItemInfos.add(dataItem); + for (MonthlyRecord.RecordItem recordItem : monthlyRecord.getList()) { + VMBillItemInfo item = new VMBillItemInfo<>(VMBillItemInfo.TYPE_TRANSACTION_RECORD); + TransactionRecordInfo transactionRecordInfo = new TransactionRecordInfo(); + transactionRecordInfo.setAvatar(recordItem.getAvatar()); + transactionRecordInfo.setTitle(recordItem.getTitle()); + transactionRecordInfo.setData(recordItem.getAmount()); + transactionRecordInfo.setDate(dayDateFormat.format(new Date(recordItem.getTime()))); + transactionRecordInfo.setDesc("["+recordItem.getSource()+"]"); + transactionRecordInfo.setMoneyName(monthlyRecord.getMoneyName()); + transactionRecordInfo.setType(recordItem.getType()); + transactionRecordInfo.setUid(recordItem.getUid()); + item.setData(transactionRecordInfo); + billItemInfos.add(item); + } + } + } + + public void showNoData(long timeMills){ + VMBillItemInfo dataItem = new VMBillItemInfo<>(VMBillItemInfo.TYPE_DATE_DIV); +// BillDateDivInfo billDateDivInfo = new BillDateDivInfo(); +// billDateDivInfo.setMoneyName(familyMoneyManagementInfo.getMoneyName()); +// billDateDivInfo.setDate(monthDateFormat.format(new Date(timeMills))); +// billDateDivInfo.setIncome(0.0f); +// billDateDivInfo.setExpend(0.0f); +// dataItem.setData(billDateDivInfo); +// billItemInfos.add(dataItem); + VMBillItemInfo emptyTip = new VMBillItemInfo<>(VMBillItemInfo.TYPE_EMPTY_TIP); + billItemInfos.add(emptyTip); + } + + + /** + * 贡献家族币 + * @param count + */ + public Single contributionCurrency(double count) { + return FamilyModel.Instance().contributeCurrency( + count + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFansListPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFansListPresenter.java new file mode 100644 index 000000000..2bf257e3b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFansListPresenter.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyFansListFragmentView; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; + +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.FansListInfo; + + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public class FamilyFansListPresenter extends BaseMvpPresenter { + private int mPage = Constants.PAGE_START; + private boolean isLoading = false; + public void refreshData() { + loadData(Constants.PAGE_START); + } + + public void loadMoreData() { + loadData(mPage + 1); + } + + private void loadData(int targetPage){ + if (isLoading){ + if (getMvpView() == null){ + return; + } + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshDataFail("正在加载,请稍后..."); + }else { + getMvpView().onLoadMoreDataFail("正在加载,请稍后..."); + } + return; + } + this.mPage = targetPage; + isLoading = true; + AttentionModel.get().getFansList( + AuthModel.get().getCurrentUid(), + this.mPage, + Constants.PAGE_SIZE + ) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FansListInfo fansListInfo) { + isLoading = false; + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshData(fansListInfo); + }else { + getMvpView().onLoadMoreData(fansListInfo); + } + } + + @Override + public void onError(Throwable e) { + isLoading = false; + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshDataFail(e.getMessage()); + }else { + getMvpView().onLoadMoreDataFail(e.getMessage()); + } + } + }); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFriendListPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFriendListPresenter.java new file mode 100644 index 000000000..bb95a925b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyFriendListPresenter.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyFriendListFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public class FamilyFriendListPresenter extends BaseMvpPresenter { + private int mPage = Constants.PAGE_START; + private final int pageSize = Constants.PAGE_SIZE; + private boolean isLoading = false; + + public void refreshData() { + loadData(Constants.PAGE_START); + } + + public void loadMoreData() { + loadData(mPage + 1); + } + + private void loadData(int targetPage){ + if (isLoading){ + if (getMvpView() == null){ + return; + } + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshDataFail("正在加载,请稍后..."); + }else { + getMvpView().onLoadMoreDataFail("正在加载,请稍后..."); + } + return; + } + this.mPage = targetPage; + isLoading = true; + IMFriendModel.get().getMyFriendsUserInfos(mPage, pageSize) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List userInfos) { + isLoading = false; + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshData(userInfos); + }else { + getMvpView().onLoadMoreData(userInfos); + } + } + + @Override + public void onError(Throwable e) { + isLoading = false; + if (mPage == Constants.PAGE_START){ + getMvpView().onRefreshDataFail(e.getMessage()); + }else { + getMvpView().onLoadMoreDataFail(e.getMessage()); + } + } + }); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyGameListPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyGameListPresenter.java new file mode 100644 index 000000000..559e4e4c3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyGameListPresenter.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyGameListActivityView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/7/23 + */ + +public class FamilyGameListPresenter extends BaseMvpPresenter { + + private AtomicInteger curPage = new AtomicInteger(Constants.PAGE_START); + private boolean isLoading = false; + + public void refreshData() { + curPage.set(Constants.PAGE_START); + loadMoreData(); + } + + + public void loadMoreData() { + loadData(curPage.get()) + .subscribe((familyGameInfos, throwable) -> { + if (throwable == null) { + getMvpView().onLoadData(familyGameInfos, curPage.getAndIncrement()); + } else { + getMvpView().onLoadDataFail(throwable.getMessage(), curPage.get()); + } + }); + } + + + private Single> loadData(int targetPage){ + FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (familyInfo == null){ + return Single.error(new Throwable("家族信息不存在.")); + } + + if (isLoading){ + return Single.error(new Throwable("正在刷新,请稍后...")); + } + isLoading = true; + return FamilyModel.Instance().loadFamilyGameList( + familyInfo.getFamilyId(), + targetPage, + Constants.PAGE_SIZE + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function, SingleSource>>() { + @Override + public SingleSource> apply(List familyGameInfos) throws Exception { + isLoading = false; + return Single.just(familyGameInfos); + } + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + isLoading = false; + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyHomePresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyHomePresenter.java new file mode 100644 index 000000000..980539333 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyHomePresenter.java @@ -0,0 +1,177 @@ +package com.yizhuan.erban.family.presenter; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.event.FamilyCurrencyUpdateEvent; +import com.yizhuan.xchat_android_core.family.event.FamilyMemberUpdateEvent; +import com.yizhuan.xchat_android_core.family.event.FamilyUpdateEvent; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.erban.home.view.IFamilyHomeActivityView; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/23 + */ + +public class FamilyHomePresenter extends BaseMvpPresenter { + + private FamilyInfo familyInfo; + private CompositeDisposable compositeDisposable; + + public FamilyInfo getFamilyInfo() { + return familyInfo; + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + compositeDisposable = new CompositeDisposable(); + addEvent(); + } + + + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (compositeDisposable != null){ + compositeDisposable.dispose(); + compositeDisposable = null; + } + } + + + private void addEvent() { + /** + * 转让或者贡献家族币后更新家族信息 + */ + RxBusHelper.doOnMainThread(FamilyCurrencyUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyCurrencyUpdateEvent familyCurrencyUpdateEvent) throws Exception { + getMvpView().reloadMyFamilyInfo(familyInfo.getFamilyId()); + } + }); + /** + * 修改家族相关信息更新家族信息事件 + */ + RxBusHelper.doOnMainThread(FamilyUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyUpdateEvent familyUpdateEvent) throws Exception { + if (familyUpdateEvent.getFamilyInfo() != null + && familyInfo.getFamilyId().equals(familyUpdateEvent.getFamilyInfo().getFamilyId())) { + familyInfo = familyUpdateEvent.getFamilyInfo(); + getMvpView().onLoadData(familyUpdateEvent.getFamilyInfo()); + } else if (familyUpdateEvent.getFamilyInfo() == null + && familyInfo.getEnterStatus() == FamilyInfo.STATUS_IN_FAMILY){ + getMvpView().close(); + } + + } + }); + + + /** + * 成员更新 + */ + RxBusHelper.doOnMainThread(FamilyMemberUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyMemberUpdateEvent familyMemberUpdateEvent) throws Exception { + getMvpView().reloadMyFamilyInfo(familyInfo.getFamilyId()); + } + }); + + } + /** + * 加载家族信息 + * @param familyId + */ + public Single loadData(String familyId) { + + return FamilyModel.Instance().loadFamilyHomeInfo( + familyId + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>() { + @Override + public SingleSource apply(FamilyInfo familyInfo) throws Exception { + FamilyHomePresenter.this.familyInfo = familyInfo; + return Single.just(familyInfo); + } + }); + + + } + + /** + * 退出家族 + * @return + */ + public Single exitFamily() { + return FamilyModel.Instance().exitFamily() + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } + + /** + * 申请加入家族 + * @return + */ + public Single joinFamily(String str) { + if (null == familyInfo){ + return Single.error(new Exception("没有家族数据!")); + } + + return FamilyModel.Instance().applyJoinFamily( + familyInfo.getFamilyId(), + str + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } + + /** + * 加入家族群 + * @return + */ + public Single joinFamilyGroup(String chatId, String message) { + + + return FamilyModel.Instance().joinFamilyGroup( + chatId, + message + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>() { + @Override + public SingleSource apply(String response) throws Exception { + getMvpView().reloadMyFamilyInfo(familyInfo.getFamilyId()); + return Single.just(response); + } + }); + } + + /** + * 邀请朋友加入家族 + * @param friendUid + * @return + */ + public Single inviteFriendToFamily(long friendUid) { + return FamilyModel.Instance().inviteIntoFamily( + String.valueOf(friendUid) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyInfoPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyInfoPresenter.java new file mode 100644 index 000000000..323178220 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyInfoPresenter.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyInfoView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyInfoPresenter extends BaseMvpPresenter { + + /** + * 修改验证状态 + * @param isOn + * @return + */ + public Single changeVerifyStatus(final boolean isOn) { + final FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo){ + return Single.error(new Exception("没有加入家族..")); + } + return FamilyModel.Instance().modifyFamilyInfo( + familyInfo.getFamilyId(), + null, + null, + isOn ? "1":"0" + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } + + /** + * 修改家族头像 + * @param url + * @return + */ + public Single changeFamilyAvatar(final String url) { + final FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo){ + return Single.error(new Exception("没有加入家族..")); + } + return FamilyModel.Instance().modifyFamilyInfo( + familyInfo.getFamilyId(), + null, + url, + null + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + /** + * 修改家族名称 + * @param str + * @return + */ + public Single changeFamilyName(final String str) { + final FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo){ + return Single.error(new Exception("没有加入家族..")); + } + return FamilyModel.Instance().modifyFamilyInfo( + familyInfo.getFamilyId(), + str, + null, + null + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyListPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyListPresenter.java new file mode 100644 index 000000000..20ea35051 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyListPresenter.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySearchView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.response.RespFamilyRankList; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/24 + */ + +public class FamilyListPresenter extends BaseMvpPresenter { + + public Single> refreshData() { + return loadData(); + } + + + private Single> loadData(){ + return FamilyModel.Instance().loadFamilyRankingList( + RespFamilyRankList.TYPE_THIS_WEEK, + String.valueOf(Constants.PAGE_START), + String.valueOf(20) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(RespFamilyRankList response) throws Exception { + return Single.just(response.getFamilys()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyManagePresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyManagePresenter.java new file mode 100644 index 000000000..ba220d0cf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyManagePresenter.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyManageActivityView; + +/** + * @author jack + * @Description + * @Date 2018/5/25 + */ + +public class FamilyManagePresenter extends BaseMvpPresenter { + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberCurrencyPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberCurrencyPresenter.java new file mode 100644 index 000000000..b61f87fa2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberCurrencyPresenter.java @@ -0,0 +1,208 @@ +package com.yizhuan.erban.family.presenter; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyCurrencyView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.BillDateDivInfo; +import com.yizhuan.xchat_android_core.family.bean.TransactionRecordInfo; +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.MonthlyRecord; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.TradeMoneyRecord; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyMemberCurrencyPresenter extends BaseMvpPresenter { + + private List monthlyRecordList = new ArrayList<>(); + private List billItemInfos = new ArrayList<>(); + + private int page = Constants.PAGE_START; + private boolean isLoading = false; + + private SimpleDateFormat monthDateFormat = new SimpleDateFormat("yyyy年MM月", Locale.getDefault()); + private SimpleDateFormat dayDateFormat = new SimpleDateFormat("MM月dd日 HH:mm:ss", Locale.getDefault()); + + + + public List getBillItemInfos() { + return billItemInfos; + } + + public FamilyMemberCurrencyPresenter() { + + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + } + + + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + } + + + public void onRefreshRecordList(@NonNull String timeMillis, String targetId){ + loadMemberRecordList(timeMillis, targetId, Constants.PAGE_START); + } + + public void onLoadMoreRecordList(@NonNull String timeMillis, String targetId){ + loadMemberRecordList(timeMillis,targetId, this.page); + } + + + /** + * 获取某个人家族币交易记录 + * + * @param timeMillis + * @param targetId + * @return + */ + private void loadMemberRecordList(@NonNull String timeMillis, String targetId, int targetPage){ + if (isLoading){ + if (getMvpView() == null){ + return; + } + getMvpView().showErrorView("正在加载,请稍后..."); + return; + } + page = targetPage; + isLoading = true; + FamilyModel.Instance().loadFamilyMemberBillRecordList( + targetId, + String.valueOf(page), + String.valueOf(Constants.PAGE_SIZE), + timeMillis + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(TradeMoneyRecord tradeMoneyRecord) { + isLoading = false; + if (page == Constants.PAGE_START){ + monthlyRecordList.clear(); + billItemInfos.clear(); + } + if (tradeMoneyRecord.getRecordMonVos().size() > 0) { + transferToViewModel(tradeMoneyRecord.getRecordMonVos()); + } + if (page == Constants.PAGE_START && billItemInfos.isEmpty()) { + showNoData(Long.parseLong(timeMillis)); + } + getMvpView().onLoadData(billItemInfos, page, tradeMoneyRecord.getRecordMonVos().size()); + page ++; + } + + @Override + public void onError(Throwable e) { + isLoading = false; + getMvpView().showErrorView(e.getMessage()); + } + }); + + } + + /** + * 整合月份数据,转换数据 + * @param + * @return + */ + @NonNull + private void transferToViewModel(List recordMonVos) { + if (ListUtils.isListEmpty(recordMonVos)){ + return; + } + if (monthlyRecordList.size() == 0){ + monthlyRecordList.addAll(recordMonVos); + }else{ + //分页的时候跨越月份了,整合起来 + MonthlyRecord monthlyRecord = monthlyRecordList.get(monthlyRecordList.size() - 1); + if (monthlyRecord.getMonth() == recordMonVos.get(0).getMonth()){ + MonthlyRecord monthlyRecord1 = recordMonVos.remove(0); + monthlyRecord.getList().addAll(monthlyRecord1.getList()); + for (MonthlyRecord.RecordItem recordItem : monthlyRecord1.getList()) { + VMBillItemInfo item = new VMBillItemInfo<>(VMBillItemInfo.TYPE_TRANSACTION_RECORD); + TransactionRecordInfo transactionRecordInfo = new TransactionRecordInfo(); + transactionRecordInfo.setAvatar(recordItem.getAvatar()); + transactionRecordInfo.setTitle(recordItem.getTitle()); + transactionRecordInfo.setData(recordItem.getAmount()); + transactionRecordInfo.setDate(dayDateFormat.format(new Date(recordItem.getTime()))); + transactionRecordInfo.setDesc("["+recordItem.getSource()+"]"); + transactionRecordInfo.setMoneyName(monthlyRecord.getMoneyName()); + item.setData(transactionRecordInfo); + billItemInfos.add(item); + } + } + monthlyRecordList.addAll(recordMonVos); + } + + for (MonthlyRecord monthlyRecord : recordMonVos) { + VMBillItemInfo dataItem = new VMBillItemInfo<>(VMBillItemInfo.TYPE_DATE_DIV); + BillDateDivInfo billDateDivInfo = new BillDateDivInfo(); + billDateDivInfo.setMoneyName(monthlyRecord.getMoneyName()); + billDateDivInfo.setDate(monthDateFormat.format(new Date(monthlyRecord.getMonth()))); + billDateDivInfo.setIncome(monthlyRecord.getIncome()); + billDateDivInfo.setExpend(monthlyRecord.getCost()); + dataItem.setData(billDateDivInfo); + billItemInfos.add(dataItem); + for (MonthlyRecord.RecordItem recordItem : monthlyRecord.getList()) { + VMBillItemInfo item = new VMBillItemInfo<>(VMBillItemInfo.TYPE_TRANSACTION_RECORD); + TransactionRecordInfo transactionRecordInfo = new TransactionRecordInfo(); + transactionRecordInfo.setAvatar(recordItem.getAvatar()); + transactionRecordInfo.setTitle(recordItem.getTitle()); + transactionRecordInfo.setData(recordItem.getAmount()); + transactionRecordInfo.setDate(dayDateFormat.format(new Date(recordItem.getTime()))); + transactionRecordInfo.setDesc("["+recordItem.getSource()+"]"); + transactionRecordInfo.setMoneyName(monthlyRecord.getMoneyName()); + item.setData(transactionRecordInfo); + billItemInfos.add(item); + } + } + + } + + public void showNoData(long timeMills){ + VMBillItemInfo dataItem = new VMBillItemInfo<>(VMBillItemInfo.TYPE_DATE_DIV); + BillDateDivInfo billDateDivInfo = new BillDateDivInfo(); + if (FamilyModel.Instance().getMyFamily() != null) { + billDateDivInfo.setMoneyName(FamilyModel.Instance().getMyFamily().getMoneyName()); + } + billDateDivInfo.setDate(monthDateFormat.format(new Date(timeMills))); + billDateDivInfo.setIncome(0.0f); + billDateDivInfo.setExpend(0.0f); + dataItem.setData(billDateDivInfo); + billItemInfos.add(dataItem); + VMBillItemInfo emptyTip = new VMBillItemInfo<>(VMBillItemInfo.TYPE_EMPTY_TIP); + billItemInfos.add(emptyTip); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberListPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberListPresenter.java new file mode 100644 index 000000000..b04cb37ee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberListPresenter.java @@ -0,0 +1,146 @@ +package com.yizhuan.erban.family.presenter; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyMemberListView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.bean.response.memberList.RespFamilymember; +import com.yizhuan.xchat_android_core.family.event.FamilyCurrencyUpdateEvent; +import com.yizhuan.xchat_android_core.family.event.FamilyMemberUpdateEvent; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyMemberListPresenter extends BaseMvpPresenter { + + private int page = Constants.PAGE_START; + private boolean isLoading = false; + private CompositeDisposable compositeDisposable; + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + compositeDisposable = new CompositeDisposable(); + addEvent(); + } + + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (null != compositeDisposable){ + compositeDisposable.dispose(); + compositeDisposable.dispose(); + } + } + + private void addEvent() { + /** + * 成员更新 + */ + RxBusHelper.doOnMainThread(FamilyMemberUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyMemberUpdateEvent familyMemberUpdateEvent) throws Exception { + getMvpView().reloadFamilyMember(); + } + }); + } + + + public Single refreshData(){ + FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo) { + return Single.error(new Throwable("没有家族信息")); + } + this.page = Constants.PAGE_START; + return loadData(familyInfo.getFamilyId(),Constants.PAGE_START); + } + + public Single loadMoreData() { + FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo) { + return Single.error(new Throwable("没有家族信息")); + } + return loadData(familyInfo.getFamilyId(),this.page); + } + + private Single loadData(String familyId, int targetPage) { + + if (isLoading){ + return Single.error(new Throwable("正在加载,请稍后...")); + } + this.page = targetPage; + isLoading = true; + return FamilyModel.Instance().loadFamilyMemberList( + familyId, + String.valueOf(page), + String.valueOf(Constants.PAGE_SIZE) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>() { + @Override + public SingleSource apply(RespFamilymember respFamilymember) throws Exception { + isLoading = false; + page++; + return Single.just(respFamilymember); + } + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + isLoading = false; + } + }); + + } + + public FamilyInfo getFamilyInfo(){ + return FamilyModel.Instance().getMyFamily(); + } + + /** + * 移除家族成员 + * @param familyMemberInfo + */ + public Single removeFamilyMember(FamilyMemberInfo familyMemberInfo) { + if (null == familyMemberInfo){ + return Single.error(new Throwable("没有成员信息")); + } + return FamilyModel.Instance().kickOutFamily( + String.valueOf(familyMemberInfo.getUid()) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + /** + * 家族币转让 + * @param familyMemberInfo + * @param count + * @return + */ + public Single transferCurrency(FamilyMemberInfo familyMemberInfo, double count) { + return FamilyModel.Instance().transferCurrency( + String.valueOf(familyMemberInfo.getUid()), + count + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberSearchPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberSearchPresenter.java new file mode 100644 index 000000000..243df0bca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyMemberSearchPresenter.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyMemberSearchView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.bean.response.memberList.RespFamilymember; +import com.yizhuan.xchat_android_core.family.event.FamilyCurrencyUpdateEvent; +import com.yizhuan.xchat_android_core.family.event.FamilyMemberUpdateEvent; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyMemberSearchPresenter extends BaseMvpPresenter { + private int page = Constants.PAGE_START; + private String searchStr; + + public FamilyInfo getFamilyInfo(){ + return FamilyModel.Instance().getMyFamily(); + } + + public Single> search(String str) { + page = Constants.PAGE_START; + searchStr = str; + return loadData(searchStr); + } + + private Single> loadData(String searchKey) { + + FamilyInfo familyInfo = FamilyModel.Instance().getMyFamily(); + if (null == familyInfo) { + return Single.error(new Throwable("没有家族信息")); + } + + return FamilyModel.Instance().searchFamilyMemberList( + familyInfo.getFamilyId(), + null, + null, + searchKey + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(RespFamilymember respFamilymember) throws Exception { + page++; + return Single.just(respFamilymember.getMembers()); + } + }); + + } + + public Single> loadMoreData() { + return loadData(searchStr); + } + + /** + * 移除家族成员 + * @param familyMemberInfo + */ + public Single removeFamilyMember(FamilyMemberInfo familyMemberInfo) { + if (null == familyMemberInfo){ + return Single.error(new Throwable("没有成员信息")); + } + return FamilyModel.Instance().kickOutFamily( + String.valueOf(familyMemberInfo.getUid()) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + /** + * 家族币转让 + * @param familyMemberInfo + * @param count + * @return + */ + public Single transferCurrency(FamilyMemberInfo familyMemberInfo, double count) { + return FamilyModel.Instance().transferCurrency( + String.valueOf(familyMemberInfo.getUid()), + count + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyPlazaPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyPlazaPresenter.java new file mode 100644 index 000000000..e348782b8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilyPlazaPresenter.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyPlazaActivityView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.family.bean.response.RespFamilyRankList; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import io.reactivex.Single; + +/** + * @author jack + * @Description + * @Date 2018/5/23 + */ + +public class FamilyPlazaPresenter extends BaseMvpPresenter { + + public FamilyPlazaPresenter() { + + } + + public Single loadWeeklyRankData() { + return FamilyModel.Instance().loadFamilyRankingList( + RespFamilyRankList.TYPE_THIS_WEEK, + String.valueOf(Constants.PAGE_START), + String.valueOf(6) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySearchPresent.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySearchPresent.java new file mode 100644 index 000000000..444363022 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySearchPresent.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.family.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySearchView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.response.familyPlaza.RespFamily; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/5/24 + */ + +public class FamilySearchPresent extends BaseMvpPresenter { + + private String searchStr = null; + + private int page = Constants.PAGE_START; + private boolean isLoading = false; + + public Single> search(String str) { + this.searchStr = str; + return loadData(Constants.PAGE_START); + } + + public Single> loadMoreData(){ + return loadData(this.page); + } + + + private Single> loadData(int targetPage){ + if (isLoading){ + return Single.error(new Throwable("加载中,请稍后...")); + } + this.page = targetPage; + isLoading = true; + return FamilyModel.Instance().searchFamilyInfos( + this.searchStr, + page + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(RespFamily response) throws Exception { + isLoading = false; + page++; + return Single.just(response.getFamilys()); + } + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + isLoading = false; + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySelectFriendPresenter.java b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySelectFriendPresenter.java new file mode 100644 index 000000000..7b2c588e0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/presenter/FamilySelectFriendPresenter.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.family.presenter; + + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySelectFriendActivityView; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public class FamilySelectFriendPresenter extends BaseMvpPresenter { +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyCurrencyActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyCurrencyActivity.java new file mode 100644 index 000000000..47daf845c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyCurrencyActivity.java @@ -0,0 +1,321 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.StyleSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.jay.widget.StickyHeadersLinearLayoutManager; +import com.jzxiang.pickerview.TimePickerDialog; +import com.jzxiang.pickerview.data.Type; +import com.jzxiang.pickerview.listener.OnDateSetListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyCurrencyView; +import com.yizhuan.erban.family.view.adapter.FamilyCurrencyBillAdapter; +import com.yizhuan.erban.family.view.dialog.FamilyContributionDialog; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.FamilyMoneyManagementInfo; +import com.yizhuan.erban.family.presenter.FamilyCurrencyPresenter; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyCurrencyPresenter.class) +public class FamilyCurrencyActivity extends BaseMvpActivity + implements IFamilyCurrencyView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener, OnDateSetListener { + + private TextView tvFamilyCurrencyLabel; + private TextView tvFamilyCurrencyBalance; + private ImageView ivFamilyCurrencyHelp; + private TextView tvAction; + private TextView tvFamilyCurrencyIncome; + private TextView tvFamilyCurrencyExpenditure; + private LinearLayout llSearch; + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView rvFamilyCurrency; + private FamilyCurrencyBillAdapter adapter; + + protected TimePickerDialog.Builder mDialogYearMonthDayBuild; + + private String selectDate; + + public static void start(Context context) { + Intent intent = new Intent(context, FamilyCurrencyActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_currency); + initTitleBar(""); + + + View header = LayoutInflater.from(this).inflate(R.layout.header_famiy_currency_bill,null,false); + tvFamilyCurrencyLabel = (TextView) header.findViewById(R.id.tv_family_currency_label); + tvFamilyCurrencyBalance = (TextView) header.findViewById(R.id.tv_family_currency_balance); + tvAction = (TextView) header.findViewById(R.id.tv_action); + tvFamilyCurrencyIncome = (TextView) header.findViewById(R.id.tv_family_currency_income); + tvFamilyCurrencyExpenditure = (TextView) header.findViewById(R.id.tv_family_currency_expenditure); + llSearch = (LinearLayout) header.findViewById(R.id.ll_search); + ivFamilyCurrencyHelp = (ImageView) header.findViewById(R.id.iv_family_currency_help); + + + swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); + swipeRefresh.setOnRefreshListener(this); + + rvFamilyCurrency = (RecyclerView) findViewById(R.id.rv_family_currency); + rvFamilyCurrency.setItemAnimator(null); + rvFamilyCurrency.setLayoutManager(new StickyHeadersLinearLayoutManager(this,LinearLayoutManager.VERTICAL, false)); + adapter = new FamilyCurrencyBillAdapter(this,null); + adapter.addHeaderView(header); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, rvFamilyCurrency); + adapter.setOnDateSelectListener(new FamilyCurrencyBillAdapter.OnDateSelectListener() { + @Override + public void onDateSelect() { + mDialogYearMonthDayBuild.build().show(getSupportFragmentManager(), "year_month"); + } + }); + rvFamilyCurrency.setAdapter(adapter); + + mDialogYearMonthDayBuild = new TimePickerDialog.Builder() + .setType(Type.YEAR_MONTH) + .setTitleStringId("日期选择") + .setThemeColor(getResources().getColor(R.color.line_background)) + .setWheelItemTextNormalColor(getResources().getColor(R.color + .timetimepicker_default_text_color)) + .setWheelItemTextSelectorColor(getResources().getColor(R.color.black)) + .setCallBack(this); + + this.selectDate = String.valueOf(System.currentTimeMillis()); + } + + @Override + public void onDateSet(TimePickerDialog timePickerView, long millseconds) { + this.selectDate = String.valueOf(millseconds); + getMvpPresenter().onRefreshRecordList(selectDate); + } + + @Override + protected void onResume() { + super.onResume(); + if (null == getMvpPresenter().getFamilyMoneyManagementInfo()){ + swipeRefresh.setRefreshing(true); + getMvpPresenter().loadData().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FamilyMoneyManagementInfo familyMoneyManagementInfo) { + showCard(familyMoneyManagementInfo); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + getMvpPresenter().onRefreshRecordList(selectDate); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDialogYearMonthDayBuild != null) { + mDialogYearMonthDayBuild.setCallBack(null); + mDialogYearMonthDayBuild = null; + } + } + + /** + * 显示头部卡片 + * @param familyMoneyManagementInfo + */ + private void showCard(FamilyMoneyManagementInfo familyMoneyManagementInfo) { + + String moneyName = familyMoneyManagementInfo.getMoneyName(); + String incomeStr = FormatUtils.formatToShortDown(familyMoneyManagementInfo.getIncomeAndCost().getIncome()); + String expendStr = FormatUtils.formatToShortDown(familyMoneyManagementInfo.getIncomeAndCost().getCost()); + StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); + + tvFamilyCurrencyLabel.setText(String.format( + getString(R.string.family_currency_balance_label), + moneyName + )); + + + + SpannableString incomeSpan = new SpannableString(incomeStr + moneyName); + incomeSpan.setSpan(boldSpan,0,incomeStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + tvFamilyCurrencyIncome.setText(incomeSpan); + + SpannableString expendSpan = new SpannableString(expendStr + moneyName); + expendSpan.setSpan(boldSpan,0,expendStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + tvFamilyCurrencyExpenditure.setText(expendSpan); + + tvFamilyCurrencyBalance.setText(FormatUtils.formatToShortDown(familyMoneyManagementInfo.getTotalAmount())); + + if (familyMoneyManagementInfo.getPosition() == FamilyMemberInfo.LEVEL_PATRIARCH){ + mTitleBar.setTitle(R.string.family_currency); + llSearch.setVisibility(View.VISIBLE); + llSearch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FamilyMemberSearchActivity.start(FamilyCurrencyActivity.this,FamilyMemberListActivity.TYPE_CHECK_MEMBER_CURRENCY); + } + }); + ivFamilyCurrencyHelp.setVisibility(View.VISIBLE); + ivFamilyCurrencyHelp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CommonWebViewActivity.start(FamilyCurrencyActivity.this, UriProvider.getFamilyCurrencyHelpUrl()); + } + }); + tvAction.setText(String.format( + getString(R.string.family_currency_transfer), + moneyName)); + tvAction.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FamilyMemberListActivity.start(FamilyCurrencyActivity.this,FamilyMemberListActivity.TYPE_SELECT_MEMBER); + } + }); + + }else { + mTitleBar.setTitle(R.string.family_my_currency); + llSearch.setVisibility(View.GONE); + ivFamilyCurrencyHelp.setVisibility(View.INVISIBLE); + tvAction.setText(String.format( + getString(R.string.family_currency_contribution), + moneyName)); + tvAction.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showContributeDialog(); + } + }); + } + } + + + @Override + public void onLoadData(List billItemInfos,int page, int dataSize) { + if (page == Constants.PAGE_START){ + swipeRefresh.setRefreshing(false); + if (!ListUtils.isListEmpty(billItemInfos)) { + adapter.setNewData(billItemInfos); + } + }else { + if (dataSize > 0) { + adapter.loadMoreComplete(); + adapter.notifyDataSetChanged(); + }else { + adapter.loadMoreEnd(true); + } + } + + } + + @Override + public void onRefresh() { + this.selectDate = String.valueOf(System.currentTimeMillis()); + getMvpPresenter().loadData().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FamilyMoneyManagementInfo familyMoneyManagementInfo) { + showCard(familyMoneyManagementInfo); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + getMvpPresenter().onRefreshRecordList(selectDate); + } + + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().onLoadMoreRecordList(selectDate); + } + + + + @Override + public void showErrorView(String message) { + swipeRefresh.setRefreshing(false); + toast(message); + } + + @Override + public void refreshData() { + onRefresh(); + } + + private void showContributeDialog(){ + FamilyContributionDialog dialog = new FamilyContributionDialog(this, getMvpPresenter().getFamilyMoneyManagementInfo()); + dialog.setOnOperationListener(new FamilyContributionDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, double count) { + dialog.dismiss(); + getMvpPresenter().contributionCurrency(count) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("贡献成功"); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + }); + dialog.show(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyGameListActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyGameListActivity.java new file mode 100644 index 000000000..d3050af53 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyGameListActivity.java @@ -0,0 +1,177 @@ +package com.yizhuan.erban.family.view.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyGameListActivityView; +import com.yizhuan.erban.family.presenter.FamilyGameListPresenter; +import com.yizhuan.erban.family.view.adapter.FamilyGameListAdapter; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyGameListPresenter.class) +public class FamilyGameListActivity extends BaseMvpActivity + implements IFamilyGameListActivityView { + + private SmartRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + private FamilyGameListAdapter adapter; + + + public static void start(Activity activity) { + Intent intent = new Intent(activity, FamilyGameListActivity.class); + activity.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_game_list); + + initTitleBar(getString(R.string.family_games)); + + + swipeRefresh = findViewById(R.id.swipe_refresh); + swipeRefresh.setEnableLoadmore(true); + swipeRefresh.setEnableRefresh(true); + swipeRefresh.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(FamilyGameListActivity.this)) { + swipeRefresh.finishLoadmore(); + return; + } + List data = adapter.getData(); + if (ListUtils.isListEmpty(data)) { + swipeRefresh.finishLoadmore(); + return; + } + getMvpPresenter().loadMoreData(); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(FamilyGameListActivity.this)) { + swipeRefresh.finishRefresh(); + return; + } + getMvpPresenter().refreshData(); + } + }); + + recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + recyclerView.setLayoutManager(new GridLayoutManager(this, 4)); + adapter = new FamilyGameListAdapter(this, null); + View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null,false); + adapter.addHeaderView(headerView); + adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + FamilyGameInfo familyGameInfo = (FamilyGameInfo) adapter.getData().get(position); + if (FamilyModel.Instance().getMyFamily() != null) { + FamilyGameInfo gameInfo = (FamilyGameInfo) adapter.getData().get(position); + CommonWebViewActivity.start(FamilyGameListActivity.this, gameInfo.getLink()); + }else { + toast("没在此家族,不能玩该家族的游戏哦~"); + } + } + }); + + recyclerView.setAdapter(adapter); + + requestFamilyInfo(); + } + + /** + * 这里获取家族信息,决定是否能使用游戏 + */ + private void requestFamilyInfo() { + if (FamilyModel.Instance().getMyFamily() == null) { + return; + } + FamilyModel.Instance().loadFamilySimpleInfo( + FamilyModel.Instance().getMyFamily().getFamilyId() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + if (!familyInfo.isOpenGame()){ + toast("已关闭家族游戏."); + finish(); + } + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + getMvpPresenter().refreshData(); + } + + @Override + public void onLoadData(List data, int page) { + if (!ListUtils.isListEmpty(data)) { + hideStatus(); + if (page == Constants.PAGE_START) { + adapter.setNewData(data); + swipeRefresh.finishRefresh(); + } else { + adapter.addData(data); + swipeRefresh.finishLoadmore(); + } + } else { + if (page == Constants.PAGE_START) { + swipeRefresh.finishRefresh(); + showNoData(R.drawable.icon_common_failure, getText(R.string.text_my_master_and_apprentices_no_data)); + } else { + swipeRefresh.finishLoadmore(); + } + } + } + + @Override + public void onLoadDataFail(String error, int page) { + if (page == Constants.PAGE_START) { + swipeRefresh.finishRefresh(); + showNoData(R.drawable.icon_common_failure, getText(R.string.text_my_master_and_apprentices_no_data)); + } else { + swipeRefresh.finishLoadmore(); + } + toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyHomeActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyHomeActivity.java new file mode 100644 index 000000000..dde48f47c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyHomeActivity.java @@ -0,0 +1,801 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.makeramen.roundedimageview.RoundedImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.family.presenter.FamilyHomePresenter; +import com.yizhuan.erban.family.view.adapter.FamilyGamesAdapter; +import com.yizhuan.erban.family.view.adapter.FamilyGroupAdapter; +import com.yizhuan.erban.family.view.adapter.FamilyMemberAdapter; +import com.yizhuan.erban.family.view.dialog.FamilyDisbandDialog; +import com.yizhuan.erban.family.view.dialog.FamilyGuideDialog; +import com.yizhuan.erban.family.view.dialog.FamilyJoinDialog; +import com.yizhuan.erban.family.view.dialog.FamilyMenuDialog; +import com.yizhuan.erban.family.view.fragment.FamilyEmptyFragment; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.home.view.IFamilyHomeActivityView; +import com.yizhuan.erban.team.view.CreateTeamMessageActivity; +import com.yizhuan.erban.team.view.NimTeamMessageActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.erban.ui.widget.recyclerview.layoutmanager.FullyLinearLayoutManager; +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyGroupInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.log.MLog; +import com.yizhuan.xchat_android_library.widget.DrawableCenterTextView; + +import cn.sharesdk.framework.Platform; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyHomePresenter.class) +public class FamilyHomeActivity extends BaseMvpActivity + implements IFamilyHomeActivityView, View.OnClickListener, ShareDialog.OnShareDialogItemClick { + + private final String share_pref_is_first_in_family = "share_pref_is_first_in_family"; + + private ImageView ivFamilyBg; + private RoundedImageView rivCover; + private TextView tvName; + private TextView tvId; + private TextView tvMemberCount; + private DrawableCenterTextView tvFamilyManage; + private LinearLayout llMyFamilyCurrency; + private TextView tvMyFamilyCurrency; + private LinearLayout llFamilyPatriarch; + private CircleImageView civPatriarchAvatar; + private TextView tvPatriarchName; + private LinearLayout llFamilyGames; + private LinearLayout llFamilyMember; + private TextView tvFamilyMemberTitle; + private TextView tvFamilyGroupTitle; + private TextView tvCreateGroup; + private RecyclerView rvFamilyGroupList; + private LinearLayout llNoGroup; + private DrawableCenterTextView rlJoinFamily; + private TextView tvAllMember; + + private FamilyGamesAdapter gamesAdapter; + private FamilyMemberAdapter memberAdapter; + private FamilyGroupAdapter groupAdapter; + + private String familyId; + private ShareDialog shareDialog; + + public static void start(Context activity,String familyId) { + Intent intent = new Intent(activity,FamilyHomeActivity.class); + if(familyId != null){ + Bundle bundle = new Bundle(); + bundle.putString(BundleKeys.KEY_EXTRA_1, familyId); + intent.putExtras(bundle); + } + activity.startActivity(intent); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + familyId = getIntent().getStringExtra(BundleKeys.KEY_EXTRA_1); + if(familyId == null){ + showNoData(); + } else { + showLoading(); + loadFamilyInfo(familyId); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + familyId = getIntent().getStringExtra(BundleKeys.KEY_EXTRA_1); + setContentView(R.layout.activity_family_home); + initTitleBar(""); + + ivFamilyBg = findViewById(R.id.iv_family_bg); + rivCover = findViewById(R.id.riv_cover); + tvName = findViewById(R.id.tv_name); + tvId = findViewById(R.id.tv_id); + tvMemberCount = findViewById(R.id.tv_member_count); + + tvFamilyManage = findViewById(R.id.tv_family_manage); + + llMyFamilyCurrency = findViewById(R.id.ll_my_family_currency); + tvMyFamilyCurrency = findViewById(R.id.tv_my_family_currency); + + llFamilyPatriarch = findViewById(R.id.ll_family_patriarch); + civPatriarchAvatar = findViewById(R.id.civ_patriarch_avatar); + tvPatriarchName = findViewById(R.id.tv_patriarch_name); + + llFamilyGames = findViewById(R.id.ll_family_games); + RecyclerView rvFamilyGameList = findViewById(R.id.rv_family_game_list); + + tvAllMember = findViewById(R.id.tv_all_member); + llFamilyMember = findViewById(R.id.ll_family_member); + tvFamilyMemberTitle = findViewById(R.id.tv_family_member_title); + RecyclerView rvFamilyMemberList = findViewById(R.id.rv_family_member_list); + + tvFamilyGroupTitle = findViewById(R.id.tv_family_group_title); + tvCreateGroup = findViewById(R.id.tv_create_group); + rvFamilyGroupList = findViewById(R.id.rv_family_group_list); + llNoGroup = findViewById(R.id.ll_no_group); + + rlJoinFamily = findViewById(R.id.rl_join_family); + + rvFamilyGameList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rvFamilyGameList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, Utils.dip2px(this, 20), 0, false)); + gamesAdapter = new FamilyGamesAdapter(this, null); + gamesAdapter.setOnItemClickListener((adapter, view, position) -> { + if (getMvpPresenter().getFamilyInfo().getEnterStatus() == FamilyInfo.STATUS_IN_FAMILY) { + FamilyGameInfo gameInfo = (FamilyGameInfo) adapter.getData().get(position); + CommonWebViewActivity.start(FamilyHomeActivity.this, gameInfo.getLink()); + } else { + toast("没在此家族,不能玩该家族的游戏哦~"); + } + }); + rvFamilyGameList.setAdapter(gamesAdapter); + + rvFamilyMemberList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rvFamilyMemberList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, Utils.dip2px(this, 20), 0, false)); + memberAdapter = new FamilyMemberAdapter(this, null); + memberAdapter.setOnItemClickListener((adapter, view, position) -> { + FamilyMemberInfo memberInfo = (FamilyMemberInfo) adapter.getData().get(position); + UserInfoActivity.Companion.start(FamilyHomeActivity.this, memberInfo.getUid()); + }); + rvFamilyMemberList.setAdapter(memberAdapter); + + rvFamilyGroupList.setLayoutManager(new FullyLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + rvFamilyGroupList.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F1F1F1), 0, 1, false)); + groupAdapter = new FamilyGroupAdapter(this, null); + groupAdapter.setActionListener(new FamilyGroupAdapter.ActionListener() { + @Override + public void onJoin(FamilyGroupInfo groupInfo) { + joinFamilyGroup(groupInfo); + } + + @Override + public void onGotoGroup(FamilyGroupInfo groupInfo) { + NimTeamMessageActivity.start(FamilyHomeActivity.this, groupInfo.getTid()); + } + }); + + rvFamilyGroupList.setAdapter(groupAdapter); + + } + + private void showFamilyManage(boolean isShow) { + if (isShow) { + tvFamilyManage.setVisibility(View.VISIBLE); + tvFamilyManage.setOnClickListener(this); + } else { + tvFamilyManage.setVisibility(View.GONE); + tvFamilyManage.setOnClickListener(null); + } + } + + private void showFamilyView(FamilyInfo data) { + if (null == data) { + return; + } + if (!TextUtils.isEmpty(data.getBackground())) { + GlideApp.with(this) + .load(data.getBackground()) + .dontAnimate() + .into(ivFamilyBg); + } else { + GlideApp.with(this) + .load(R.mipmap.bg_family_home) + .dontAnimate() + .into(ivFamilyBg); + } + + GlideApp.with(this) + .load(data.getFamilyIcon()) + .placeholder(R.drawable.default_cover) + .into(rivCover); + tvName.setText(data.getFamilyName()); + tvId.setText(data.getFamilyId()); + tvMemberCount.setText(String.valueOf(data.getMemberCount())); + + if (ListUtils.isListEmpty(data.getGames()) || !data.isOpenGame()) { + llFamilyGames.setVisibility(View.GONE); + } else { + llFamilyGames.setVisibility(View.VISIBLE); + gamesAdapter.setNewData(data.getGames()); + } + + + if (FamilyInfo.STATUS_NOT_IN_FAMILY == data.getEnterStatus()) { + showFamilyManage(false); + + llMyFamilyCurrency.setVisibility(View.GONE); + llFamilyPatriarch.setVisibility(View.VISIBLE); + llFamilyMember.setVisibility(View.GONE); + rlJoinFamily.setVisibility(View.VISIBLE); + rlJoinFamily.setOnClickListener(this); + showTitleBar(data.getFamilyName(), false); + + tvCreateGroup.setVisibility(View.GONE); + + FamilyMemberInfo patriarch = data.getLeader(); + GlideApp.with(this) + .load(patriarch.getIcon()) + .placeholder(R.drawable.default_cover) + .into(civPatriarchAvatar); + + tvPatriarchName.setText(patriarch.getName()); + llFamilyPatriarch.setOnClickListener(v -> + UserInfoActivity.Companion.start(FamilyHomeActivity.this, patriarch.getUid()) + ); + + } else { + + llMyFamilyCurrency.setVisibility(View.VISIBLE); + llMyFamilyCurrency.setOnClickListener(this); + llFamilyPatriarch.setVisibility(View.GONE); + llFamilyMember.setVisibility(View.VISIBLE); + tvAllMember.setOnClickListener(this); + rlJoinFamily.setVisibility(View.GONE); + + showTitleBar(getString(R.string.family_mine), true); + + if (data.getPosition() == FamilyInfo.LEVEL_PATRIARCH) { + showFamilyManage(true); + tvCreateGroup.setVisibility(View.VISIBLE); + tvCreateGroup.setOnClickListener(this); + showFamilyGuide(); + + } else { + showFamilyManage(false); + tvCreateGroup.setVisibility(View.GONE); + tvCreateGroup.setOnClickListener(null); + } + + if (data.isOpenMoney()) { + llMyFamilyCurrency.setVisibility(View.VISIBLE); + tvMyFamilyCurrency.setText(String.format( + getResources().getString(R.string.family_currency_count), + FormatUtils.formatToShortDown(data.getFamilyMoney()), + data.getMoneyName())); + } else { + llMyFamilyCurrency.setVisibility(View.GONE); + } + + tvFamilyMemberTitle.setText(String.format( + getResources().getString(R.string.family_member_title), + String.valueOf(data.getMemberCount()) + )); + memberAdapter.setNewData(data.getMembers()); + + } + + tvFamilyGroupTitle.setText(String.format( + getResources().getString(R.string.family_group_title), + String.valueOf(data.getGroups().size()) + )); + + if (!ListUtils.isListEmpty(data.getGroups())) { + llNoGroup.setVisibility(View.GONE); + rvFamilyGroupList.setVisibility(View.VISIBLE); + groupAdapter.setNewData(data.getGroups()); + } else { + llNoGroup.setVisibility(View.VISIBLE); + rvFamilyGroupList.setVisibility(View.GONE); + } + + } + + private void showTitleBar(String title, boolean isMore) { + mTitleBar.setTitle(title); + mTitleBar.removeAllActions(); + + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_family_share) { + @Override + public void performAction(View view) { + shareDialog = new ShareDialog(FamilyHomeActivity.this); + shareDialog.setOnShareDialogItemClick(FamilyHomeActivity.this); + shareDialog.show(); + } + }); + + if (isMore) + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_family_more) { + @Override + public void performAction(View view) { + showMenuDialog(view); + } + }); + } + + private void showMenuDialog(View view) { + FamilyMenuDialog dialog = new FamilyMenuDialog(this, getMvpPresenter().getFamilyInfo(), view); + dialog.setOnMenuClickListener(new FamilyMenuDialog.OnMenuClickListener() { + @Override + public void onExitFamily(DialogInterface dialog, FamilyInfo familyInfo) { + dialog.dismiss(); + getDialogManager().showOkCancelWithTitleDialog(new String[]{"退出家族后您的", "家族币将无法使用", "重新加入即可还原,你真的要退出吗?"}, + () -> getMvpPresenter().exitFamily().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("退出家族成功."); + finish(); + } + + @Override + public void onError(Throwable e) { +// Toast.makeText(FamilyHomeActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + })); + } + + @Override + public void onDisbandFamily(DialogInterface dialog, FamilyInfo familyInfo) { //解散家族 + dialog.dismiss(); + FamilyDisbandDialog disbandFamilyDialog = new FamilyDisbandDialog(FamilyHomeActivity.this); + disbandFamilyDialog.show(); + } + + @Override + public void onInviteFriends(DialogInterface dialog, FamilyInfo familyInfo) { + FamilySelectFriendActivity.start(FamilyHomeActivity.this, (activity, uid) -> + getMvpPresenter().inviteFriendToFamily(uid) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast("邀请成功."); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + })); + dialog.dismiss(); + } + }); + dialog.show(); + } + + @Override + protected void onResume() { + super.onResume(); + if(familyId == null){ + showNoData(); + } else { + showLoading(); + loadFamilyInfo(familyId); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SelectFriendActivity.CODE_REQUEST_TO_SHARE_FAMILY && + resultCode == RESULT_OK) { + String targetUid = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_UID); + String nick = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_NAME); + int sessionType = data.getIntExtra(SelectFriendActivity.EXTRA_SESSION_TYPE, SessionType.P2P); + IMNetEaseManager.get().sendSharingFamilyMessage(sessionType, targetUid, getMvpPresenter().getFamilyInfo()); + } + } + + @Override + public void onLoadData(FamilyInfo data) { + hideStatus(); + showFamilyView(data); + } + + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + + FamilyEmptyFragment fragment = FamilyEmptyFragment.newInstance(0 - mTitleBar.getmHeight()); + fragment.setOnClickListener(v -> FamilyPlazaActivity.start(FamilyHomeActivity.this)); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showErrorView(String message) { + toast(message); + finish(); + } + + @Override + public void reloadMyFamilyInfo(String familyId) { + loadFamilyInfo(familyId); + } + + @Override + public void close() { + finish(); + } + + private void loadFamilyInfo(String familyId) { + getMvpPresenter().loadData(familyId).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + mTitleBar.setVisibility(View.VISIBLE); + onLoadData(familyInfo); + } + + @Override + public void onError(Throwable e) { + hideStatus(); + showErrorView(e.getMessage()); + } + }); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvFamilyManage.getId()) { + FamilyManageActivity.start(this); + } else if (id == llMyFamilyCurrency.getId()) { + FamilyCurrencyActivity.start(this); + } else if (id == tvAllMember.getId()) { + FamilyMemberListActivity.start(this, FamilyMemberListActivity.TYPE_SHOW_MEMBER); + } else if (id == tvCreateGroup.getId()) { + //去创建群组 + CreateTeamMessageActivity.start(this); + } else if (id == rlJoinFamily.getId()) { + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.JOIN_FAMILY_CLICK, "加入家族", null); + + joinFamily(getMvpPresenter().getFamilyInfo()); + } + } + + private void joinFamily(FamilyInfo familyInfo) { + if (null != FamilyModel.Instance().getMyFamily()) { + toast("需要退出当前家族才可以加入!"); + return; + } + if (familyInfo.getVerifyType() == FamilyInfo.VERIFY_ON) { + showJoinFamilyDialog(getMvpPresenter().getFamilyInfo()); + } else { + getMvpPresenter().joinFamily(null) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("加入成功."); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + } + + /** + * 加入家族验证弹框 + */ + private void showJoinFamilyDialog(FamilyInfo familyInfo) { + FamilyJoinDialog dialog = new FamilyJoinDialog(this); + String str = String.format(getResources().getString(R.string.family_join_tip), + "\"" + familyInfo.getFamilyName() + "\""); + SpannableString spannableString = new SpannableString(str); + StyleSpan styleSpan = new StyleSpan(Typeface.BOLD); + spannableString.setSpan(styleSpan, str.indexOf("\""), str.lastIndexOf("\"") + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + dialog.setTipMessage(spannableString); + dialog.setDefaultVerifyMessage(getResources().getString(R.string.family_join_hint)); + dialog.setOnOperationListener(new FamilyJoinDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, String str) { + dialog.dismiss(); + getMvpPresenter().joinFamily(str) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("申请成功."); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + }); + dialog.show(); + } + + private void joinFamilyGroup(FamilyGroupInfo groupInfo) { + if (getMvpPresenter().getFamilyInfo().getEnterStatus() == FamilyInfo.STATUS_IN_FAMILY) { + if (groupInfo.isVerify()) { + showInFamilyJoinDialog(groupInfo); + } else { + getMvpPresenter().joinFamilyGroup( + String.valueOf(groupInfo.getId()), + "" + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("加入群成功."); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + + } else if (getMvpPresenter().getFamilyInfo().getEnterStatus() == FamilyInfo.STATUS_NOT_IN_FAMILY) { + if (null != FamilyModel.Instance().getMyFamily()) { + toast("需要退出当前家族才可以加入!"); + return; + } + if (getMvpPresenter().getFamilyInfo().getVerifyType() == FamilyInfo.VERIFY_ON || groupInfo.isVerify()) { + //凡是有一个需要验证,弹出验证dailog + showNotInFamilyJoinDialog(groupInfo); + } else { + //都不需要验证的情况 直接进群 + getMvpPresenter().joinFamilyGroup( + String.valueOf(groupInfo.getId()), + null + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("加入群成功."); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + + } + + } + + /** + * 在家族中加入需要验证的群组 + */ + private void showInFamilyJoinDialog(FamilyGroupInfo groupInfo) { + FamilyJoinDialog dialog = new FamilyJoinDialog(this); + String str = String.format(getResources().getString(R.string.family_join_tip), + "\"" + groupInfo.getName() + "\""); + SpannableString spannableString = new SpannableString(str); + StyleSpan styleSpan = new StyleSpan(Typeface.BOLD); + spannableString.setSpan(styleSpan, str.indexOf("\""), str.lastIndexOf("\"") + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + dialog.setTipMessage(spannableString); + dialog.setDefaultVerifyMessage(getResources().getString(R.string.family_group_join_hint)); + dialog.setOnOperationListener(new FamilyJoinDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, String str) { + dialog.dismiss(); + getMvpPresenter().joinFamilyGroup( + String.valueOf(groupInfo.getId()), + str + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("加入群申请成功。"); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + }); + dialog.show(); + } + + /** + * 不在家族中加入家族的群 + */ + private void showNotInFamilyJoinDialog(FamilyGroupInfo groupInfo) { + FamilyJoinDialog dialog = new FamilyJoinDialog(this); + String str = String.format(getResources().getString(R.string.family_group_join_tip_1), + "\"" + getMvpPresenter().getFamilyInfo().getFamilyName() + "\""); + SpannableString spannableString = new SpannableString(str); + StyleSpan styleSpan = new StyleSpan(Typeface.BOLD); + spannableString.setSpan(styleSpan, str.indexOf("\""), str.lastIndexOf("\"") + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + dialog.setTipMessage(spannableString); + dialog.setDefaultVerifyMessage(getResources().getString(R.string.family_group_join_hint)); + + dialog.setOnOperationListener(new FamilyJoinDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, String str) { + dialog.dismiss(); + getMvpPresenter().joinFamilyGroup( + String.valueOf(groupInfo.getId()), + str + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("加入群申请成功"); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + }); + dialog.show(); + + } + + @Override + public void onInAppSharingItemClick() { + if (shareDialog != null && shareDialog.isShowing()) { + shareDialog.dismiss(); + } + SelectFriendActivity.startForSharingFamily(this); + } + + @Override + public void onSharePlatformClick(Platform platform) { + FamilyInfo familyInfo = getMvpPresenter().getFamilyInfo(); + if (familyInfo != null) { + ShareModel.get().shareFamily( + platform, familyInfo.getFamilyId(), + familyInfo.getFamilyIcon(), + familyInfo.getFamilyName() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + } + + private void showFamilyGuide() { + if (!isFirstInFamily()) { + return; + } + + FamilyGuideDialog guideDialog = new FamilyGuideDialog(this); + guideDialog.show(); + + setFirstInFamily(false); + } + + private boolean isFirstInFamily() { +// return (boolean) SharedPreferenceUtils.get(share_pref_is_first_in_family, new Boolean(true)); + return false; + } + + private void setFirstInFamily(boolean firstInFamily) { + SharedPreferenceUtils.put(share_pref_is_first_in_family, new Boolean(firstInFamily)); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyInfoActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyInfoActivity.java new file mode 100644 index 000000000..504f96eee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyInfoActivity.java @@ -0,0 +1,226 @@ +package com.yizhuan.erban.family.view.activity; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.jph.takephoto.model.TResult; +import com.makeramen.roundedimageview.RoundedImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.ErbanTakePhotoActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyInfoView; +import com.yizhuan.erban.family.presenter.FamilyInfoPresenter; +import com.yizhuan.erban.family.view.dialog.FamilyDisbandDialog; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyInfoPresenter.class) +public class FamilyInfoActivity extends BaseMvpActivity + implements IFamilyInfoView, View.OnClickListener,ErbanTakePhotoActivity.TakePhotoCallBack { + + private LinearLayout llFamilyAvatar; + private RoundedImageView rivFamilyCover; + private LinearLayout llFamilyName; + private TextView tvFamilyName; + private TextView tvFamilyDisband; + private IOSSwitchView svIdentityCheck; + + private FamilyInfo familyInfo; + + public static void start(Activity activity) { + Intent intent = new Intent(activity, FamilyInfoActivity.class); + activity.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_info); + initTitleBar(getString(R.string.family_info)); + + + llFamilyAvatar = (LinearLayout) findViewById(R.id.ll_family_avatar); + rivFamilyCover = (RoundedImageView) findViewById(R.id.riv_family_cover); + llFamilyName = (LinearLayout) findViewById(R.id.ll_family_name); + tvFamilyName = (TextView) findViewById(R.id.tv_family_name); + tvFamilyDisband = (TextView) findViewById(R.id.tv_family_disband); + svIdentityCheck = (IOSSwitchView) findViewById(R.id.sv_identity_check); + + + llFamilyAvatar.setOnClickListener(this); + llFamilyName.setOnClickListener(this); + tvFamilyDisband.setOnClickListener(this); + svIdentityCheck.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + svIdentityCheck.setEnabled(false); + getMvpPresenter().changeVerifyStatus(isOn).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("修改成功"); + svIdentityCheck.setEnabled(true); + } + + @Override + public void onError(Throwable e) { + svIdentityCheck.setEnabled(true); + toast(e.getMessage()); + svIdentityCheck.setOn(!isOn,true,false); + } + }); + } + }); + + initData(); + + } + + private void initData(){ + familyInfo = FamilyModel.Instance().getMyFamily(); + if (familyInfo == null) { + toast("没有家族信息!"); + return; + } + GlideApp.with(this) + .load(familyInfo.getFamilyIcon()) + .dontAnimate() + .into(rivFamilyCover); + + tvFamilyName.setText(familyInfo.getFamilyName()); + if (FamilyInfo.VERIFY_ON == familyInfo.getVerifyType()){ + svIdentityCheck.setOn(true,false); + }else { + svIdentityCheck.setOn(false,false); + } + } + + + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == llFamilyAvatar.getId()){ + ButtonItem buttonItem = new ButtonItem("拍照上传", ()->{ + ErbanTakePhotoActivity.startToTakePhoto(this,this); + }); + ButtonItem buttonItem1 = new ButtonItem("本地相册", () -> { + ErbanTakePhotoActivity.startToSelectPhoto(this,this); + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, "取消", false); + + }else if (id == llFamilyName.getId()){ + FamilyTextInputActivity.start(this, familyInfo.getFamilyName(), new FamilyTextInputActivity.CallBack() { + @Override + public void onModify(String str) { + getMvpPresenter().changeFamilyName(str).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + tvFamilyName.setText(str); + toast("修改成功"); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + }); + + }else if (id == tvFamilyDisband.getId()){ + FamilyDisbandDialog disbandFamilyDialog = new FamilyDisbandDialog(this); + disbandFamilyDialog.show(); + } + } + + /********************************************* 照相上传逻辑 ******************************************************/ + + public void onUpload(String url) { + getDialogManager().dismissDialog(); + GlideApp.with(FamilyInfoActivity.this) + .load(url) + .error(R.drawable.default_user_head) + .into(rivFamilyCover); + + + getMvpPresenter().changeFamilyAvatar(url).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("修改成功"); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(FamilyInfoActivity.this, "请稍后"); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + @Override + public void takeCancel() { + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyListActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyListActivity.java new file mode 100644 index 000000000..fa7c384d5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyListActivity.java @@ -0,0 +1,139 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySearchView; +import com.yizhuan.erban.family.presenter.FamilyListPresenter; +import com.yizhuan.erban.family.view.adapter.FamilyWeeklyRankBoardAdapter; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyListPresenter.class) +public class FamilyListActivity extends BaseMvpActivity + implements IFamilySearchView,SwipeRefreshLayout.OnRefreshListener { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + private FamilyWeeklyRankBoardAdapter adapter; + + public static void start(Context context) { + Intent intent = new Intent(context,FamilyListActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_list); + initTitleBar(getString(R.string.family_weekly_rank_board)); + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_family_list_search) { + @Override + public void performAction(View view) { + FamilySearchActivity.start(FamilyListActivity.this); + } + }); + + swipeRefresh = findViewById(R.id.swipe_refresh); + swipeRefresh.setOnRefreshListener(this); + + recyclerView = findViewById(R.id.recycler_view); + recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false)); + if (recyclerView.getItemDecorationCount() == 0) { + int marginStart = SizeUtils.dp2px(this, 16); + recyclerView.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F1F1F1), + 0,1, false, marginStart, marginStart)); + } + adapter = new FamilyWeeklyRankBoardAdapter(this, null); +// View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null,false); +// adapter.addHeaderView(headerView); + adapter.setOnItemClickListener((adapter1, view, position) -> { + RankingFamilyInfo familyInfo = adapter.getData().get(position); + FamilyHomeActivity.start(FamilyListActivity.this,familyInfo.getId()); + }); + adapter.setEnableLoadMore(false); + + recyclerView.setAdapter(adapter); + + } + + @Override + protected void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())){ + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List familyInfoList) { + swipeRefresh.setRefreshing(false); + if (familyInfoList != null && familyInfoList.size() > 0) { + hideStatus(); + adapter.setNewData(familyInfoList); + adapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + + @Override + public void onError(Throwable e) { + swipeRefresh.setRefreshing(false); + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + } + + @Override + public void onRefresh() { + getMvpPresenter().refreshData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List familyInfoList) { + swipeRefresh.setRefreshing(false); + if (familyInfoList != null && familyInfoList.size() > 0) { + hideStatus(); + adapter.setNewData(familyInfoList); + adapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + + @Override + public void onError(Throwable e) { + swipeRefresh.setRefreshing(false); + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyManageActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyManageActivity.java new file mode 100644 index 000000000..c1e805449 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyManageActivity.java @@ -0,0 +1,91 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyManageActivityView; +import com.yizhuan.erban.family.view.adapter.FamilyManageAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.family.bean.FamilyManageItemInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.erban.family.presenter.FamilyManagePresenter; + +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(FamilyManagePresenter.class) +public class FamilyManageActivity extends BaseMvpActivity + implements IFamilyManageActivityView, BaseQuickAdapter.OnItemClickListener{ + + private RecyclerView rvFamilyManage; + private FamilyManageAdapter familyManageAdapter; + + public static void start(Context context) { + Intent intent = new Intent(context,FamilyManageActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_manage_activty); + initTitleBar(getString(R.string.family_manage_title)); + + rvFamilyManage = (RecyclerView) findViewById(R.id.rv_family_manage); + rvFamilyManage.setLayoutManager(new LinearLayoutManager(this)); + //rvFamilyManage.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F5F5F5),1,1,false)); + + List manageItemInfos = new ArrayList<>(); + + if (FamilyModel.Instance().getMyFamily().isOpenMoney()) { + FamilyManageItemInfo itemInfo = new FamilyManageItemInfo(); + itemInfo.setId(FamilyManageItemInfo.ID_FAMILY_MANAGE_CURRENCY); + itemInfo.setName("家族币管理"); + itemInfo.setImg(R.drawable.ic_family_manage_currency); + manageItemInfos.add(itemInfo); + } + + FamilyManageItemInfo itemInfo2 = new FamilyManageItemInfo(); + itemInfo2.setId(FamilyManageItemInfo.ID_FAMILY_MANAGE_MEMBER); + itemInfo2.setName("成员管理"); + itemInfo2.setImg(R.drawable.ic_family_manage_member); + manageItemInfos.add(itemInfo2); + + FamilyManageItemInfo itemInfo3 = new FamilyManageItemInfo(); + itemInfo3.setId(FamilyManageItemInfo.ID_FAMILY_MANAGE_INFO); + itemInfo3.setName("家族信息"); + itemInfo3.setImg(R.drawable.ic_family_manage_info); + manageItemInfos.add(itemInfo3); + + familyManageAdapter = new FamilyManageAdapter(manageItemInfos); + familyManageAdapter.setOnItemClickListener(this); + rvFamilyManage.setAdapter(familyManageAdapter); + + } + + + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + FamilyManageItemInfo itemInfo = (FamilyManageItemInfo) adapter.getData().get(position); + if (FamilyManageItemInfo.ID_FAMILY_MANAGE_CURRENCY == itemInfo.getId()){ + FamilyCurrencyActivity.start(this); + + }else if (FamilyManageItemInfo.ID_FAMILY_MANAGE_MEMBER == itemInfo.getId()){ + FamilyMemberListActivity.start(this,FamilyMemberListActivity.TYPE_REMOVE_MEMBER); + + }else if (FamilyManageItemInfo.ID_FAMILY_MANAGE_INFO == itemInfo.getId()){ + FamilyInfoActivity.start(this); + + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberCurrencyActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberCurrencyActivity.java new file mode 100644 index 000000000..5c421adc5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberCurrencyActivity.java @@ -0,0 +1,135 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.jay.widget.StickyHeadersLinearLayoutManager; +import com.jzxiang.pickerview.TimePickerDialog; +import com.jzxiang.pickerview.data.Type; +import com.jzxiang.pickerview.listener.OnDateSetListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyCurrencyView; +import com.yizhuan.erban.family.view.adapter.FamilyCurrencyBillAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; +import com.yizhuan.erban.family.presenter.FamilyMemberCurrencyPresenter; + +import java.util.List; + +@CreatePresenter(FamilyMemberCurrencyPresenter.class) +public class FamilyMemberCurrencyActivity extends BaseMvpActivity + implements IFamilyCurrencyView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener, OnDateSetListener { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView rvFamilyCurrency; + private FamilyCurrencyBillAdapter adapter; + + protected TimePickerDialog.Builder mDialogYearMonthDayBuild; + + private String selectDate; + private long uid; + + public static void start(Context context, long uid) { + Intent intent = new Intent(context, FamilyMemberCurrencyActivity.class); + intent.putExtra(BundleKeys.KEY_EXTRA_1, uid); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + uid = getIntent().getLongExtra(BundleKeys.KEY_EXTRA_1,0); + setContentView(R.layout.activity_family_member_currency); + + initTitleBar(getString(R.string.family_currency)); + + swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); + swipeRefresh.setOnRefreshListener(this); + + rvFamilyCurrency = (RecyclerView) findViewById(R.id.rv_family_currency); + rvFamilyCurrency.setItemAnimator(null); + rvFamilyCurrency.setLayoutManager(new StickyHeadersLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + adapter = new FamilyCurrencyBillAdapter(this,null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, rvFamilyCurrency); + adapter.setOnDateSelectListener(new FamilyCurrencyBillAdapter.OnDateSelectListener() { + @Override + public void onDateSelect() { + mDialogYearMonthDayBuild.build().show(getSupportFragmentManager(), "year_month"); + } + }); + rvFamilyCurrency.setAdapter(adapter); + + mDialogYearMonthDayBuild = new TimePickerDialog.Builder() + .setType(Type.YEAR_MONTH) + .setTitleStringId("日期选择") + .setThemeColor(getResources().getColor(R.color.line_background)) + .setWheelItemTextNormalColor(getResources().getColor(R.color + .timetimepicker_default_text_color)) + .setWheelItemTextSelectorColor(getResources().getColor(R.color.black)) + .setCallBack(this); + + this.selectDate = String.valueOf(System.currentTimeMillis()); + } + + @Override + protected void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(getMvpPresenter().getBillItemInfos())){ + swipeRefresh.setRefreshing(true); + getMvpPresenter().onRefreshRecordList(selectDate, String.valueOf(uid)); + + } + } + + @Override + public void onRefresh() { + this.selectDate = String.valueOf(System.currentTimeMillis()); + getMvpPresenter().onRefreshRecordList(selectDate, String.valueOf(uid)); + } + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().onLoadMoreRecordList(selectDate, String.valueOf(uid)); + } + + @Override + public void onDateSet(TimePickerDialog timePickerView, long millseconds) { + this.selectDate = String.valueOf(millseconds); + getMvpPresenter().onRefreshRecordList(selectDate, String.valueOf(uid)); + } + + @Override + public void onLoadData(List billItemInfos, int page, int dataSize) { + if (page == Constants.PAGE_START){ + swipeRefresh.setRefreshing(false); + adapter.setNewData(billItemInfos); + }else { + if (dataSize > 0) { + adapter.loadMoreComplete(); + adapter.notifyDataSetChanged(); + }else { + adapter.loadMoreEnd(true); + } + } + } + + @Override + public void showErrorView(String message) { + toast(message); + } + + @Override + public void refreshData() { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberListActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberListActivity.java new file mode 100644 index 000000000..04b6dc589 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberListActivity.java @@ -0,0 +1,291 @@ +package com.yizhuan.erban.family.view.activity; + +import android.app.Activity; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyMemberListView; +import com.yizhuan.erban.family.view.adapter.FamilyMemberListAdapter; +import com.yizhuan.erban.family.view.dialog.FamilyRemoveMemberDialog; +import com.yizhuan.erban.family.view.dialog.FamilyTransferDialog; +import com.yizhuan.erban.team.view.TeamMemberListActivity; +import com.yizhuan.erban.team.view.TeamMemberSearchListActivity; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.bean.response.memberList.RespFamilymember; +import com.yizhuan.erban.family.presenter.FamilyMemberListPresenter; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyMemberListPresenter.class) +public class FamilyMemberListActivity extends BaseMvpActivity + implements IFamilyMemberListView, View.OnClickListener, BaseQuickAdapter.RequestLoadMoreListener, SwipeRefreshLayout.OnRefreshListener { + + public static final int TYPE_SHOW_MEMBER = 1;// 查看成员方式 + public static final int TYPE_SELECT_MEMBER = 2;//选择成员方式 + public static final int TYPE_REMOVE_MEMBER = 3;//移除成员方式 + public static final int TYPE_CHECK_MEMBER_CURRENCY = 4;//查看家族成员家族币记录 + + private LinearLayout llSearch; + private TextView tvMemberCount; + private RecyclerView rvMember; + private FamilyMemberListAdapter familyMemberListAdapter; + private int optType = TYPE_SHOW_MEMBER; + private SwipeRefreshLayout swipeRefresh; + + private TitleBar.Action searchAction = new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_family_search; + } + + @Override + public void performAction(View view) { + FamilyMemberSearchActivity.start(FamilyMemberListActivity.this, optType); + } + }; + public static void start(Activity activity, int optType) { + Intent intent = new Intent(activity, FamilyMemberListActivity.class); + Bundle b = new Bundle(); + b.putInt(BundleKeys.KEY_EXTRA_1, optType); + intent.putExtras(b); + activity.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + optType = getIntent().getIntExtra(BundleKeys.KEY_EXTRA_1, TYPE_SHOW_MEMBER); + setContentView(R.layout.activity_family_list_member); + + initTitleBar(getString(R.string.family_member_list)); + + llSearch = (LinearLayout) findViewById(R.id.ll_search); + tvMemberCount = (TextView) findViewById(R.id.tv_member_count); + rvMember = (RecyclerView) findViewById(R.id.rv_member); + + + swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); + swipeRefresh.setOnRefreshListener(this); + rvMember.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + familyMemberListAdapter = new FamilyMemberListAdapter(this, null, optType); + familyMemberListAdapter.setEnableLoadMore(true); + familyMemberListAdapter.setOnLoadMoreListener(this, rvMember); + familyMemberListAdapter.setActionListener(new FamilyMemberListAdapter.ActionListener() { + @Override + public void onRemoveMember(FamilyMemberInfo familyMemberInfo) { + //移除成员 + showRemoveFamilyMemberDialog(familyMemberInfo); + + } + + @Override + public void onTransferCurrency(FamilyMemberInfo familyMemberInfo) { + showTransferDialog(familyMemberInfo); + } + + @Override + public void onClickAvatar(FamilyMemberInfo item) { + UserInfoActivity.Companion.start(FamilyMemberListActivity.this, item.getUid()); + } + + @Override + public void onCheckMemberCurrency(FamilyMemberInfo item) { + + } + }); + rvMember.setAdapter(familyMemberListAdapter); + + mTitleBar.addAction(searchAction); + llSearch.setOnClickListener(this); + + } + + @Override + protected void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(this.familyMemberListAdapter.getData())) { + refreshData(); + } + + } + + private void refreshData() { + showLoading(); + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(RespFamilymember respFamilymember) { + swipeRefresh.setRefreshing(false); + tvMemberCount.setText(String.format( + getString(R.string.family_member_label2), + String.valueOf(respFamilymember.getCount()) + )); + + onLoadData(respFamilymember.getMembers()); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + swipeRefresh.setRefreshing(false); + showNetworkErr(); + } + } + ); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == llSearch.getId()) { + FamilyMemberSearchActivity.start(this, optType); + } + } + + @Override + public void onLoadData(List memberInfoList) { + if (!ListUtils.isListEmpty(memberInfoList)) { + hideStatus(); + familyMemberListAdapter.setNewData(memberInfoList); + familyMemberListAdapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + refreshData(); + } + + @Override + public void reloadFamilyMember() { + refreshData(); + } + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(RespFamilymember respFamilymember) { + List memberInfos = respFamilymember.getMembers(); + if (!ListUtils.isListEmpty(memberInfos)) { + familyMemberListAdapter.addData(memberInfos); + familyMemberListAdapter.loadMoreComplete(); + } else { + familyMemberListAdapter.loadMoreEnd(true); + } + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + @Override + public void onRefresh() { + refreshData(); + } + + + private void showTransferDialog(FamilyMemberInfo familyMemberInfo) { + FamilyTransferDialog dialog = new FamilyTransferDialog(this, getMvpPresenter().getFamilyInfo(), familyMemberInfo); + dialog.setOnOperationListener(new FamilyTransferDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, FamilyMemberInfo familyMemberInfo, double count) { + dialog.dismiss(); + getMvpPresenter().transferCurrency(familyMemberInfo, count) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(getResources().getString(R.string.family_transfer_currency_success)); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + }); + dialog.show(); + } + + + private void showRemoveFamilyMemberDialog(FamilyMemberInfo familyMemberInfo) { + getDialogManager().showOkCancelWithTitleDialog(new String[]{"移出后该成员", "家族币", "将不可使用,重新加入后可还原,确定将", + familyMemberInfo.getName(), "移除本家族?"}, + () -> getMvpPresenter().removeFamilyMember(familyMemberInfo) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("移除成功"); + refreshData(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + })); + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberSearchActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberSearchActivity.java new file mode 100644 index 000000000..b5c598f0f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyMemberSearchActivity.java @@ -0,0 +1,316 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyMemberSearchView; +import com.yizhuan.erban.family.view.adapter.FamilyMemberListAdapter; +import com.yizhuan.erban.family.view.dialog.FamilyRemoveMemberDialog; +import com.yizhuan.erban.family.view.dialog.FamilyTransferDialog; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.erban.family.presenter.FamilyMemberSearchPresenter; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyMemberSearchPresenter.class) +public class FamilyMemberSearchActivity extends BaseMvpActivity + implements IFamilyMemberSearchView, View.OnClickListener, BaseQuickAdapter.RequestLoadMoreListener { + + private RecyclerView recyclerView; + private FamilyMemberListAdapter searchAdapter; + private EditText searchEdit; + private ImageView ivBack; + private TextView tvSearch; + private ImageView ivClearText; + private int optType; + private String searchStr; + + public static void start(Context context,int optType) { + Intent intent = new Intent(context,FamilyMemberSearchActivity.class); + Bundle b = new Bundle(); + b.putInt(BundleKeys.KEY_EXTRA_1,optType); + intent.putExtras(b); + context.startActivity(intent); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + optType = getIntent().getIntExtra(BundleKeys.KEY_EXTRA_1,FamilyMemberListActivity.TYPE_SHOW_MEMBER); + setContentView(R.layout.activity_family_member_search); + + initView(); + + } + + private void initView() { + recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + searchEdit = (EditText) findViewById(R.id.search_edit); + searchEdit.addTextChangedListener(textWatcher); + searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + searchEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event!=null && event.getKeyCode()== KeyEvent.KEYCODE_ENTER)) { + String str = v.getText().toString(); + if (TextUtils.isEmpty(str)){ +// Toast.makeText(v.getContext(),"请输入搜索内容!",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return true; + } + searchStr = str; + search(str); + hideIME(); + return true; + } + return false; + + } + }); + recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); + if (recyclerView.getItemDecorationCount() == 0) { + recyclerView.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F1F1F1), 0,1, false)); + } + searchAdapter = new FamilyMemberListAdapter(this, null,optType); + View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null,false); + searchAdapter.addHeaderView(headerView); + searchAdapter.setActionListener(new FamilyMemberListAdapter.ActionListener() { + @Override + public void onRemoveMember(FamilyMemberInfo familyMemberInfo) { + showRemoveFamilyMemberDialog(familyMemberInfo); + } + + @Override + public void onTransferCurrency(FamilyMemberInfo familyMemberInfo) { + showTransferDialog(familyMemberInfo); + } + @Override + public void onClickAvatar(FamilyMemberInfo item) { + UserInfoActivity.Companion.start(FamilyMemberSearchActivity.this, item.getUid()); + } + + @Override + public void onCheckMemberCurrency(FamilyMemberInfo item) { + FamilyMemberCurrencyActivity.start(FamilyMemberSearchActivity.this, item.getUid()); + } + }); + //搜索去掉分页 +// searchAdapter.setEnableLoadMore(true); +// searchAdapter.setOnLoadMoreListener(this,recyclerView); + recyclerView.setAdapter(searchAdapter); + + ivBack = (ImageView) findViewById(R.id.iv_back); + ivBack.setOnClickListener(this); + + tvSearch = (TextView) findViewById(R.id.tv_search); + tvSearch.setOnClickListener(this); + + ivClearText = (ImageView) findViewById(R.id.iv_clear_text); + ivClearText.setOnClickListener(this); + ivClearText.setVisibility(View.GONE); + + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + ivClearText.setVisibility(View.GONE); + } else { + ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == ivBack.getId()){ + finish(); + }else if (id == tvSearch.getId()){ + String str = searchEdit.getText().toString(); + if (TextUtils.isEmpty(str)){ +// Toast.makeText(this,"请输入搜索内容!",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return; + } + searchStr = str; + search(str); + hideIME(); + + }else if (id == ivClearText.getId()){ + searchEdit.setText(""); + } + + } + + private void search(String str){ + getMvpPresenter().search(str) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List memberInfos) { + update(memberInfos); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + + @Override + public void update(List memberInfos) { + if (memberInfos != null && memberInfos.size() > 0) { + hideStatus(); + searchAdapter.setNewData(memberInfos); + searchAdapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + + @Override + public void onLoadMoreRequested() { +// getMvpPresenter().loadMoreData() +// .subscribe(new SingleObserver>() { +// @Override +// public void onSubscribe(Disposable d) { +// mCompositeDisposable.add(d); +// } +// +// @Override +// public void onSuccess(List memberInfos) { +// if (!ListUtils.isListEmpty(memberInfos)){ +// searchAdapter.addData(memberInfos); +// searchAdapter.loadMoreComplete(); +// }else { +// searchAdapter.loadMoreEnd(false); +// } +// } +// +// @Override +// public void onError(Throwable e) { +// toast(e.getMessage()); +// } +// }); + } + + + + private void showTransferDialog(FamilyMemberInfo familyMemberInfo) { + FamilyTransferDialog dialog = new FamilyTransferDialog(this, getMvpPresenter().getFamilyInfo(),familyMemberInfo); + dialog.setOnOperationListener(new FamilyTransferDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, FamilyMemberInfo familyMemberInfo, double count) { + dialog.dismiss(); + getMvpPresenter().transferCurrency(familyMemberInfo, count) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(getResources().getString(R.string.family_transfer_currency_success)); + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + }); + dialog.show(); + } + + + private void showRemoveFamilyMemberDialog(FamilyMemberInfo familyMemberInfo) { + FamilyRemoveMemberDialog familyRemoveMemberDialog = new FamilyRemoveMemberDialog(this,familyMemberInfo); + familyRemoveMemberDialog.setOnOperationListener(new FamilyRemoveMemberDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog, FamilyMemberInfo familyMemberInfo) { + dialog.dismiss(); + getMvpPresenter().removeFamilyMember(familyMemberInfo) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + toast("移除成功"); + search(searchStr); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + }); + familyRemoveMemberDialog.show(); + + + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyPlazaActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyPlazaActivity.java new file mode 100644 index 000000000..e4e2f4871 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyPlazaActivity.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyPlazaActivityView; +import com.yizhuan.erban.family.view.adapter.FamilyWeeklyRankBoardAdapter; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.erban.ui.widget.recyclerview.layoutmanager.FullyLinearLayoutManager; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.response.RespFamilyRankList; +import com.yizhuan.erban.family.presenter.FamilyPlazaPresenter; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilyPlazaPresenter.class) +public class FamilyPlazaActivity extends BaseMvpActivity + implements IFamilyPlazaActivityView,View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { + + + private SwipeRefreshLayout srlRefreshContainer; + private LinearLayout llFamilyContainer; + private TextView tvGetMore; + + private FamilyWeeklyRankBoardAdapter familyWeeklyRankBoardAdapter; + + private boolean isFirstLoad = true; + + public static void start(Context context) { + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.FAMILY_FAMILY_SQUARE_CLICK, "家族广场", null); + + Intent intent = new Intent(context,FamilyPlazaActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_plaza); + initTitleBar(getString(R.string.family_plaza)); + + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_family_list_search) { + @Override + public void performAction(View view) { + FamilySearchActivity.start(FamilyPlazaActivity.this); + } + }); + + srlRefreshContainer = findViewById(R.id.srl_refresh_container); + + llFamilyContainer = findViewById(R.id.ll_family_container); + RecyclerView rvList = findViewById(R.id.rv_list); + tvGetMore = findViewById(R.id.tv_get_more); + + srlRefreshContainer.setOnRefreshListener(this); + + rvList.setItemAnimator(null); + rvList.setFocusable(false); + rvList.setLayoutManager(new FullyLinearLayoutManager(this, LinearLayoutManager.VERTICAL,false)); + if (rvList.getItemDecorationCount() == 0) { + int marginStart = SizeUtils.dp2px(this, 16); + rvList.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F1F1F1), + 0,1, false, marginStart, marginStart)); + } + familyWeeklyRankBoardAdapter = new FamilyWeeklyRankBoardAdapter(this, null); + familyWeeklyRankBoardAdapter.setOnItemClickListener((adapter, view, position) -> { + RankingFamilyInfo familyInfo = (RankingFamilyInfo) adapter.getData().get(position); + FamilyHomeActivity.start(FamilyPlazaActivity.this, familyInfo.getId()); + }); + rvList.setAdapter(familyWeeklyRankBoardAdapter); + + tvGetMore.setOnClickListener(this); + + } + + @Override + protected void onResume() { + super.onResume(); + if (isFirstLoad){ + isFirstLoad = false; + srlRefreshContainer.setRefreshing(true); + loadData(); + } + + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvGetMore.getId()) { + FamilyListActivity.start(this); + } + } + + @Override + public void onRefresh() { + loadData(); + } + + private void loadData(){ + getMvpPresenter().loadWeeklyRankData() + .doAfterTerminate(() -> srlRefreshContainer.setRefreshing(false)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(RespFamilyRankList respFamily) { + if (ListUtils.isListEmpty(respFamily.getFamilys())){ + llFamilyContainer.setVisibility(View.GONE); + tvGetMore.setVisibility(View.GONE); + return; + } + llFamilyContainer.setVisibility(View.VISIBLE); + if (respFamily.getCount() <= 6){ + tvGetMore.setVisibility(View.GONE); + } + familyWeeklyRankBoardAdapter.setNewData(respFamily.getFamilys()); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySearchActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySearchActivity.java new file mode 100644 index 000000000..d4336560e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySearchActivity.java @@ -0,0 +1,221 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySearchView; +import com.yizhuan.erban.family.view.adapter.FamilyAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.erban.family.presenter.FamilySearchPresent; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@CreatePresenter(FamilySearchPresent.class) +public class FamilySearchActivity extends BaseMvpActivity + implements IFamilySearchView, View.OnClickListener, BaseQuickAdapter.RequestLoadMoreListener { + + + private RecyclerView recyclerView; + private FamilyAdapter searchAdapter; + private EditText searchEdit; + private ImageView ivBack; + private TextView tvSearch; + private ImageView ivClearText; + + private String searchText; + + public static void start(Context context) { + Intent intent = new Intent(context,FamilySearchActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_search); + + initView(); + } + + + private void initView() { + recyclerView = (RecyclerView) findViewById(R.id.recycler_view); + searchEdit = (EditText) findViewById(R.id.search_edit); + searchEdit.addTextChangedListener(textWatcher); + searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + searchEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event!=null && event.getKeyCode()== KeyEvent.KEYCODE_ENTER)) { + searchText = v.getText().toString(); + if (TextUtils.isEmpty(searchText)){ +// Toast.makeText(v.getContext(),"请输入搜索内容!",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return true; + } + searchFamily(searchText); + hideIME(); + return true; + } + return false; + + } + }); + recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)); + if (recyclerView.getItemDecorationCount() == 0) { + recyclerView.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_F1F1F1), 0,1, false)); + } + searchAdapter = new FamilyAdapter(this, null); + View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null,false); + searchAdapter.addHeaderView(headerView); + searchAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + FamilyInfo familyInfo = (FamilyInfo) adapter.getData().get(position); + FamilyHomeActivity.start(FamilySearchActivity.this,familyInfo.getFamilyId()); + } + }); + //搜索去掉分页 +// searchAdapter.setEnableLoadMore(true); +// searchAdapter.setOnLoadMoreListener(this, recyclerView); + recyclerView.setAdapter(searchAdapter); + + ivBack = (ImageView) findViewById(R.id.iv_back); + ivBack.setOnClickListener(this); + + tvSearch = (TextView) findViewById(R.id.tv_search); + tvSearch.setOnClickListener(this); + + ivClearText = (ImageView) findViewById(R.id.iv_clear_text); + ivClearText.setOnClickListener(this); + ivClearText.setVisibility(View.GONE); + + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + ivClearText.setVisibility(View.GONE); + } else { + ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == ivBack.getId()){ + finish(); + }else if (id == tvSearch.getId()){ + searchText = searchEdit.getText().toString(); + if (TextUtils.isEmpty(searchText)){ +// Toast.makeText(this,"请输入搜索内容!",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return; + } + hideIME(); + searchFamily(searchText); + + }else if (id == ivClearText.getId()){ + searchEdit.setText(""); + } + + } + + @Override + public void onReloadDate() { + super.onReloadDate(); +// searchFamily(searchText); + } + + private void searchFamily(String key){ + showLoading(); + getMvpPresenter().search(key).subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List familyInfoList) { + if (familyInfoList != null && familyInfoList.size() > 0) { + hideStatus(); + searchAdapter.setNewData(familyInfoList); + searchAdapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List familyInfoList) { + if (ListUtils.isListEmpty(familyInfoList)){ + searchAdapter.loadMoreEnd(true); + return; + } + searchAdapter.addData(familyInfoList); + searchAdapter.loadMoreComplete(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + searchAdapter.loadMoreComplete(); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySelectFriendActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySelectFriendActivity.java new file mode 100644 index 000000000..71d8de92d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilySelectFriendActivity.java @@ -0,0 +1,147 @@ +package com.yizhuan.erban.family.view.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.common.ViewPagerAdapter; +import com.yizhuan.erban.family.contract.viewinterface.IFamilySelectFriendActivityView; +import com.yizhuan.erban.family.view.dialog.FamilyInviteConfirmDialog; +import com.yizhuan.erban.family.view.fragment.FamilyAttentionFragment; +import com.yizhuan.erban.family.view.fragment.FamilyFansListFragment; +import com.yizhuan.erban.family.view.fragment.FamilyFriendListFragment; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.erban.family.presenter.FamilySelectFriendPresenter; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(FamilySelectFriendPresenter.class) +public class FamilySelectFriendActivity extends BaseMvpActivity + implements IFamilySelectFriendActivityView, CarMagicIndicator.OnItemSelectListener { + + private TitleBar titleBar; + private MagicIndicator viewIndicator; + private ViewPager viewpager; + + private static SelectFriendCallBack callBack; + + private int pageLimitSize = 3; + private String[] titles = {"好友", "关注", "粉丝"}; + + public static void start(Context context,SelectFriendCallBack selectFriendCallBack) { + callBack = selectFriendCallBack; + Intent intent = new Intent(context,FamilySelectFriendActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_family_select_friend); + init(); + } + + private void init() { + titleBar = findViewById(R.id.title_bar); + initTitleBar(getString(R.string.title_select_friend)); +// titleBar.addAction(new TitleBar.Action() { +// @Override +// public String getText() { +// return null; +// } +// +// @Override +// public int getDrawable() { +// return R.drawable.ic_send_search; +// } +// +// @Override +// public void performAction(View view) { +// AitFriendsSearchActivity.startForSharing(FamilySelectFriendActivity.this); +// } +// }); + + viewIndicator = findViewById(R.id.view_indicator); + viewpager = findViewById(R.id.viewpager); + + viewpager.setOffscreenPageLimit(pageLimitSize); + viewpager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getFragment(), titles)); + + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(1, getString(R.string.tab_title_friends))); + tabInfoList.add(new TabInfo(2, getString(R.string.tab_title_attentions))); + tabInfoList.add(new TabInfo(3, getString(R.string.tab_title_fans))); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(viewIndicator, viewpager); + } + + private List getFragment() { + List list = new ArrayList<>(); + list.add(FamilyFriendListFragment.newInstances()); + list.add(FamilyAttentionFragment.newInstance()); + list.add(FamilyFansListFragment.newInstances()); + return list; + } + + @Override + public void onItemSelect(int position) { + viewpager.setCurrentItem(position); + } + + + public void onSelectFriend(UserInfo userInfo){ + showConfirmDialog(userInfo); + } + + private void showConfirmDialog(UserInfo userInfo) { + FamilyInviteConfirmDialog dialog = new FamilyInviteConfirmDialog(this); + dialog.setAvatar(userInfo.getAvatar()); + dialog.setName(userInfo.getNick()); + dialog.setOnOperationListener(new FamilyInviteConfirmDialog.OnOperationListener() { + @Override + public void onCancel(DialogInterface dialog) { + dialog.dismiss(); + } + + @Override + public void onOk(DialogInterface dialog) { + dialog.dismiss(); + if (callBack != null){ + callBack.onSelectFriend(FamilySelectFriendActivity.this, userInfo.getUid()); + } + finish(); + } + }); + dialog.show(); + } + + @Override + protected void onDestroy() { + callBack = null; + super.onDestroy(); + } + + public interface SelectFriendCallBack{ + void onSelectFriend(Activity activity, long uid); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyTextInputActivity.java b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyTextInputActivity.java new file mode 100644 index 000000000..e9888fc88 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/activity/FamilyTextInputActivity.java @@ -0,0 +1,73 @@ +package com.yizhuan.erban.family.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.EditText; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public class FamilyTextInputActivity extends BaseMvpActivity implements IMvpBaseView{ + + public static final String CONTENT = "content"; + private EditText etInput; + private TitleBar titleBar; + + private static CallBack listener; + + + public static void start(Context context, String familyName, CallBack callBack){ + listener = callBack; + Intent intent = new Intent(context,FamilyTextInputActivity.class); + intent.putExtra(BundleKeys.KEY_EXTRA_1,familyName); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + String originalText = getIntent().getStringExtra(BundleKeys.KEY_EXTRA_1); + setContentView(R.layout.activity_family_text_input); + + titleBar = (TitleBar) findViewById(R.id.title_bar); + etInput = (EditText) findViewById(R.id.et_input); + etInput.setText(originalText); + + initTitleBar(getResources().getString(R.string.family_name_hint)); + titleBar.setActionTextColor(R.color.text_color_primary); + titleBar.addAction(new TitleBar.TextAction("完成") { + @Override + public void performAction(View view) { + String content = etInput.getText().toString(); + //修改个人介绍 + if (!content + .trim() + .replaceAll(" ","") + .isEmpty()) { + if (listener != null){ + listener.onModify(content); + } + finish(); + } else { + toast("所填内容为空!"); + } + } + }); + + } + + @Override + protected void onDestroy() { + listener = null; + super.onDestroy(); + } + + public interface CallBack{ + void onModify(String str); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAdapter.java new file mode 100644 index 000000000..17b051c3a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAdapter.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class FamilyAdapter extends BaseQuickAdapter { + + private Context mContext; + private int mRound = 10; + + public FamilyAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_list, data); + this.mContext = context; + + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, FamilyInfo familyInfo) { + SquareImageView ivCover = (SquareImageView) baseViewHolder.getView(R.id.iv_cover); + + GlideApp.with(mContext) + .load(familyInfo.getFamilyIcon()) + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(mRound)) + .into(ivCover); + + TextView tvFamilyName = (TextView) baseViewHolder.getView(R.id.tv_family_name); + TextView tvFamilyId = (TextView) baseViewHolder.getView(R.id.tv_family_id); + TextView tvFamilyMemberCount = (TextView) baseViewHolder.getView(R.id.tv_family_member_count); + + tvFamilyName.setText(familyInfo.getFamilyName()); + tvFamilyId.setText(String.format(mContext.getResources().getString(R.string.family_id),familyInfo.getFamilyId())); + tvFamilyMemberCount.setText(String.format(mContext.getResources().getString(R.string.family_member_count),String.valueOf(familyInfo.getMemberCount()))); + + + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAttentionListAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAttentionListAdapter.java new file mode 100644 index 000000000..de0a1ceaa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyAttentionListAdapter.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/5 + */ + +public class FamilyAttentionListAdapter extends BaseQuickAdapter { + + public FamilyAttentionListAdapter(List attentionInfoList) { + super(R.layout.family_attention_item, attentionInfoList); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, AttentionInfo attentionInfo) { + if (attentionInfo == null) return; + + baseViewHolder.setText(R.id.tv_userName, attentionInfo.getNick()) + .setText(R.id.tv_user_desc, attentionInfo.getUserDesc() != null ? + attentionInfo.getUserDesc() + : baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) + .setVisible(R.id.view_line, baseViewHolder.getLayoutPosition() != getItemCount() - 1); + + + AppCompatImageView ivGender = baseViewHolder.getView(R.id.iv_gender); + if (attentionInfo.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + AppCompatImageView ivNobleLevel = baseViewHolder.getView(R.id.iv_noble_level); + if (attentionInfo.nobleUsers != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(attentionInfo.nobleUsers.getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(50, 75, 15); + nobleAvatarView.setData(attentionInfo.avatar, attentionInfo.nobleUsers); + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (attentionInfo.userLevelVo != null && !TextUtils.isEmpty(attentionInfo.userLevelVo.getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, attentionInfo.userLevelVo.getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = baseViewHolder.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (attentionInfo.userLevelVo != null && !TextUtils.isEmpty(attentionInfo.userLevelVo.getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, attentionInfo.userLevelVo.getCharmUrl(), ivCharmLevel); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyBannerAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyBannerAdapter.java new file mode 100644 index 000000000..6de6b1520 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyBannerAdapter.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.jude.rollviewpager.adapter.StaticPagerAdapter; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.family.bean.FindBannerInfo; + +import java.util.List; + + +public class FamilyBannerAdapter extends StaticPagerAdapter { + private Context context; + private List bannerInfoList; + private LayoutInflater mInflater; + + public FamilyBannerAdapter(List bannerInfoList, Context context) { + this.context = context; + this.bannerInfoList = bannerInfoList; + mInflater = LayoutInflater.from(context); + } + + public void setNewData(List data){ + this.bannerInfoList = data; + notifyDataSetChanged(); + } + + + @Override + public View getView(ViewGroup container, int position) { + FindBannerInfo bannerInfo = bannerInfoList.get(position); + String url = bannerInfo.getSkipUri(); + ImageView imgBanner = (ImageView) mInflater.inflate(R.layout.layout_family_banner_page_item, container, false); + //和游戏、首页tab一样,加载带大圆角的图 + ImageLoadUtils.loadGameBannerRoundBackground(context, bannerInfo.getBannerPic(), imgBanner); + + imgBanner.setOnClickListener(v -> { + if (TextUtils.isEmpty(url)) return; + if (bannerInfo.getSkipType() == FindBannerInfo.SKIP_TYP_H5) { + CommonWebViewActivity.start(context,url); + + } else if (bannerInfo.getSkipType() == FindBannerInfo.SKIP_TYP_CHAT_ROOM) { + if (TextUtils.isEmpty(url)) return; + try { + AVRoomActivity.start(context, Long.valueOf(url)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + }); + return imgBanner; + } + + @Override + public int getCount() { + if (bannerInfoList == null) { + return 0; + } else + return bannerInfoList.size(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyCurrencyBillAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyCurrencyBillAdapter.java new file mode 100644 index 000000000..95e66038e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyCurrencyBillAdapter.java @@ -0,0 +1,129 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.jay.widget.StickyHeaders; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.xchat_android_core.family.bean.BillDateDivInfo; +import com.yizhuan.xchat_android_core.family.bean.TransactionRecordInfo; +import com.yizhuan.xchat_android_core.family.bean.VMBillItemInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/30 + */ + +public class FamilyCurrencyBillAdapter extends BaseMultiItemQuickAdapter implements StickyHeaders { + + private Context mContext; + + public FamilyCurrencyBillAdapter(Context context, @Nullable List data) { + super(data); + this.mContext = context; + addItemType(VMBillItemInfo.TYPE_DATE_DIV, R.layout.item_family_currency_bill_date);//月份分割 + addItemType(VMBillItemInfo.TYPE_TRANSACTION_RECORD, R.layout.item_family_currency_transaction_record);//交易记录 + addItemType(VMBillItemInfo.TYPE_EMPTY_TIP, R.layout.item_family_currency_empty);//无记录 + } + + + @Override + protected void convert(BaseViewHolder helper, VMBillItemInfo item) { + if (item.getItemType() == VMBillItemInfo.TYPE_DATE_DIV){ + covertDateDIV(helper,(BillDateDivInfo) item.getData()); + } else if (item.getItemType() == VMBillItemInfo.TYPE_TRANSACTION_RECORD){ + covertTransactionRecord(helper, (TransactionRecordInfo) item.getData()); + } + } + + + private void covertDateDIV(BaseViewHolder helper, BillDateDivInfo item) { + if (null == item) return; + String currencyName = item.getMoneyName(); + + TextView tvDate = (TextView) helper.getView(R.id.tv_date); + TextView tvSummary = (TextView) helper.getView(R.id.tv_summary); + tvDate.setText(item.getDate()); + tvSummary.setText(String.format(mContext.getResources().getString(R.string.family_currency_bill_summary), + FormatUtils.formatToShortDown(item.getExpend()), + currencyName, + FormatUtils.formatToShortDown(item.getIncome()), + currencyName)); + tvDate.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != onDateSelectListener){ + onDateSelectListener.onDateSelect(); + } + } + }); + + + } + + private void covertTransactionRecord(BaseViewHolder helper, TransactionRecordInfo item) { + if (null == item) return; + + CircleImageView civImg = (CircleImageView) helper.getView(R.id.civ_img); + TextView tvDesc = (TextView) helper.getView(R.id.tv_desc); + TextView tvFrom = (TextView) helper.getView(R.id.tv_from); + TextView tvData = (TextView) helper.getView(R.id.tv_data); + TextView tvTime = (TextView) helper.getView(R.id.tv_time); + + + GlideApp.with(mContext) + .load(item.getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(civImg); + + civImg.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (item.getUid() > 0) { + UserInfoDialog userInfoDialog = new UserInfoDialog(mContext, item.getUid()); + userInfoDialog.show(); + } + } + }); + + tvDesc.setText(item.getTitle()); + tvFrom.setText(item.getDesc()); + tvData.setText(FormatUtils.formatToShortDown(item.getData()) + item.getMoneyName()); + if (item.getData() >= 0) { + tvData.setTextColor(mContext.getResources().getColor(R.color.appColor)); + }else { + tvData.setTextColor(mContext.getResources().getColor(R.color.color_333333)); + } + tvTime.setText(item.getDate()); + + + } + + @Override + public boolean isStickyHeader(int i) { + return getItemViewType(i) == VMBillItemInfo.TYPE_DATE_DIV ; + } + + private OnDateSelectListener onDateSelectListener; + + public void setOnDateSelectListener(OnDateSelectListener onDateSelectListener) { + this.onDateSelectListener = onDateSelectListener; + } + + public interface OnDateSelectListener{ + public void onDateSelect(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFansViewAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFansViewAdapter.java new file mode 100644 index 000000000..db0c4eeaa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFansViewAdapter.java @@ -0,0 +1,76 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/5 + */ + +public class FamilyFansViewAdapter extends BaseQuickAdapter { + + public FamilyFansViewAdapter(List fansInfoList) { + super(R.layout.family_fans_list_item, fansInfoList); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, FansInfo fansInfo) { + if (fansInfo == null) return; + baseViewHolder.setText(R.id.tv_userName, fansInfo.getNick()) + .setText(R.id.tv_user_desc, fansInfo.getUserDesc() != null ? + fansInfo.getUserDesc() + : baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) + .setVisible(R.id.view_line, baseViewHolder.getLayoutPosition() != getItemCount() - 1); + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(50, 75, 15); + nobleAvatarView.setData(fansInfo.getAvatar(), fansInfo.getNobleUsers()); + + AppCompatImageView ivGender = baseViewHolder.getView(R.id.iv_gender); + if (fansInfo.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + AppCompatImageView ivNobleLevel = baseViewHolder.getView(R.id.iv_noble_level); + if (fansInfo.getNobleUsers() != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(fansInfo.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (fansInfo.getUserLevelVo() != null && !TextUtils.isEmpty(fansInfo.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, fansInfo.getUserLevelVo().getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = baseViewHolder.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (fansInfo.getUserLevelVo() != null && !TextUtils.isEmpty(fansInfo.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, fansInfo.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFriendListAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFriendListAdapter.java new file mode 100644 index 000000000..25b70eddd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyFriendListAdapter.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ + +public class FamilyFriendListAdapter extends BaseQuickAdapter { + private Context context; + + public FamilyFriendListAdapter(Context context, @Nullable List data) { + super(R.layout.family_list_item_friend, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, UserInfo item) { + if (item == null) return; + + helper.setText(R.id.tv_userName, item.getNick()) + .setText(R.id.tv_user_desc, item.getUserDesc() != null ? + item.getUserDesc() + : helper.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)); + + NobleAvatarView mNobleAvatarView = helper.getView(R.id.noble_avatar_view); + mNobleAvatarView.setSize(47, 70, 13); + mNobleAvatarView.setData(item.getAvatar(), item.getNobleUsers()); + + AppCompatImageView ivGender = helper.getView(R.id.iv_gender); + if (item.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + AppCompatImageView ivNobleLevel = helper.getView(R.id.iv_noble_level); + if (item.getNobleUsers() != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(item.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + AppCompatImageView ivUserLevel = helper.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = helper.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGameListAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGameListAdapter.java new file mode 100644 index 000000000..b04dc2e2b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGameListAdapter.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.makeramen.roundedimageview.RoundedImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/23 + */ + +public class FamilyGameListAdapter extends BaseQuickAdapter { + + private Context mContext; + public FamilyGameListAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_game_list,data); + this.mContext = context; + + } + + @Override + protected void convert(BaseViewHolder helper, FamilyGameInfo item) { + RoundedImageView rivCover = (RoundedImageView) helper.getView(R.id.riv_cover); + TextView tvName = (TextView) helper.getView(R.id.tv_name); + + GlideApp.with(mContext) + .load(TextUtils.isEmpty(item.getIcon()) ? R.drawable.default_cover : item.getIcon()) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(rivCover); + + tvName.setText(item.getName()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGamesAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGamesAdapter.java new file mode 100644 index 000000000..c926ac4c1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGamesAdapter.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.makeramen.roundedimageview.RoundedImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.family.bean.FamilyGameInfo; + +import java.util.List; + +/** + * @author jack + */ + +public class FamilyGamesAdapter extends BaseQuickAdapter { + + private Context mContext; + + public FamilyGamesAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_games, data); + this.mContext = context; + } + + @Override + protected void convert(BaseViewHolder helper, FamilyGameInfo item) { + RoundedImageView rivCover = helper.getView(R.id.riv_cover); + TextView tvName = helper.getView(R.id.tv_name); + + GlideApp.with(mContext) + .load(TextUtils.isEmpty(item.getIcon()) ? R.drawable.default_cover : item.getIcon()) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(rivCover); + + tvName.setText(item.getName()); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGroupAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGroupAdapter.java new file mode 100644 index 000000000..4c0f82eea --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyGroupAdapter.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.xchat_android_core.family.bean.FamilyGroupInfo; + +import java.util.List; + +/** + * @author jack + */ +public class FamilyGroupAdapter extends BaseQuickAdapter { + + private Context mContext; + + public FamilyGroupAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_group, data); + this.mContext = context; + } + + @Override + protected void convert(BaseViewHolder helper, FamilyGroupInfo item) { + SquareImageView ivCover = helper.getView(R.id.iv_cover); + TextView tvFamilyGroupName = helper.getView(R.id.tv_family_group_name); + TextView tvFamilyGroupDesc = helper.getView(R.id.tv_family_group_desc); + + TextView tvJoinGroup = helper.getView(R.id.tv_join_group); + ImageView ivArrowRight = helper.getView(R.id.iv_arrow_right); + + GlideApp.with(mContext) + .load(TextUtils.isEmpty(item.getIcon()) ? R.drawable.default_cover : item.getIcon()) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(10)) + .into(ivCover); + + tvFamilyGroupName.setText(item.getName()); + tvFamilyGroupDesc.setText(String.format( + mContext.getResources().getString(R.string.family_member_count), + String.valueOf(item.getMemberCount()))); + + if (item.isExists()){ + tvJoinGroup.setVisibility(View.GONE); + ivArrowRight.setVisibility(View.VISIBLE); + helper.itemView.setOnClickListener(v -> { + if (actionListener != null){ + actionListener.onGotoGroup(item); + } + }); + } else { + tvJoinGroup.setVisibility(View.VISIBLE); + ivArrowRight.setVisibility(View.GONE); + tvJoinGroup.setOnClickListener(v -> { + if (actionListener != null){ + actionListener.onJoin(item); + } + }); + } + + } + + private ActionListener actionListener; + + public void setActionListener(ActionListener actionListener) { + this.actionListener = actionListener; + } + + public interface ActionListener{ + void onJoin(FamilyGroupInfo groupInfo); + void onGotoGroup(FamilyGroupInfo groupInfo); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyManageAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyManageAdapter.java new file mode 100644 index 000000000..f130d0818 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyManageAdapter.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.xchat_android_core.family.bean.FamilyManageItemInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class FamilyManageAdapter extends BaseQuickAdapter { + + public FamilyManageAdapter( @Nullable List data) { + super(R.layout.item_family_manage_rv, data); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, FamilyManageItemInfo familyManageItemInfo) { + SquareImageView ivImg = (SquareImageView) baseViewHolder.getView(R.id.iv_img); + ivImg.setImageResource(familyManageItemInfo.getImg()); + TextView tvName = (TextView) baseViewHolder.getView(R.id.tv_name); + tvName.setText(familyManageItemInfo.getName()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberAdapter.java new file mode 100644 index 000000000..87ebc396e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberAdapter.java @@ -0,0 +1,64 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/25 + */ + +public class FamilyMemberAdapter extends BaseQuickAdapter { + + private Context mContext; + + + public FamilyMemberAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_member, data); + this.mContext = context; + } + + @Override + protected void convert(BaseViewHolder helper, FamilyMemberInfo item) { + + + View view = helper.itemView; + ViewGroup.LayoutParams lp = view.getLayoutParams(); + lp.width = (Utils.getWindowWidth(mContext) - Utils.dip2px(mContext,30 + 20*4)) / 5; + view.setLayoutParams(lp); + + CircleImageView rivCover = (CircleImageView) helper.getView(R.id.riv_cover); + ImageView ivPatriarchTag = (ImageView) helper.getView(R.id.iv_patriarch_tag); + TextView tvName = (TextView) helper.getView(R.id.tv_name); + + GlideApp.with(mContext) + .load(TextUtils.isEmpty(item.getIcon()) ? R.drawable.default_avatar : item.getIcon()) + .placeholder(R.drawable.default_avatar) + .error(R.drawable.default_avatar) + .into(rivCover); + tvName.setText(item.getName()); + if (item.getPosition() == FamilyMemberInfo.LEVEL_PATRIARCH){ + ivPatriarchTag.setVisibility(View.VISIBLE); + }else { + ivPatriarchTag.setVisibility(View.GONE); + } + + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberListAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberListAdapter.java new file mode 100644 index 000000000..154406d59 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyMemberListAdapter.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.family.view.activity.FamilyMemberListActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.level.UserLevelVo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/28 + */ + +public class FamilyMemberListAdapter extends BaseQuickAdapter { + + private Context mContext; + private int optType; + + public FamilyMemberListAdapter(Context context, @Nullable List data, int optType) { + super(R.layout.item_family_member_list,data); + this.mContext = context; + this.optType = optType; + } + + @Override + protected void convert(BaseViewHolder helper, FamilyMemberInfo item) { + + CircleImageView civAvatar = (CircleImageView) helper.getView(R.id.civ_avatar); + + ImageView ivPatriarchTag = helper.getView(R.id.iv_patriarch_tag); + + TextView tvName = (TextView) helper.getView(R.id.tv_name); + TextView tvErbanId = (TextView) helper.getView(R.id.tv_erban_id); + + if (item.getGender() == 1) { + helper.setImageResource(R.id.iv_gender, R.drawable.ic_male); + } else { + helper.setImageResource(R.id.iv_gender, R.drawable.ic_female); + } + + + ImageButton tvMemberRemove = helper.getView(R.id.tv_member_remove); + UserLevelVo userLevelVo = item.getUserLevelVo(); + ImageView ivUserLevel = helper.getView(R.id.iv_user_level); + ImageView ivUserCharm = helper.getView(R.id.iv_user_charm); + ivUserLevel.setVisibility(userLevelVo == null ? View.GONE : View.VISIBLE); + ivUserLevel.setVisibility(userLevelVo == null ? View.GONE : View.VISIBLE); + if (userLevelVo != null) { + ivUserLevel.setVisibility(TextUtils.isEmpty(userLevelVo.getExperUrl()) ? View.GONE : View.VISIBLE); + if (!TextUtils.isEmpty(userLevelVo.getExperUrl())) { + ImageLoadUtils.loadImage(mContext, userLevelVo.getExperUrl(), ivUserLevel); + } + ivUserCharm.setVisibility(TextUtils.isEmpty(userLevelVo.getCharmUrl()) ? View.GONE : View.VISIBLE); + if (!TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + ivUserCharm.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, userLevelVo.getCharmUrl(), ivUserCharm); + } + } + GlideApp.with(mContext) + .load(TextUtils.isEmpty(item.getIcon()) ? R.drawable.default_avatar : item.getIcon()) + .placeholder(R.drawable.default_avatar) + .error(R.drawable.default_avatar) + .into(civAvatar); + tvName.setText(item.getName()); + tvErbanId.setText(String.format( + mContext.getResources().getString(R.string.family_member_erban_id), + String.valueOf(item.getErbanNo()) + )); + + if (item.getPosition() == FamilyMemberInfo.LEVEL_PATRIARCH){ + ivPatriarchTag.setVisibility(View.VISIBLE); + }else { + ivPatriarchTag.setVisibility(View.GONE); + } + civAvatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != actionListener){ + actionListener.onClickAvatar(item); + } + } + }); + if (optType == FamilyMemberListActivity.TYPE_SELECT_MEMBER){ + tvMemberRemove.setVisibility(View.GONE); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != actionListener){ + actionListener.onTransferCurrency(item); + } + } + }); + }else if (optType == FamilyMemberListActivity.TYPE_REMOVE_MEMBER){ + if (item.getPosition() == FamilyMemberInfo.LEVEL_PATRIARCH) { + tvMemberRemove.setVisibility(View.GONE); + }else { + tvMemberRemove.setVisibility(View.VISIBLE); + tvMemberRemove.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != actionListener){ + actionListener.onRemoveMember(item); + } + } + }); + } + }else if (optType == FamilyMemberListActivity.TYPE_SHOW_MEMBER){ + tvMemberRemove.setVisibility(View.GONE); + + }else if (optType == FamilyMemberListActivity.TYPE_CHECK_MEMBER_CURRENCY){ + tvMemberRemove.setVisibility(View.GONE); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != actionListener){ + actionListener.onCheckMemberCurrency(item); + } + } + }); + } + + } + + private ActionListener actionListener; + + public void setActionListener(ActionListener actionListener) { + this.actionListener = actionListener; + } + + public interface ActionListener{ + public void onRemoveMember(FamilyMemberInfo familyMemberInfo); + public void onTransferCurrency(FamilyMemberInfo familyMemberInfo); + void onClickAvatar(FamilyMemberInfo item); + void onCheckMemberCurrency(FamilyMemberInfo item); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyWeeklyRankBoardAdapter.java b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyWeeklyRankBoardAdapter.java new file mode 100644 index 000000000..69f18e032 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/adapter/FamilyWeeklyRankBoardAdapter.java @@ -0,0 +1,95 @@ +package com.yizhuan.erban.family.view.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class FamilyWeeklyRankBoardAdapter extends BaseQuickAdapter { + + private Context mContext; + private int mRound = 10; + + public FamilyWeeklyRankBoardAdapter(Context context, @Nullable List data) { + super(R.layout.item_family_weekly_rank_list, data); + this.mContext = context; + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, RankingFamilyInfo familyInfo) { + SquareImageView ivCover = baseViewHolder.getView(R.id.iv_cover); + + GlideApp.with(mContext) + .load(familyInfo.getIcon()) + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(mRound)) + .into(ivCover); + + TextView tvRanking = baseViewHolder.getView(R.id.tv_ranking); + TextView tvCharm = baseViewHolder.getView(R.id.tv_charm); + TextView tvCharmLabel = baseViewHolder.getView(R.id.tv_charm_label); + TextView tvFamilyName = baseViewHolder.getView(R.id.tv_family_name); + TextView tvFamilyId = baseViewHolder.getView(R.id.tv_family_id); + + tvFamilyName.setText(familyInfo.getName()); + tvFamilyId.setText(String.format(mContext.getResources().getString(R.string.family_id),familyInfo.getId())); + + int position = getItemPositionInList(getData(),familyInfo); + if (position == 0){ + tvCharmLabel.setVisibility(View.GONE); + tvCharm.setVisibility(View.VISIBLE); + tvCharm.setText("No.1"); + }else { + tvCharmLabel.setVisibility(View.VISIBLE); + tvCharm.setVisibility(View.VISIBLE); + RankingFamilyInfo previousOne = getData().get(position - 1); + long charmDiff = previousOne.getFamilyCharm() - familyInfo.getFamilyCharm(); + tvCharm.setText(FormatUtils.formatToShortHalfUp(charmDiff)); + } + + if (position == 0){ + tvRanking.setBackgroundResource(R.mipmap.ic_family_weekly_ranking_1); + tvRanking.setText(""); + }else if (position == 1){ + tvRanking.setBackgroundResource(R.mipmap.ic_family_weekly_ranking_2); + tvRanking.setText(""); + }else if (position == 2){ + tvRanking.setBackgroundResource(R.mipmap.ic_family_weekly_ranking_3); + tvRanking.setText(""); + }else { + tvRanking.setText(String.valueOf(position + 1)); + tvRanking.setBackgroundResource(R.drawable.shape_circle_gray_small); + } + + } + + private int getItemPositionInList(List list,RankingFamilyInfo familyInfo){ + int pos = -1; + for (int i = 0; i < list.size(); i++) { + if (familyInfo.getId().equals(list.get(i).getId())){ + pos = i; + break; + } + } + return pos; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyContributionDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyContributionDialog.java new file mode 100644 index 000000000..c73593612 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyContributionDialog.java @@ -0,0 +1,170 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_core.family.bean.response.moneyManagement.FamilyMoneyManagementInfo; +import com.yizhuan.xchat_android_library.utils.ImeUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +/** + * @author jack + * @Description 贡献家族币 + * @Date 2018/5/30 + */ + +public class FamilyContributionDialog extends Dialog { + + private TextView tvTitle; + private TextView tvFamilyCurrencyBalanceTip; + private TextView tvFamilyCurrencyBalanceValue; + private TextView tvMemberName; + private EditText etInput; + private TextView tvCurrencyName; + private TextView tvCancel; + private TextView tvOk; + + private FamilyMoneyManagementInfo familyMoneyManagementInfo; + + public FamilyContributionDialog(@NonNull Context context) { + super(context, R.style.easy_dialog_style); + } + + public FamilyContributionDialog(Context context, FamilyMoneyManagementInfo familyMoneyManagementInfo) { + this(context); + this.familyMoneyManagementInfo = familyMoneyManagementInfo; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + init(); + } + + private void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + setContentView(R.layout.dialog_family_currency_contribution); + + tvTitle = (TextView) findViewById(R.id.tv_title); + tvFamilyCurrencyBalanceTip = (TextView) findViewById(R.id.tv_family_currency_balance_tip); + tvFamilyCurrencyBalanceValue = (TextView) findViewById(R.id.tv_family_currency_balance_value); + tvMemberName = (TextView) findViewById(R.id.tv_member_name); + etInput = (EditText) findViewById(R.id.et_input); + tvCurrencyName = (TextView) findViewById(R.id.tv_currency_name); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvOk = (TextView) findViewById(R.id.tv_ok); + + tvTitle.setText(String.format( + getContext().getResources().getString(R.string.family_currency_contribution), + familyMoneyManagementInfo.getMoneyName() + )); + tvFamilyCurrencyBalanceTip.setText(String.format( + getContext().getResources().getString(R.string.family_currency_contribution_balance_tip), + familyMoneyManagementInfo.getMoneyName() + )); + tvFamilyCurrencyBalanceValue.setText(String.format( + getContext().getResources().getString(R.string.family_currency_count), + FormatUtils.formatToShortDown(familyMoneyManagementInfo.getTotalAmount()), + familyMoneyManagementInfo.getMoneyName() + )); + tvCurrencyName.setText(familyMoneyManagementInfo.getMoneyName()); + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + if (null != onOperationListener){ + onOperationListener.onCancel(FamilyContributionDialog.this); + } + } + }); + + tvOk.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + String str = etInput.getText().toString().trim(); + if (TextUtils.isEmpty(str)){ +// Toast.makeText(getContext(),"请输入正确的金额",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入正确的金额"); + return; + } + double count = Double.valueOf(str); + if (count < 0.01f){ +// Toast.makeText(getContext(),"最低操作家族币不少于 0.01",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("最低操作家族币不少于 0.01"); + return; + } + if (null != onOperationListener){ + onOperationListener.onOk(FamilyContributionDialog.this, count); + } + } + }); + + + etInput.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.toString().contains(".")) { + if (s.length() - 1 - s.toString().indexOf(".") > 2) { + s = s.toString().subSequence(0, + s.toString().indexOf(".") + 3); + etInput.setText(s); + etInput.setSelection(s.length()); + } + } + if (s.toString().trim().substring(0).equals(".")) { + s = "0" + s; + etInput.setText(s); + etInput.setSelection(2); + } + + if (s.toString().startsWith("0") + && s.toString().trim().length() > 1) { + if (!s.toString().substring(1, 2).equals(".")) { + etInput.setText(s.subSequence(0, 1)); + etInput.setSelection(1); + return; + } + } + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + } + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog, double count); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyDisbandDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyDisbandDialog.java new file mode 100644 index 000000000..03ee2ae2b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyDisbandDialog.java @@ -0,0 +1,75 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.xchat_android_core.family.bean.CustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyCustomServiceInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +/** + * @author jack + */ + +public class FamilyDisbandDialog extends Dialog { + + private TextView tvDisbandTip; + private CustomServiceInfo serviceInfo; + + + public FamilyDisbandDialog(@NonNull Context context) { + super(context, R.style.easy_dialog_style); + init(); + } + + private void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + setContentView(R.layout.dialog_disband_family); + tvDisbandTip = findViewById(R.id.tv_disband_tip); + TextView tvCancel = findViewById(R.id.tv_cancel); + TextView tvContactService = findViewById(R.id.tv_contact_service); + + tvCancel.setOnClickListener(v -> dismiss()); + tvContactService.setOnClickListener(v -> { + dismiss(); + if (null != serviceInfo) { + NimP2PMessageActivity.start(getContext(), serviceInfo.getUid()); + }else { +// Toast.makeText(getContext(),"没找到客服信息.",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("没找到客服信息."); + } + }); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + FamilyCustomServiceInfo customServiceInfo = FamilyModel.Instance().getCustomServiceInfo(); + if (null == customServiceInfo){ +// Toast.makeText(getContext(),"没找到客服信息.",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("没找到客服信息."); + return; + } + + String str = ""; + for (int i = 0; i < customServiceInfo.getServices().size(); i++) { + CustomServiceInfo item = customServiceInfo.getServices().get(i); + if (item.getType() == CustomServiceInfo.TYPE_ONLINE){ + serviceInfo = item; + str = serviceInfo.getContent(); + } + } + + tvDisbandTip.setText(String.format(getContext().getResources().getString(R.string.family_disband_tip1), str)); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyExitTipDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyExitTipDialog.java new file mode 100644 index 000000000..fa710db32 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyExitTipDialog.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.support.annotation.NonNull; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; + +/** + * @author jack + * @Description + * @Date 2018/6/19 + */ + +public class FamilyExitTipDialog extends Dialog { + + private TextView tvMessage; + private TextView tvCancel; + private TextView tvContactService; + + private FamilyInfo familyInfo; + + public FamilyExitTipDialog(@NonNull Context context, FamilyInfo familyInfo) { + super(context, R.style.easy_dialog_style); + this.familyInfo = familyInfo; + init(); + } + + private void init() { + setCancelable(true); + setCanceledOnTouchOutside(true); + + setContentView(R.layout.dialog_family_exit); + tvMessage = (TextView) findViewById(R.id.tv_message); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvContactService = (TextView) findViewById(R.id.tv_contact_service); + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onCancel(FamilyExitTipDialog.this); + } + } + }); + tvContactService.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onOk(FamilyExitTipDialog.this, familyInfo); + } + } + }); + } + + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog, FamilyInfo familyInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyGuideDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyGuideDialog.java new file mode 100644 index 000000000..9a3d35620 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyGuideDialog.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/18 + */ + +public class FamilyGuideDialog extends Dialog { + + private ImageView ivGuide1; + private List guidePics = new ArrayList<>(); + private Iterator iterator; + + public FamilyGuideDialog(@NonNull Context context) { + super(context, R.style.common_dialog_theme); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Window window = getWindow(); + if (window != null){ + window.getDecorView().setPadding(0,0,0,0); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.width = WindowManager.LayoutParams.MATCH_PARENT; + lp.height = WindowManager.LayoutParams.MATCH_PARENT; + lp.gravity = Gravity.CENTER; + window.setAttributes(lp); + + } + + setContentView(R.layout.dialog_family_guide); + + + guidePics.add(R.mipmap.bg_family_guide_1); + guidePics.add(R.mipmap.bg_family_guide_2); + guidePics.add(R.mipmap.bg_family_guide_3); + iterator = guidePics.iterator(); + + ivGuide1 = (ImageView) findViewById(R.id.iv_guide_1); + GlideApp.with(getContext()) + .load(iterator.next()) + .dontAnimate() + .into(ivGuide1); + + ivGuide1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (iterator.hasNext()){ + GlideApp.with(getContext()) + .load(iterator.next()) + .dontAnimate() + .into(ivGuide1); + }else { + dismiss(); + } + } + }); + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyInviteConfirmDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyInviteConfirmDialog.java new file mode 100644 index 000000000..07156baba --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyInviteConfirmDialog.java @@ -0,0 +1,97 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; + +/** + * @author jack + * @Description + * @Date 2018/6/19 + */ + +public class FamilyInviteConfirmDialog extends Dialog { + + private CircleImageView civAvatar; + private TextView tvMessage; + private TextView tvCancel; + private TextView tvContactService; + + private String avatar; + private CharSequence name; + + public FamilyInviteConfirmDialog(@NonNull Context context) { + super(context, R.style.easy_dialog_style); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + init(); + } + + private void init() { + setCancelable(true); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_family_invite_confirm); + + civAvatar = (CircleImageView) findViewById(R.id.civ_avatar); + tvMessage = (TextView) findViewById(R.id.tv_message); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvContactService = (TextView) findViewById(R.id.tv_contact_service); + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onCancel(FamilyInviteConfirmDialog.this); + } + } + }); + tvContactService.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onOk(FamilyInviteConfirmDialog.this); + } + } + }); + if (avatar != null){ + GlideApp.with(getContext()) + .load(avatar) + .dontAnimate() + .into(civAvatar); + } + if (name != null){ + tvMessage.setText(name); + } + } + + public void setAvatar(String avatar){ + this.avatar = avatar; + } + + public void setName(CharSequence name){ + this.name = name; + } + + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyJoinDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyJoinDialog.java new file mode 100644 index 000000000..3d7067dc7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyJoinDialog.java @@ -0,0 +1,101 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.ImeUtil; + +/** + * @author jack + */ +public class FamilyJoinDialog extends Dialog { + + private TextView tvFamilyJoinTip; + private EditText etInput; + private TextView tvCancel; + private TextView tvOk; + + private String defaultVerifyMessage = ""; + + public FamilyJoinDialog(@NonNull Context context) { + super(context, R.style.easy_dialog_style); + init(); + } + + private void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + setContentView(R.layout.dialog_family_join); + + + tvFamilyJoinTip = findViewById(R.id.tv_family_join_tip); + etInput = findViewById(R.id.et_input); + tvCancel = findViewById(R.id.tv_cancel); + tvOk = findViewById(R.id.tv_ok); + + etInput.setHint(getContext().getResources().getString(R.string.family_join_hint)); + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + if (null != onOperationListener){ + onOperationListener.onCancel(FamilyJoinDialog.this); + } + } + }); + + tvOk.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + String str = etInput.getText().toString(); + if (!TextUtils.isEmpty(str)){ + defaultVerifyMessage = str; + } + if (null != onOperationListener){ + onOperationListener.onOk(FamilyJoinDialog.this,defaultVerifyMessage); + } + } + }); + + } + + /** + * 设置提示语句 + * @param msg + */ + public void setTipMessage(CharSequence msg){ + tvFamilyJoinTip.setText(msg); + } + + /** + * 设置默认验证信息 + * @param str + */ + public void setDefaultVerifyMessage(String str){ + etInput.setHint(str); + this.defaultVerifyMessage = str; + } + + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog, String str); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyMenuDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyMenuDialog.java new file mode 100644 index 000000000..faeee3e79 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyMenuDialog.java @@ -0,0 +1,97 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_library.widget.DrawableCenterTextView; + +/** + * @author jack + */ +public class FamilyMenuDialog extends Dialog { + + private FamilyInfo familyInfo; + + private Context mContext; + + public FamilyMenuDialog(@NonNull Context context, FamilyInfo familyInfo) { + super(context, R.style.easy_dialog_style); + mContext = context; + this.familyInfo = familyInfo; + init(null); + } + public FamilyMenuDialog(@NonNull Context context, FamilyInfo familyInfo, View attachView) { + super(context, R.style.easy_dialog_style); + mContext = context; + this.familyInfo = familyInfo; + init(attachView); + } + + private void init(View attachView) { + Window window = getWindow(); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.gravity = Gravity.TOP | Gravity.END; + if (attachView != null) { + lp.x = attachView.getWidth() / 2 - SizeUtils.dp2px(mContext, 9); + lp.y = attachView.getHeight() + SizeUtils.dp2px(mContext, 10); + } + window.setAttributes(lp); + + setContentView(R.layout.dialog_family_menu); + + setCanceledOnTouchOutside(true); + + boolean isPatriarch = familyInfo.getPosition() == FamilyInfo.LEVEL_PATRIARCH; + + DrawableCenterTextView tvMenu1 = findViewById(R.id.tv_menu1); + View divider = findViewById(R.id.v_divider_family); + tvMenu1.setVisibility(isPatriarch ? View.VISIBLE : View.GONE); + divider.setVisibility(isPatriarch ? View.VISIBLE : View.GONE); + if (isPatriarch) { + tvMenu1.setOnClickListener(v -> { + if (null != onMenuClickListener){ + onMenuClickListener.onInviteFriends(FamilyMenuDialog.this,familyInfo); + } + }); + } + + DrawableCenterTextView tvMenu2 = findViewById(R.id.tv_menu2); + tvMenu2.setText(isPatriarch ? + getContext().getResources().getString(R.string.family_disband) : getContext().getResources().getString(R.string.family_exit_family)); + Drawable drawable = isPatriarch ? + ContextCompat.getDrawable(mContext, R.drawable.ic_dissolve_family) : ContextCompat.getDrawable(mContext, R.drawable.ic_exit_family); + tvMenu2.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); + tvMenu2.setOnClickListener(v -> { + if (null != onMenuClickListener){ + if (familyInfo.getPosition() == FamilyInfo.LEVEL_PATRIARCH) { + onMenuClickListener.onDisbandFamily(FamilyMenuDialog.this, familyInfo); + }else { + onMenuClickListener.onExitFamily(FamilyMenuDialog.this, familyInfo); + } + } + }); + + } + + private OnMenuClickListener onMenuClickListener; + public void setOnMenuClickListener(OnMenuClickListener listener){ + this.onMenuClickListener = listener; + } + + public interface OnMenuClickListener{ + void onExitFamily(DialogInterface dialog, FamilyInfo familyInfo); + void onDisbandFamily(DialogInterface dialog, FamilyInfo familyInfo); + void onInviteFriends(DialogInterface dialog, FamilyInfo familyInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyRemoveMemberDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyRemoveMemberDialog.java new file mode 100644 index 000000000..8332ef79c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyRemoveMemberDialog.java @@ -0,0 +1,86 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; + +/** + * @author jack + * @Description + * @Date 2018/5/29 + */ + +public class FamilyRemoveMemberDialog extends Dialog { + + private TextView tvMessage; + private TextView tvCancel; + private TextView tvContactService; + + private FamilyMemberInfo familyMemberInfo; + + + public FamilyRemoveMemberDialog(@NonNull Context context, FamilyMemberInfo familyMemberInfo) { + super(context, R.style.easy_dialog_style); + this.familyMemberInfo = familyMemberInfo; + init(); + } + + private void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + setContentView(R.layout.dialog_family_remove_member); + tvMessage = (TextView) findViewById(R.id.tv_message); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvContactService = (TextView) findViewById(R.id.tv_contact_service); + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onCancel(FamilyRemoveMemberDialog.this); + } + } + }); + tvContactService.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onOperationListener != null){ + onOperationListener.onOk(FamilyRemoveMemberDialog.this, familyMemberInfo); + } + } + }); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + tvMessage.setText(String.format( + getContext().getResources().getString(R.string.family_remove_member_tip), + familyMemberInfo.getName())); + + } + + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog, FamilyMemberInfo familyMemberInfo); + } + + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyTransferDialog.java b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyTransferDialog.java new file mode 100644 index 000000000..0502a90bc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/dialog/FamilyTransferDialog.java @@ -0,0 +1,178 @@ +package com.yizhuan.erban.family.view.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.support.annotation.NonNull; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_library.utils.ImeUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +/** + * @author jack + * @Description + * @Date 2018/5/30 + */ + +public class FamilyTransferDialog extends Dialog { + + private TextView tvTitle; + private TextView tvFamilyCurrencyBalanceTip; + private TextView tvFamilyCurrencyBalanceValue; + private TextView tvMemberName; + private EditText etInput; + private TextView tvCurrencyName; + private TextView tvCancel; + private TextView tvOk; + + private FamilyInfo familyInfo; + private FamilyMemberInfo familyMemberInfo; + + public FamilyTransferDialog(@NonNull Context context, FamilyInfo familyInfo, FamilyMemberInfo familyMemberInfo) { + super(context, R.style.easy_dialog_style); + this.familyInfo = familyInfo; + this.familyMemberInfo = familyMemberInfo; + init(); + } + + + private void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + setContentView(R.layout.dialog_family_currency_transfer); + + tvTitle = (TextView) findViewById(R.id.tv_title); + tvFamilyCurrencyBalanceTip = (TextView) findViewById(R.id.tv_family_currency_balance_tip); + tvFamilyCurrencyBalanceValue = (TextView) findViewById(R.id.tv_family_currency_balance_value); + tvMemberName = (TextView) findViewById(R.id.tv_member_name); + etInput = (EditText) findViewById(R.id.et_input); + tvCurrencyName = (TextView) findViewById(R.id.tv_currency_name); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvOk = (TextView) findViewById(R.id.tv_ok); + + tvTitle.setText(String.format( + getContext().getResources().getString(R.string.family_currency_transfer), + familyInfo.getMoneyName())); + + tvFamilyCurrencyBalanceTip.setText(String.format( + getContext().getResources().getString(R.string.family_currency_transfer_label1), + familyInfo.getMoneyName()) + ); + tvFamilyCurrencyBalanceValue.setText(String.format( + getContext().getResources().getString(R.string.family_currency_count), + FormatUtils.formatToShortDown(familyInfo.getFamilyMoney()), + familyInfo.getMoneyName() + ) + ); + tvMemberName.setText(familyMemberInfo.getName()); + tvCurrencyName.setText(familyInfo.getMoneyName()); + + + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + if (null != onOperationListener){ + onOperationListener.onCancel(FamilyTransferDialog.this); + } + + } + }); + + tvOk.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ImeUtil.hideIME(getContext(),etInput); + if (familyMemberInfo.getUid() == AuthModel.get().getCurrentUid()){ +// Toast.makeText(getContext(),"不可以给自己转让哦~",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("不可以给自己转让哦~"); + return; + } + String str = etInput.getText().toString().trim(); + if (TextUtils.isEmpty(str)){ +// Toast.makeText(getContext(),"请输入正确的金额",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入正确的金额"); + return; + } + double count = Double.valueOf(etInput.getText().toString().trim()); + if (count < 0.01f){ +// Toast.makeText(getContext(),"最低操作家族币不少于 0.01",Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("最低操作家族币不少于 0.01"); + return; + } + +// Toast.makeText(getContext(),getContext().getResources() +// .getString(R.string.family_transfer_currency_insufficient),Toast.LENGTH_SHORT).show(); + + + if (null != onOperationListener){ + onOperationListener.onOk(FamilyTransferDialog.this, familyMemberInfo, count); + } + } + }); + + etInput.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.toString().contains(".")) { + if (s.length() - 1 - s.toString().indexOf(".") > 2) { + s = s.toString().subSequence(0, + s.toString().indexOf(".") + 3); + etInput.setText(s); + etInput.setSelection(s.length()); + } + } + if (s.toString().trim().substring(0).equals(".")) { + s = "0" + s; + etInput.setText(s); + etInput.setSelection(2); + } + + if (s.toString().startsWith("0") + && s.toString().trim().length() > 1) { + if (!s.toString().substring(1, 2).equals(".")) { + etInput.setText(s.subSequence(0, 1)); + etInput.setSelection(1); + return; + } + } + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + } + + private OnOperationListener onOperationListener; + + public void setOnOperationListener(OnOperationListener onOperationListener) { + this.onOperationListener = onOperationListener; + } + + public interface OnOperationListener{ + void onCancel(DialogInterface dialog); + void onOk(DialogInterface dialog, FamilyMemberInfo familyMemberInfo, double count); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyAttentionFragment.java b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyAttentionFragment.java new file mode 100644 index 000000000..df68bee57 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyAttentionFragment.java @@ -0,0 +1,146 @@ +package com.yizhuan.erban.family.view.fragment; + +import android.app.Activity; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyAttentionFragmentView; +import com.yizhuan.erban.family.view.activity.FamilySelectFriendActivity; +import com.yizhuan.erban.family.view.adapter.FamilyAttentionListAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.family.presenter.FamilyAttentionPresenter; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ +@CreatePresenter(FamilyAttentionPresenter.class) +public class FamilyAttentionFragment extends BaseMvpFragment + implements IFamilyAttentionFragmentView { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView userLiveRecyclerView; + + private FamilySelectFriendActivity activity; + + private FamilyAttentionListAdapter adapter; + + public static Fragment newInstance() { + return new FamilyAttentionFragment(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof FamilySelectFriendActivity){ + this.activity = (FamilySelectFriendActivity) activity; + } + } + @Override + public int getRootLayoutId() { + return R.layout.fragment_family_attention; + } + + @Override + public void onFindViews() { + swipeRefresh = (SwipeRefreshLayout) getView().findViewById(R.id.swipe_refresh); + userLiveRecyclerView = (RecyclerView) getView().findViewById(R.id.user_live_recyclerView); + + } + + @Override + public void onSetListener() { + swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getMvpPresenter().refreshData(); + } + }); + + + } + + @Override + public void initiate() { + userLiveRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false)); + + adapter = new FamilyAttentionListAdapter(null); + adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + AttentionInfo item = (AttentionInfo) adapter.getData().get(position); + UserInfo userInfo = new UserInfo(); + userInfo.setUid(item.getUid()); + userInfo.setNick(item.getNick()); + userInfo.setAvatar(item.getAvatar()); + activity.onSelectFriend(userInfo); + } + }); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData(); + } + }, userLiveRecyclerView); + + userLiveRecyclerView.setAdapter(adapter); + + + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())){ + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData(); + } + } + + @Override + public void onRefreshData(List attentionInfoList) { + swipeRefresh.setRefreshing(false); + if (!ListUtils.isListEmpty(attentionInfoList)){ + adapter.setNewData(attentionInfoList); + } else { + showNoData(getString(R.string.no_attention_text)); + } + } + + @Override + public void onRefreshDataFail(String error) { + swipeRefresh.setRefreshing(false); + showNetworkErr(); + toast(error); + } + + @Override + public void onLoadMoreData(List attentionInfoList) { + adapter.loadMoreComplete(); + if (!ListUtils.isListEmpty(attentionInfoList)){ + adapter.addData(attentionInfoList); + }else { + adapter.loadMoreEnd(true); + } + } + + @Override + public void onLoadMoreDataFail(String error) { + adapter.loadMoreComplete(); + adapter.loadMoreFail(); + toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyEmptyFragment.java b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyEmptyFragment.java new file mode 100644 index 000000000..86a976825 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyEmptyFragment.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.family.view.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.AbsStatusFragment; + +/** + * Created by xujiexing on 14-4-9. + */ +public class FamilyEmptyFragment extends AbsStatusFragment { + + private View.OnClickListener mOnClickListener; + private LinearLayout rlCenter; + + /** + * 通过设置负数top以达到有title状态下居中,无title状态下默认居中 + */ + public static FamilyEmptyFragment newInstance(int topPx) { + FamilyEmptyFragment fragment = new FamilyEmptyFragment(); + Bundle bundle = new Bundle(); + bundle.putInt("topPx", topPx); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_family_empty, container, false); + + rlCenter = view.findViewById(R.id.rl_family_empty_center); + + Bundle bundle = this.getArguments(); + if (bundle != null) { + int topPx = bundle.getInt("topPx", 0); + setRlCenterTop(topPx); + } + + TextView textView = view.findViewById(R.id.tv_family_plaza); + textView.setOnClickListener(v -> { + if (mOnClickListener != null) { + mOnClickListener.onClick(v); + } + }); + return view; + } + + /** + * @param topPx px + */ + public void setRlCenterTop(int topPx) { + if (rlCenter != null) { + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) rlCenter.getLayoutParams(); + layoutParams.setMargins(layoutParams.leftMargin, topPx, layoutParams.rightMargin, layoutParams.bottomMargin); + rlCenter.setLayoutParams(layoutParams); + } + } + + public void setOnClickListener(View.OnClickListener onClickListener) { + this.mOnClickListener = onClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFansListFragment.java b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFansListFragment.java new file mode 100644 index 000000000..458935544 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFansListFragment.java @@ -0,0 +1,134 @@ +package com.yizhuan.erban.family.view.fragment; + +import android.app.Activity; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyFansListFragmentView; +import com.yizhuan.erban.family.view.activity.FamilySelectFriendActivity; +import com.yizhuan.erban.family.view.adapter.FamilyFansViewAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.family.presenter.FamilyFansListPresenter; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; +import com.yizhuan.xchat_android_core.user.bean.FansListInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ +@CreatePresenter(FamilyFansListPresenter.class) +public class FamilyFansListFragment extends BaseMvpFragment + implements IFamilyFansListFragmentView { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + private FamilySelectFriendActivity activity; + private FamilyFansViewAdapter adapter; + + public static Fragment newInstances() { + return new FamilyFansListFragment(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof FamilySelectFriendActivity){ + this.activity = (FamilySelectFriendActivity) activity; + } + } + @Override + public int getRootLayoutId() { + return R.layout.fragment_family_fans_list; + } + + @Override + public void onFindViews() { + swipeRefresh = (SwipeRefreshLayout) getView().findViewById(R.id.swipe_refresh); + recyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view); + + } + + @Override + public void onSetListener() { + swipeRefresh.setOnRefreshListener(() -> { + getMvpPresenter().refreshData(); + }); + + } + + @Override + public void initiate() { + recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)); + adapter = new FamilyFansViewAdapter(null); + adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + FansInfo item = (FansInfo) adapter.getData().get(position); + UserInfo userInfo = new UserInfo(); + userInfo.setUid(item.getUid()); + userInfo.setNick(item.getNick()); + userInfo.setAvatar(item.getAvatar()); + activity.onSelectFriend(userInfo); + } + }); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData(); + } + },recyclerView); + recyclerView.setAdapter(adapter); + + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())){ + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData(); + } + } + + @Override + public void onRefreshData(FansListInfo fansListInfo) { + swipeRefresh.setRefreshing(false); + adapter.setNewData(fansListInfo.getFansList()); + } + + @Override + public void onRefreshDataFail(String message) { + swipeRefresh.setRefreshing(false); + showNetworkErr(); + toast(message); + } + + @Override + public void onLoadMoreData(FansListInfo fansListInfo) { + adapter.loadMoreComplete(); + if (!ListUtils.isListEmpty(fansListInfo.getFansList())){ + adapter.addData(fansListInfo.getFansList()); + }else { + adapter.setEnableLoadMore(false); + adapter.loadMoreEnd(true); + } + } + + + + @Override + public void onLoadMoreDataFail(String message) { + adapter.loadMoreComplete(); + adapter.loadMoreFail(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFriendListFragment.java b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFriendListFragment.java new file mode 100644 index 000000000..c27c09822 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/family/view/fragment/FamilyFriendListFragment.java @@ -0,0 +1,146 @@ +package com.yizhuan.erban.family.view.fragment; + +import android.content.Context; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.family.contract.viewinterface.IFamilyFriendListFragmentView; +import com.yizhuan.erban.family.view.activity.FamilySelectFriendActivity; +import com.yizhuan.erban.family.view.adapter.FamilyFriendListAdapter; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.family.presenter.FamilyFriendListPresenter; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/7/4 + */ +@CreatePresenter(FamilyFriendListPresenter.class) +public class FamilyFriendListFragment extends BaseMvpFragment + implements IFamilyFriendListFragmentView { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + private FamilyFriendListAdapter adapter; + + FamilySelectFriendActivity activity; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof FamilySelectFriendActivity) { + activity = (FamilySelectFriendActivity) context; + } + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_family_friend_list; + } + + public static Fragment newInstances() { + return new FamilyFriendListFragment(); + } + + @Override + public void onFindViews() { + swipeRefresh = (SwipeRefreshLayout) getView().findViewById(R.id.swipe_refresh); + recyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view); + + } + + @Override + public void onSetListener() { + swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getMvpPresenter().refreshData(); + } + }); + } + + @Override + public void initiate() { + recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL,false)); + adapter = new FamilyFriendListAdapter(getContext(),null); + adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + UserInfo userInfo = (UserInfo) adapter.getData().get(position); + activity.onSelectFriend(userInfo); + } + }); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData(); + } + },recyclerView); + recyclerView.setAdapter(adapter); + + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())) { + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData(); + } + } + + @Override + public void onReloadData() { + super.onReloadData(); + swipeRefresh.setRefreshing(true); + getMvpPresenter().refreshData(); + } + + @Override + public void onRefreshData(List userInfos) { + swipeRefresh.setRefreshing(false); + if (!ListUtils.isListEmpty(userInfos)) { + adapter.setNewData(userInfos); + }else { + showNoData(getString(R.string.no_frenids_text)); + } + } + + @Override + public void onRefreshDataFail(String message) { + swipeRefresh.setRefreshing(false); + showNetworkErr(); + toast(message); + } + + @Override + public void onLoadMoreData(List userInfos) { + adapter.loadMoreComplete(); + if (!ListUtils.isListEmpty(userInfos)){ + adapter.addData(userInfos); + }else { + adapter.setEnableLoadMore(false); + adapter.loadMoreEnd(true); + } + } + + + + @Override + public void onLoadMoreDataFail(String message) { + adapter.loadMoreComplete(); + adapter.loadMoreFail(); + toast(message); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/friend/Holder.java b/app/src/main/java/com/yizhuan/erban/friend/Holder.java new file mode 100644 index 000000000..a99fcea7a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/friend/Holder.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.friend; + +/** + * Created by MadisonRong on 06/06/2018. + */ + +public class Holder { +} diff --git a/app/src/main/java/com/yizhuan/erban/friend/action/AbstractSelectFriendAction.java b/app/src/main/java/com/yizhuan/erban/friend/action/AbstractSelectFriendAction.java new file mode 100644 index 000000000..02e9de5dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/friend/action/AbstractSelectFriendAction.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.friend.action; + +import android.content.Context; + +import com.yizhuan.erban.common.widget.dialog.DialogManager; + +/** + * Created by MadisonRong on 06/06/2018. + */ + +public abstract class AbstractSelectFriendAction { + + public static final String KEY_TYPE = "key_type"; + public static final int TYPE_NORMAL = 0; + public static final int TYPE_CAR = 1; + public static final int TYPE_WEAR = 2; + public static final int TYPE_INVITE = 3; + public static final int TYPE_SHARE = 4; + public static final int ROOM_MSG = 5; + /** + * 世界动态 + */ + public static final int TYPE_WORLD_DYNAMIC = 6; + /** + * 模厅的搜索 + */ + public static final int TYPE_MODULE_HALL = 5; + + protected Context context; + protected DialogManager dialogManager; + + public AbstractSelectFriendAction() { + dialogManager = new DialogManager(context); + dialogManager.setCanceledOnClickOutside(false); + } + + abstract protected void showSureDialog(T data, String targetName, String targetUid); + + public DialogManager getDialogManager() { + return dialogManager; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/friend/action/DefaultSelectFriendAction.java b/app/src/main/java/com/yizhuan/erban/friend/action/DefaultSelectFriendAction.java new file mode 100644 index 000000000..d41d6d03a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/friend/action/DefaultSelectFriendAction.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.friend.action; + +/** + * Created by MadisonRong on 06/06/2018. + */ + +public class DefaultSelectFriendAction extends AbstractSelectFriendAction { + + @Override + protected void showSureDialog(T data, String targetName, String targetUid) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/friend/action/SelectFriendManager.java b/app/src/main/java/com/yizhuan/erban/friend/action/SelectFriendManager.java new file mode 100644 index 000000000..1124c6b61 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/friend/action/SelectFriendManager.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.friend.action; + +/** + * Created by MadisonRong on 07/06/2018. + */ + +public class SelectFriendManager { + + private SelectFriendManager() {} + + public static SelectFriendManager get() { + return SelectFriendManagerHolder.instance; + } + + private static class SelectFriendManagerHolder { + private static SelectFriendManager instance = new SelectFriendManager(); + } + + public void showSureDialog(int type, String targetId, String nick) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + break; + + case AbstractSelectFriendAction.TYPE_INVITE: + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/friend/view/SelectFriendActivity.java b/app/src/main/java/com/yizhuan/erban/friend/view/SelectFriendActivity.java new file mode 100644 index 000000000..2039d3e40 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/friend/view/SelectFriendActivity.java @@ -0,0 +1,300 @@ +package com.yizhuan.erban.friend.view; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.Fragment; +import android.view.View; + +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.ViewPagerAdapter; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivitySelectFriendBinding; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.home.fragment.AttentionFragment; +import com.yizhuan.erban.team.view.TeamListFragment; +import com.yizhuan.erban.ui.im.friend.FriendListFragment; +import com.yizhuan.erban.ui.relation.FansListFragment; +import com.yizhuan.erban.ui.search.SearchActivity; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.community.dynamic.DynamicModel; +import com.yizhuan.xchat_android_core.community.im.DynamicImMsg; +import com.yizhuan.xchat_android_core.community.im.WorldDynamicAttachment; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; + +@ActLayoutRes(R.layout.activity_select_friend) +public class SelectFriendActivity extends BaseBindingActivity implements CarMagicIndicator.OnItemSelectListener { + + public static final String EXTRA_TARGET_UID = "EXTRA_TARGET_UID"; + public static final String EXTRA_TARGET_NAME = "EXTRA_TARGET_NAME"; + public static final String EXTRA_SESSION_TYPE = "EXTRA_SESSION_TYPE"; + public static final String KEY_SECOND_OPERATOR = "KEY_SECOND_OPERATOR"; + public static final String EXTRA_DYNAMIC_DATA = "extra_dynamic_data"; + + public static final int CODE_REQUEST_TO_SHARE_ROOM = 100; + public static final int CODE_REQUEST_TO_SHARE_FAMILY = 101; + public static final int CODE_REQUEST_TO_SHARE_TEAM = 102; + public static final int CODE_REQUEST_TO_SHARE_H5 = 103; + public static final int CODE_REQUEST_TO_SHARE_MINI_WORLD = 104; + + private int pageLimitSize = 3; + private String[] titles = {"好友", "关注", "粉丝"}; + + private int type; + private int secondOperator = 0; + private boolean needShowTeamTab; + + public static void start(Context context) { + Intent intent = new Intent(context, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + context.startActivity(intent); + } + + public static void startForSharingRoom(Activity activity) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(KEY_SECOND_OPERATOR, CODE_REQUEST_TO_SHARE_ROOM); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SHARE_ROOM); + } + + public static void startForSharingFamily(Activity activity) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(KEY_SECOND_OPERATOR, CODE_REQUEST_TO_SHARE_FAMILY); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SHARE_FAMILY); + } + + public static void startForSharingMiniWorld(Activity activity) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(KEY_SECOND_OPERATOR, CODE_REQUEST_TO_SHARE_MINI_WORLD); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SHARE_MINI_WORLD); + } + + public static void startForSharingTeam(Activity activity) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(KEY_SECOND_OPERATOR, CODE_REQUEST_TO_SHARE_TEAM); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SHARE_TEAM); + } + + public static void startForSharingH5(Activity activity) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(KEY_SECOND_OPERATOR, CODE_REQUEST_TO_SHARE_H5); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SHARE_H5); + } + + public static void startForSharingDynamic(Activity activity, DynamicImMsg msg) { + Intent intent = new Intent(activity, SelectFriendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC); + intent.putExtra(EXTRA_DYNAMIC_DATA, msg); + activity.startActivity(intent); + } + + @Override + public void init() { + type = getIntent().getIntExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_NORMAL); + + secondOperator = getIntent().getIntExtra(KEY_SECOND_OPERATOR, 0); + + initTitleBar(getString(R.string.title_select_friend)); + + mBinding.titleBar.addAction(new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_send_search; + } + + @Override + public void performAction(View view) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + SearchActivity.startForSharing(SelectFriendActivity.this, secondOperator); + break; + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + DynamicImMsg dynamicImMsg = (DynamicImMsg) getIntent().getSerializableExtra(EXTRA_DYNAMIC_DATA); + if (dynamicImMsg == null) { + return; + } + SearchActivity.startForShareDynamic(SelectFriendActivity.this, dynamicImMsg); + break; + } + } + }); + + needShowTeamTab = FamilyModel.Instance().getMyFamily() != null && + type == AbstractSelectFriendAction.TYPE_SHARE && secondOperator != 0; + if (needShowTeamTab) { + pageLimitSize = 4; + titles = new String[]{"好友", "关注", "粉丝", "群"}; + } + mBinding.viewpager.setOffscreenPageLimit(pageLimitSize); + mBinding.viewpager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getFragment(), titles)); + + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(1, getString(R.string.tab_title_friends))); + tabInfoList.add(new TabInfo(2, getString(R.string.tab_title_attentions))); + tabInfoList.add(new TabInfo(3, getString(R.string.tab_title_fans))); + if (needShowTeamTab) { + tabInfoList.add(new TabInfo(4, getString(R.string.tab_title_team))); + } + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mBinding.viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mBinding.viewIndicator, mBinding.viewpager); + } + + private List getFragment() { + List list = new ArrayList<>(); + list.add(FriendListFragment.newInstance(true, type)); + list.add(AttentionFragment.newInstance(type)); + list.add(FansListFragment.newInstanceForSelect(type)); + if (needShowTeamTab) { + list.add(TeamListFragment.newInstanceForSelect(type)); + } + return list; + } + + @Override + public void onItemSelect(int position) { + mBinding.viewpager.setCurrentItem(position); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SearchActivity.CODE_REQUEST_TO_SEARCH && resultCode == RESULT_OK) { + setResult(RESULT_OK, data); + finish(); + } + } + + public void showSureDialog(String targetId, String avatar, String nick) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + String msg = ""; + if (CODE_REQUEST_TO_SHARE_FAMILY == secondOperator) { + msg = getResources().getString(R.string.family_invite_friends_slogan); + } + getDialogManager().showInAppSharingConfirmDialog(avatar, nick, msg, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + Intent intent = new Intent(); + intent.putExtra(EXTRA_TARGET_UID, targetId); + intent.putExtra(EXTRA_TARGET_NAME, nick); + setResult(Activity.RESULT_OK, intent); + intent.putExtra(EXTRA_SESSION_TYPE, SessionType.P2P); + finish(); + } + }); + break; + + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + if (getIntent() == null) { + return; + } + DynamicImMsg dynamicImMsg = (DynamicImMsg) getIntent().getSerializableExtra(EXTRA_DYNAMIC_DATA); + if (dynamicImMsg == null) { + return; + } + getDialogManager().showOkCancelDialog("确认分享给" + nick + "?", () -> { + //发出自定义消息 + IMMessage message = WorldDynamicAttachment.createShareMsg(dynamicImMsg, targetId); + IMNetEaseManager.get().sendMessage(message) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Boolean aBoolean, String error) { + super.accept(aBoolean, error); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + SingleToastUtil.showToast("分享成功"); + DynamicModel.get().reportShare(dynamicImMsg.getPublishUid(), + dynamicImMsg.getWorldId(), dynamicImMsg.getDynamicId()) + .subscribe(); + } + } + }); + finish(); + }); + break; + default: + + break; + } + } + + public void shareToTeam(String sessionId, String avatar, String name) { + switch (type) { + case AbstractSelectFriendAction.TYPE_SHARE: + String msg = ""; + if (CODE_REQUEST_TO_SHARE_FAMILY == secondOperator) { + msg = getResources().getString(R.string.family_invite_friends_slogan); + } + getDialogManager().showInAppSharingConfirmDialog(avatar, name, msg, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + Intent intent = new Intent(); + intent.putExtra(EXTRA_TARGET_UID, sessionId); + intent.putExtra(EXTRA_TARGET_NAME, name); + intent.putExtra(EXTRA_SESSION_TYPE, SessionType.TEAM); + setResult(Activity.RESULT_OK, intent); + finish(); + } + }); + break; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/guide/GuideActivity.java b/app/src/main/java/com/yizhuan/erban/guide/GuideActivity.java new file mode 100644 index 000000000..424178ae6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/guide/GuideActivity.java @@ -0,0 +1,121 @@ +package com.yizhuan.erban.guide; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +import java.net.URI; +import butterknife.BindView; +import butterknife.ButterKnife; + +public class GuideActivity extends BaseActivity { + + public final static String KEY_FIRST_GUIDE = "key_first_guide"; + + private final int[] mTopImages = new int[]{ + R.drawable.ic_guide_top_1, + R.drawable.ic_guide_top_2, + R.drawable.ic_guide_top_3 + }; + + private final int[] mCenterImages = new int[]{ + R.drawable.ic_guide_center_1, + R.drawable.ic_guide_center_2, + R.drawable.ic_guide_center_3 + }; + + private final int[] mBottomImages = new int[]{ + R.drawable.ic_guide_bottom_1, + R.drawable.ic_guide_bottom_2, + R.drawable.ic_guide_bottom_3 + }; + + @BindView(R.id.view_pager) + ViewPager viewPager; + + public static void start(Context context) { + Boolean flag = (Boolean) SharedPreferenceUtils.get(KEY_FIRST_GUIDE, true); + if (flag != null && flag) { + SharedPreferenceUtils.put(KEY_FIRST_GUIDE, false); + context.startActivity(new Intent(context, GuideActivity.class)); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_guide); + ButterKnife.bind(this); + + + if (mTopImages.length != mCenterImages.length) { + return; + } + if (mTopImages.length != mBottomImages.length) { + return; + } + viewPager.setAdapter(new PagerAdapter() { + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + View view = View.inflate(GuideActivity.this, R.layout.pager_guide, null); +// ImageView iv_guide_pager_corner = view.findViewById(R.id.iv_guide_pager_corner); +// iv_guide_pager_corner.getLayoutParams().height = +// UIUtil.getScreenWidth(context) * 286 / 750; +// iv_guide_pager_corner.setImageResource(cornerArray[position]); +// +// ImageView iv_guide_pager_top = view.findViewById(R.id.iv_guide_pager_top); +// iv_guide_pager_top.setImageResource(textArray[position]); +// ImageView iv_guide_pager_bottom = view.findViewById(R.id.iv_guide_pager_bottom); +// iv_guide_pager_bottom.getLayoutParams().height = +// UIUtil.getScreenWidth(context) * 1048 / 750; +// iv_guide_pager_bottom.setImageResource(picArray[position]); +// ImageView iv_guide_pager_use = view.findViewById(R.id.iv_guide_pager_use); +// if (position == textArray.length - 1) { +// iv_guide_pager_use.setVisibility(View.VISIBLE); +// } else { +// iv_guide_pager_use.setVisibility(View.GONE); +// } + ImageView ivTop = view.findViewById(R.id.iv_top); + ImageView ivCenter = view.findViewById(R.id.iv_center); + ImageView ivBottom = view.findViewById(R.id.iv_bottom); + + ivTop.setImageResource(mTopImages[position]); + ivCenter.setImageResource(mCenterImages[position]); + ivBottom.setImageResource(mBottomImages[position]); + + ivBottom.setOnClickListener(v -> finish()); + ivBottom.setClickable(position == mBottomImages.length - 1); + container.addView(view); + return view; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView((View) object); + } + + @Override + public int getCount() { + return mTopImages.length; + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/headline/HeadLineFragment.java b/app/src/main/java/com/yizhuan/erban/headline/HeadLineFragment.java new file mode 100644 index 000000000..6b4708910 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/headline/HeadLineFragment.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.headline; + +import android.os.Bundle; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.CommonWebViewFragment; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.fragment_common_web_view) +public class HeadLineFragment extends CommonWebViewFragment { + + public static HeadLineFragment newInstance() { + return new HeadLineFragment(); + } + + @Override + protected void onInitArguments(Bundle bundle) { + url = UriProvider.getErbanTopMessageUrl(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/headline/MyHeadLineFragment.java b/app/src/main/java/com/yizhuan/erban/headline/MyHeadLineFragment.java new file mode 100644 index 000000000..b315c1b01 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/headline/MyHeadLineFragment.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.headline; + +import android.os.Bundle; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.CommonWebViewFragment; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.fragment_common_web_view) +public class MyHeadLineFragment extends CommonWebViewFragment { + + public static MyHeadLineFragment newInstance() { + return new MyHeadLineFragment(); + } + + @Override + protected void onInitArguments(Bundle bundle) { + url = UriProvider.getRelatedToMeHeadLineUrl(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/activity/AllGameActivity.java b/app/src/main/java/com/yizhuan/erban/home/activity/AllGameActivity.java new file mode 100644 index 000000000..d65079bf1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/activity/AllGameActivity.java @@ -0,0 +1,227 @@ +package com.yizhuan.erban.home.activity; + +import android.content.Intent; +import android.support.v7.widget.GridLayoutManager; +import android.text.SpannableString; +import android.text.TextUtils; +import android.view.View; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.game.MatchActivity; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityRecyclerviewBindBinding; +import com.yizhuan.erban.databinding.ItemHomeGameBinding; +import com.yizhuan.erban.home.model.AllGameVm; +import com.yizhuan.erban.ui.patriarch.help.LimitEnterRoomHelper; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +@ActLayoutRes(R.layout.activity_recyclerview_bind) +public class AllGameActivity extends BaseBindingActivity { + private AllGameVm viewModel; + + private LimitEnterRoomHelper limitEnterRoomHelper; + + @Override + protected void init() { + initTitleBar("全部游戏"); + mTitleBar.addAction(new TitleBar.ImageAction(R.drawable.icon_game_top) { + @Override + public void performAction(View view) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.gamepage_homepage, "游戏榜单"); + CommonWebViewActivity.start(AllGameActivity.this, UriProvider.IM_SERVER_URL + XChatConstants.GAME_ROOK); + } + }); + viewModel = new AllGameVm(); + mBinding.setViewmodel(viewModel); + mBinding.recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); + BaseAdapter adapter = new BaseAdapter(R.layout.item_home_game, BR.gameInfo) { + @Override + protected void convert(BindingViewHolder helper, Object item) { + super.convert(helper, item); + if (helper.getAdapterPosition() == 0) { + ItemHomeGameBinding binding = (ItemHomeGameBinding) helper.getBinding(); + binding.image.setImageResource(R.drawable.game_all_find_player); + } + } + }; + adapter.setOnItemClickListener((adap, view, position) -> { + if (position == 0) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.all_game_player, "全部游戏页-找玩友入口"); + startActivity(new Intent(AllGameActivity.this, UserMatchActivity.class)); + } else { + startMatch(adapter, position); + } + }); + mBinding.recyclerView.setAdapter(adapter); + + viewModel.loadData(false).subscribe(); + } + + + private void startMatch(BaseAdapter adapter, int position) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.all_game_choice, "选择游戏"); + + getDialogManager().showProgressDialog(AllGameActivity.this); + AvRoomModel.get().requestRoomInfoV2(String.valueOf(AuthModel.get().getCurrentUid()), 0) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(RoomInfo data, Throwable throwable) { + super.acceptThrowable(data, throwable); + getDialogManager().dismissDialog(); + if (data != null) { + if (data.isValid()) { + closeRoom(adapter, position); + } else if (AvRoomDataManager.get().isRoomOwner()) { + exitRoom(adapter, position); + } else { + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + } + + @Override + public void onFail(int code, String error) { + } + }); + MatchActivity.start(AllGameActivity.this, adapter.getItem(position)); + } + } else if (throwable != null) { + if (throwable instanceof PmRoomLimitException) { + getLimitEnterRoomHelper().handleThisContext( + context, + throwable.getMessage(), false, + () -> { + }); + } else if (!TextUtils.isEmpty(throwable.getMessage())) { + toast(throwable.getMessage()); + } + } + } + }); + + } + + private void exitRoom(BaseAdapter adapter, int position) { + if (DemoCache.readFirstMatchDialog()) { + DemoCache.saveFirstMatchDialog(); + getDialogManager().showOkCancelDialog("匹配玩家将关闭当前房间(进房限制取消)并解散房内的用户", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(AllGameActivity.this); + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + getDialogManager().dismissDialog(); + MatchActivity.start(AllGameActivity.this, adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("退出房间失败"); + } + }); + + } + }); + } else { + getDialogManager().showProgressDialog(AllGameActivity.this); + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + getDialogManager().dismissDialog(); + MatchActivity.start(AllGameActivity.this, adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("退出房间失败"); + } + }); + } + } + + private void closeRoom(BaseAdapter adapter, int position) { + if (DemoCache.readFirstMatchDialog()) { + DemoCache.saveFirstMatchDialog(); + getDialogManager().showOkCancelWithTitleDialog("匹配玩家", + new SpannableString("将关闭当前房间(进房限制取消)并解散房内的用户"), + "确认", + "取消", + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(AllGameActivity.this); + AvRoomModel.get().quitRoomForOurService(new CallBack() { + @Override + public void onSuccess(String data) { + getDialogManager().dismissDialog(); + MatchActivity.start(AllGameActivity.this, adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("关闭房间失败"); + } + }); + + } + }); + } else { + getDialogManager().showProgressDialog(AllGameActivity.this); + AvRoomModel.get().quitRoomForOurService(new CallBack() { + @Override + public void onSuccess(String data) { + getDialogManager().dismissDialog(); + MatchActivity.start(AllGameActivity.this, adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("关闭房间失败"); + } + }); + } + + } + + public LimitEnterRoomHelper getLimitEnterRoomHelper() { + if (limitEnterRoomHelper == null) { + limitEnterRoomHelper = new LimitEnterRoomHelper(); + } + return limitEnterRoomHelper; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/activity/NewUserListActivity.java b/app/src/main/java/com/yizhuan/erban/home/activity/NewUserListActivity.java new file mode 100644 index 000000000..03893eb5b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/activity/NewUserListActivity.java @@ -0,0 +1,138 @@ +package com.yizhuan.erban.home.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.home.adapter.FindNewUserListAdapter; +import com.yizhuan.erban.home.presenter.NewUserListPresenter; +import com.yizhuan.erban.home.view.INewUserListActivityView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.SpacingDecoration; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +@CreatePresenter(NewUserListPresenter.class) +public class NewUserListActivity extends BaseMvpActivity + implements INewUserListActivityView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + + private SwipeRefreshLayout srlRefreshContainer; + private RecyclerView rvList; + private FindNewUserListAdapter adapter; + + public static void start(Context context) { + Intent intent = new Intent(context, NewUserListActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_user_list); + initTitleBar(getString(R.string.find_newer_list_title)); + + srlRefreshContainer = (SwipeRefreshLayout) findViewById(R.id.srl_refresh_container); + rvList = (RecyclerView) findViewById(R.id.rv_list); + + rvList.setLayoutManager(new GridLayoutManager(this, 3)); + rvList.addItemDecoration(new SpacingDecoration( + Utils.dip2px(this, 10), + Utils.dip2px(this, 20), + false)); + + adapter = new FindNewUserListAdapter(this, null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, rvList); + rvList.setAdapter(adapter); + + srlRefreshContainer.setOnRefreshListener(this); + } + + + @Override + protected void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())) { + srlRefreshContainer.setRefreshing(true); + onRefresh(); + } + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + srlRefreshContainer.setRefreshing(true); + onRefresh(); + } + + @Override + public void onRefresh() { + getMvpPresenter().refreshData() + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + srlRefreshContainer.setRefreshing(false); + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List userInfos) { + if (ListUtils.isListEmpty(userInfos)) { + showNoData(); + return; + } + adapter.setNewData(userInfos); + } + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData() + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List userInfos) { + if (ListUtils.isListEmpty(userInfos)) { + adapter.loadMoreEnd(true); + return; + } + adapter.addData(userInfos); + adapter.loadMoreComplete(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/activity/UserMatchActivity.java b/app/src/main/java/com/yizhuan/erban/home/activity/UserMatchActivity.java new file mode 100644 index 000000000..fd582f726 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/activity/UserMatchActivity.java @@ -0,0 +1,198 @@ +package com.yizhuan.erban.home.activity; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.text.TextUtils; +import android.view.View; + +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityUserMatchBinding; +import com.yizhuan.erban.home.dialog.FiltrateDialog; +import com.yizhuan.erban.home.model.UserMatchVm; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.patriarch.help.LimitEnterRoomHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +@ActLayoutRes(R.layout.activity_user_match) +public class UserMatchActivity extends BaseBindingActivity { + private UserMatchVm viewModel; + private Disposable subscribe; + private SVGAParser mSVGAParser; + + @Override + protected void init() { + viewModel = new UserMatchVm(); + mBinding.setViewModel(viewModel); + viewModel.setMatchConsumer(s -> { + matchSucces(s.getUid()); + }); + + startAnim(mBinding.wave2); + mBinding.wave3.post(() -> mBinding.wave3.setVisibility(View.GONE)); + mBinding.wave3.postDelayed(() -> { + if (viewModel.pageType.get() == UserMatchVm.START) { + mBinding.wave3.setVisibility(View.VISIBLE); + } + startAnim(mBinding.wave3); + }, 1200); + + mSVGAParser = new SVGAParser(this); + playSvag(UserMatchVm.SVGA_START); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void onDestroy() { + viewModel.destroy(); + super.onDestroy(); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + case R.id.tv_match: + viewModel.changePageType(pmConsumer); + if (subscribe != null) { + subscribe.dispose(); + } + if (viewModel.pageType.get() == UserMatchVm.MATCHING) { + playSvag(UserMatchVm.SVGA_MATCHING); + } else if (viewModel.pageType.get() == UserMatchVm.START) { + playSvag(UserMatchVm.SVGA_START); + } + subscribe = Observable.interval(1, TimeUnit.SECONDS) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> { + if (aLong == 20) { + toast("匹配超时,请尝试重新匹配"); + viewModel.changePageType(pmConsumer); + playSvag(UserMatchVm.SVGA_START); + } + mBinding.tvTime.setText("等待时长 " + (aLong + 1) + " 秒"); + }); + break; + case R.id.tv_filtrate: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_player_choice, "筛选条件"); + new FiltrateDialog(this, viewModel).show(); + break; + } + + } + + private void matchSucces(long uid) { + if (subscribe != null) { + subscribe.dispose(); + } +// startAlphaAnim(mBinding.tvText); +// startAlphaAnim(mBinding.tvTime); + mBinding.svgaImageview.animate().scaleX(0) + .scaleY(0).setDuration(500) + .setListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + mBinding.tvTime.setText("请开始你的表演"); + mBinding.tvNick.animate().alpha(1).setDuration(400).start(); + mBinding.tvRightNick.animate().alpha(1).setDuration(400).start(); + mBinding.llSelf.animate().translationX(-UIUtil.dip2px(UserMatchActivity.this, 60)) + .setDuration(400).start(); + mBinding.llOther.animate().translationX(UIUtil.dip2px(UserMatchActivity.this, 60)) + .setDuration(400).start(); + mBinding.llOther.postDelayed(() -> { + NimP2PMessageActivity.startByMatch(UserMatchActivity.this, uid + ""); + finish(); + }, 2700); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }) + .start(); + } + + private void playSvag(String effect) { + if (TextUtils.isEmpty(effect)) return; + try { + mSVGAParser.parse(new URL(effect), + new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + mBinding.svgaImageview.setImageDrawable(new SVGADrawable(svgaVideoEntity)); + mBinding.svgaImageview.startAnimation(); + } + + @Override + public void onError() { + mBinding.svgaImageview.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + private void startAnim(View view) { + ObjectAnimator transY = ObjectAnimator.ofFloat(view, "scaleY", 1, 1.4f); + transY.setRepeatCount(ValueAnimator.INFINITE); + transY.setDuration(2400).start(); + ObjectAnimator transX = ObjectAnimator.ofFloat(view, "scaleX", 1, 1.15f); + transX.setRepeatCount(ValueAnimator.INFINITE); + transX.setDuration(2400).start(); + ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 0.5f, 0); + alpha.setRepeatCount(ValueAnimator.INFINITE); + alpha.setDuration(2400).start(); + } + + private void startAlphaAnim(View view) { + ObjectAnimator transY = ObjectAnimator.ofFloat(view, "alpha", 1, 0, 1); + transY.setDuration(800); + transY.start(); + } + + private Consumer pmConsumer = throwable -> { + if (throwable instanceof PmRoomLimitException) { + new LimitEnterRoomHelper().handleThisContext(context, throwable.getMessage(), + false, null); + } else { + toast(throwable.getMessage()); + } + }; +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/BannerAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/BannerAdapter.java new file mode 100644 index 000000000..919c4c78c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/BannerAdapter.java @@ -0,0 +1,115 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.jude.rollviewpager.adapter.StaticPagerAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.utils.CommonJumpHelper; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import java.util.List; + +/** + * @author Administrator + * @date 2017/8/7 + */ + +public class BannerAdapter extends StaticPagerAdapter { + private Context context; + private List bannerInfoList; + private LayoutInflater mInflater; + private boolean isHomeGame; + private int roundingRadius = -1; + private OnItemClickListener mOnItemClickListener; + + public BannerAdapter(List bannerInfoList, Context context) { + this.context = context; + this.bannerInfoList = bannerInfoList; + mInflater = LayoutInflater.from(context); + } + + public void setHomeGame(boolean homeGame) { + isHomeGame = homeGame; + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.mOnItemClickListener = onItemClickListener; + } + + @Override + public View getView(ViewGroup container, int position) { + BannerInfo bannerInfo = bannerInfoList.get(position); + ImageView imgBanner = (ImageView) mInflater.inflate(R.layout.banner_page_item, container, false); + if (bannerInfo == null) return imgBanner; + String url = bannerInfo.getSkipUri(); + // if (isHomeGame){ + if (roundingRadius == -1) { + ImageLoadUtils.loadGameBannerRoundBackground(context, bannerInfo.getBannerPic(), imgBanner); + } else { + ImageLoadUtils.loadBannerRoundBackground(context, bannerInfo.getBannerPic(), imgBanner, roundingRadius); + } +// }else { +// ImageLoadUtils.loadBannerRoundBackground(context, bannerInfo.getBannerPic(), imgBanner); +// } + imgBanner.setOnClickListener(v -> { +// if (TextUtils.isEmpty(url)) return; +// if (bannerInfo.getSkipType() == 3) { +// Intent intent = new Intent(context, CommonWebViewActivity.class); +// intent.putExtra("url", url); +// context.startActivity(intent); +// } else if (bannerInfo.getSkipType() == 2) { +// if (TextUtils.isEmpty(url)) return; +// try { +// AVRoomActivity.start(context, Long.valueOf(url)); +// } catch (NumberFormatException e) { +// e.printStackTrace(); +// } +// } + CommonJumpHelper.bannerJump(context, bannerInfo); + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(position, bannerInfo); + } + if (isHomeGame) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.game_homepage_banner_click, "选中banner点击"); + } + }); + return imgBanner; + } + + public void setRoundingRadius(int roundingRadius) { + this.roundingRadius = roundingRadius; + } + + @Override + public int getCount() { + return bannerInfoList == null ? 0 : bannerInfoList.size(); + + } + + public void setData(List bannerInfos) { + this.bannerInfoList = bannerInfos; + } + + + public interface OnItemClickListener { + /** + * item点击事件,用于做banner点击埋点 + * + * @param position + * @param bannerInfo + */ + void onItemClick(int position, BannerInfo bannerInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/CommonMagicIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/CommonMagicIndicatorAdapter.java new file mode 100644 index 000000000..765f38576 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/CommonMagicIndicatorAdapter.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + *

公共多个滑动tab样式

+ * + * @author Administrator + * @date 2017/11/15 + */ +public class CommonMagicIndicatorAdapter extends CommonNavigatorAdapter { + + private Context mContext; + private List mTitleList; + private int mBottomMargin; + + public CommonMagicIndicatorAdapter(Context context, List titleList, int bottomMargin) { + mContext = context; + mTitleList = titleList; + mBottomMargin = bottomMargin; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_666666)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_000000)); + scaleTransitionPagerTitleView.setMinScale(1); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(i).getName()); + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT); + indicator.setLineHeight(UIUtil.dip2px(mContext, 2.5)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 1.25)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 27)); + indicator.setColors(context.getResources().getColor(R.color.appColor)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/CommunityNoticeAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/CommunityNoticeAdapter.java new file mode 100644 index 000000000..672d710ca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/CommunityNoticeAdapter.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.home.adapter; + +import android.text.TextUtils; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.RectRoundImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.community.bean.CommunityNoticeInfo; +import com.yizhuan.xchat_android_core.community.bean.DynamicMedia; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +public class CommunityNoticeAdapter extends BaseQuickAdapter { + + public CommunityNoticeAdapter() { + super(R.layout.item_community_notice_list); + } + + @Override + protected void convert(BaseViewHolder helper, CommunityNoticeInfo item) { + + if (item == null) { + return; + } + + CircleImageView circleImageView = helper.getView(R.id.civ_avatar_community_notice_list); + ImageLoadUtilsV2.loadImage(circleImageView, item.getAvatar()); + + String worldName = item.getWorldName(); + helper.setText(R.id.tv_name_mini_world, worldName) + .setGone(R.id.tv_name_mini_world, !TextUtils.isEmpty(worldName)); + helper.setText(R.id.tv_name_community_notice_list, item.getNick()); + helper.setText(R.id.tv_age_community_notice_list, String.valueOf(item.getAge())); + + helper.setGone(R.id.tv_age_community_notice_list, false) + .setGone(R.id.iv_gender, false); + if (item.isShowAge()) { + helper.setBackgroundRes(R.id.tv_age_community_notice_list, + item.isMale() ? R.drawable.ic_male_community_notice : R.drawable.ic_female_age_community_notice) + .setGone(R.id.tv_age_community_notice_list, true); + } else { + helper.setGone(R.id.iv_gender, true) + .setImageResource(R.id.iv_gender, item.isMale() ? R.drawable.ic_male : R.drawable.ic_female); + } + + helper.setGone(R.id.tv_right_content, false) + .setGone(R.id.rriv_right_content, false); + DynamicMedia dynamicMedia = item.getDynamicRes(); + switch (item.getType()) { + case 0: // 纯文本 + helper.setGone(R.id.tv_right_content, true) + .setText(R.id.tv_right_content, item.getContent()); + break; + case 1: // 语音 + break; + case 2: // 图片 + case 3: // 视频 + helper.setGone(R.id.rriv_right_content, true); + if (dynamicMedia != null) { + RectRoundImageView rectRoundImageView = helper.getView(R.id.rriv_right_content); + ImageLoadUtilsV2.loadImage(rectRoundImageView, dynamicMedia.getResUrl()); + } + break; + + } + + helper.setGone(R.id.tv_label_community_notice_list, false); + helper.setText(R.id.tv_content_community_notice_list, item.getMessage()); + switch (item.getActionType()) { + case 1: // 评论 + if (item.getTargetUid() == AuthModel.get().getCurrentUid()) { + helper.setGone(R.id.tv_label_community_notice_list, true); + } else { + helper.setGone(R.id.tv_label_community_notice_list, false); + } + break; + case 2: // 回复 + // TODO 区分动态/评论 + break; + case 3: // 点赞 + // TODO 区分动态/评论 + break; + } + + helper.setText(R.id.tv_time_community_notice_list, TimeUtils.getTimeStringFromMillis(item.getPublishTime())); + + helper.addOnClickListener(R.id.cl_community_notice_list); + helper.addOnClickListener(R.id.civ_avatar_community_notice_list); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java new file mode 100644 index 000000000..cef191c7b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/ContactsIndicatorAdapter.java @@ -0,0 +1,117 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.v7.widget.AppCompatTextView; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public class ContactsIndicatorAdapter extends CommonNavigatorAdapter { + private List mTitleList; + private Context mContext; + private int mBottomMargin; + + public ContactsIndicatorAdapter(Context mContext, List mTitleList, int bottomMargin) { + this.mTitleList = mTitleList; + this.mContext = mContext; + mBottomMargin = bottomMargin; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + ContactsPagerTitleView categoryPagerTitleView = new ContactsPagerTitleView(context, mTitleList.get(index)); + categoryPagerTitleView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mOnItemSelectListener) { + mOnItemSelectListener.onItemSelect(index); + } + } + }); + return categoryPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(mContext, 3)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 2)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 12)); + indicator.setColors(context.getResources().getColor(R.color.color_34EBDE)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } + + class ContactsPagerTitleView extends AppCompatTextView implements IPagerTitleView { + + + public ContactsPagerTitleView(Context context, String tabInfo) { + super(context); + setWidth(Utils.dip2px(getContext(), 96)); + setHeight(Utils.dip2px(getContext(), 30)); + setTextSize(16); + setText(tabInfo); + setGravity(Gravity.CENTER); + + } + + + @Override + public void onSelected(int index, int totalCount) { +// setBackgroundResource(R.drawable.shape_bg_contact_indicator_item); + setTextColor(getResources().getColor(R.color.color_333333)); + } + + @Override + public void onDeselected(int index, int totalCount) { +// setBackgroundDrawable(null); + setTextColor(getResources().getColor(R.color.color_B3B3B3)); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanRecommendAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanRecommendAdapter.java new file mode 100644 index 000000000..d62dfe9f9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanRecommendAdapter.java @@ -0,0 +1,174 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.LivingIconView; +import com.yizhuan.erban.ui.widget.RoomItemView; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class ErbanRecommendAdapter extends BaseMultiItemQuickAdapter { + + private Context mContext; + private int mRound, mTagHeight, mBadgeHeight; + + public ErbanRecommendAdapter(Context context, @Nullable List data) { + super(data); + addItemType(HomeRoom.TYPE_GIRD, R.layout.item_erban_recommend); + addItemType(HomeRoom.TYPE_LINEAR, R.layout.item_room_recommended); + addItemType(HomeRoom.TYPE_GIRD_EMPTY, R.layout.item_erban_grid_empty); + this.mContext = context; + mRound = Utils.dip2px(mContext, 9); + mTagHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + mBadgeHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + } + private void setLinearTypeData(BaseViewHolder helper, HomeRoom homeRoom) { + RoomItemView roomItemView = helper.getView(R.id.riv_room_view); + roomItemView.bindData(homeRoom); + } + + private void setGridEmptyData(BaseViewHolder helper, HomeRoom homeRoom) { + + } + + @Override + protected void convert(BaseViewHolder helper, HomeRoom homeRoom) { + if (homeRoom.getItemType() == HomeRoom.TYPE_LINEAR) { + setLinearTypeData(helper, homeRoom); + return; + } + if (homeRoom.getItemType() == HomeRoom.TYPE_GIRD_EMPTY) { + setGridEmptyData(helper, homeRoom); + return; + } + + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AVRoomActivity.start(mContext, homeRoom.getUid()); + } + }); + + + LivingIconView livingIconView = helper.getView(R.id.liv_living_icon); + livingIconView.setColor(Color.WHITE); + livingIconView.start(); + + helper.setText(R.id.tv_online_number, mContext.getString(R.string.online_number_text, homeRoom.getOnlineNum())) + .setText(R.id.tv_title, homeRoom.getTitle()); + + helper.getView(R.id.lock_bg).setVisibility(!TextUtils.isEmpty(homeRoom.getRoomPwd()) ? View.VISIBLE : View.GONE); + + ImageView mIvTabLabel = helper.getView(R.id.iv_tab_label); +// +// mIvEmperorRecommend.setVisibility(homeRoom.getIsRecom() > 0 ? View.VISIBLE : View.GONE); +// GlideApp.with(mContext) +// .load(mContext.getResources().getDrawable(R.drawable.ic_king_recommend)) +//// .load(homeRoom.getIsRecom() > 0 ? NobleUtil.getEmperorRecommendTag(7) : 0) +// .fitCenter() +// .into(mIvEmperorRecommend); + + if (homeRoom.getIsRecom() > 0) { + mIvTabLabel.setVisibility(View.VISIBLE); + GlideApp.with(mContext) + .load(mContext.getResources().getDrawable(R.drawable.ic_king_recommend)) + .fitCenter() + .into(mIvTabLabel); + } else if (!TextUtils.isEmpty(homeRoom.badge)) { + mIvTabLabel.setVisibility(View.VISIBLE); + GlideApp.with(mContext) + .load(homeRoom.badge) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { + float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); + int width = Math.round(mBadgeHeight / ratio); + int height = mBadgeHeight; + ViewGroup.LayoutParams params = mIvTabLabel.getLayoutParams(); + params.width = width; + params.height = height; + mIvTabLabel.setLayoutParams(params); + mIvTabLabel.setImageDrawable(drawable); + return true; + } + }) + .into(mIvTabLabel); + + } else + mIvTabLabel.setVisibility(View.INVISIBLE); + +// mIvTabLabel.setVisibility(TextUtils.isEmpty(homeRoom.badge) ? View.INVISIBLE : View.VISIBLE); + +// GlideApp.with(mContext) +// .load(homeRoom.badge) +// .listener(new RequestListener() { +// @Override +// public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { +// return false; +// } +// +// @Override +// public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { +// float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); +// int width = Math.round(mBadgeHeight / ratio); +// int height = mBadgeHeight; +// ViewGroup.LayoutParams params = mIvTabLabel.getLayoutParams(); +// params.width = width; +// params.height = height; +// mIvTabLabel.setLayoutParams(params); +// mIvTabLabel.setImageDrawable(drawable); +// return true; +// } +// }) +// .into(mIvTabLabel); + + + ImageView ivCover = helper.getView(R.id.iv_cover); + if (!TextUtils.isEmpty(homeRoom.getAvatar())) { + ImageLoadUtils.loadAvatarBig(homeRoom.getAvatar(), ivCover, R.drawable.default_cover); + } else { + GlideApp.with(mContext) + .load(R.drawable.default_cover) + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(mRound)) + .into(ivCover); + } + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanTopMessageAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanTopMessageAdapter.java new file mode 100644 index 000000000..abb46a726 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/ErbanTopMessageAdapter.java @@ -0,0 +1,112 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.xchat_android_core.home.bean.TopMessage; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessage; + +import java.util.List; + +/** + * @author jack + * @Description 滚动轮播适配器 + * @Date 2018/5/3 + */ + +public class ErbanTopMessageAdapter extends BetterMarqueeView.Adapter { + private Context context; + private List vmTopMessageList; + + public ErbanTopMessageAdapter(Context context,List vmTopMessageList) { + this.context = context; + this.vmTopMessageList = vmTopMessageList; + } + + @Override + public ErbanTopMessageAdapter.ErBanTopMessageViewHolder onCreateView(ViewGroup parent) { + return new ErBanTopMessageViewHolder(LayoutInflater.from(this.context).inflate(R.layout.item_erban_top_message,parent,false)); + } + + @Override + public void onBindViewHolder(ErbanTopMessageAdapter.ErBanTopMessageViewHolder holder, int position) { + VMTopMessage item = vmTopMessageList.get(position); + + TextView[] textViews = new TextView[]{holder.tvMsg1,holder.tvMsg2}; + for (TextView textView : textViews) { + textView.setText(""); + } + ImageView[] imageViews = new ImageView[]{holder.ivMsg1,holder.ivMsg2}; + for (ImageView imageView : imageViews) { + imageView.setVisibility(View.GONE); + + } + String imgUrl = null; + for (int i = 0; i < item.getTopMessageList().size() ; i++) { + if (i >= textViews.length) break; + TopMessage topMessage = item.getTopMessageList().get(i); + if (!TextUtils.isEmpty(topMessage.getImg()) && imgUrl == null){ + imgUrl = topMessage.getImg(); + } + if (!TextUtils.isEmpty(topMessage.getTitle())){ + textViews[i].setText(topMessage.getTitle()); + if (topMessage.getTipType() == TopMessage.TIP_TYPE_ABOUT_ME){ + imageViews[i].setVisibility(View.VISIBLE); + imageViews[i].setImageResource(R.drawable.erban_toutiao_tag_about_me); + + }else if (topMessage.getTipType() == TopMessage.TIP_TYPE_NEW){ + imageViews[i].setVisibility(View.VISIBLE); + imageViews[i].setImageResource(R.drawable.erban_toutiao_tag_new); + + }else if (topMessage.getTipType() == TopMessage.TIP_TYPE_MONSTER){ + imageViews[i].setVisibility(View.VISIBLE); + imageViews[i].setImageResource(R.drawable.erban_toutiao_tag_monster); + + } + } + + } + if (null != imgUrl){ + holder.ivPic.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(context,imgUrl,holder.ivPic, R.drawable.default_cover); + }else{ + holder.ivPic.setVisibility(View.GONE); + } + + } + + @Override + public int getSize() { + return vmTopMessageList.size(); + } + + + class ErBanTopMessageViewHolder extends BetterMarqueeView.ViewHolder{ + private TextView tvMsg1; + private TextView tvMsg2; + private ImageView ivPic; + private ImageView ivMsg1; + private ImageView ivMsg2; + + public ErBanTopMessageViewHolder(View itemView) { + super(itemView); + ivMsg1 = (ImageView) itemView.findViewById(R.id.iv_msg1); + ivMsg2 = (ImageView) itemView.findViewById(R.id.iv_msg2); + tvMsg1 = (TextView) itemView.findViewById(R.id.tv_msg1); + tvMsg2 = (TextView) itemView.findViewById(R.id.tv_msg2); + ivPic = (ImageView) itemView.findViewById(R.id.iv_pic); + + } + } + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/FindAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/FindAdapter.java new file mode 100644 index 000000000..123582909 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/FindAdapter.java @@ -0,0 +1,135 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.RedPointView; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.home.bean.FindEntranceInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +/** + * @author jackI + * @Description + * @Date 2018/5/24 + */ + +public class FindAdapter extends BaseQuickAdapter { + + private Context context; + private final int itemWidth; + + public FindAdapter(Context context, @Nullable List data) { + super(R.layout.list_item_find_rv, data); + this.context = context; + + int screenWidth = context.getResources().getDisplayMetrics().widthPixels; + itemWidth = (screenWidth - ScreenUtil.dip2px(20) * 2 - ScreenUtil.dip2px(12) * 3) / 4; + } + + @Override + protected BaseViewHolder onCreateDefViewHolder(ViewGroup parent, int viewType) { + BaseViewHolder baseViewHolder = super.onCreateDefViewHolder(parent, viewType); + ViewGroup.LayoutParams layoutParams = baseViewHolder.itemView.getLayoutParams(); + layoutParams.width = itemWidth; + baseViewHolder.itemView.setLayoutParams(layoutParams); + return baseViewHolder; + } + + @Override + protected void convert(BaseViewHolder helper, FindEntranceInfo item) { + + ImageView rivPic = helper.getView(R.id.iv_pic); + GlideApp.with(context) + .load(item.getMinPic()) + .transforms(new CenterCrop()) + .dontAnimate() + .into(rivPic); + + helper.setText(R.id.tv_name, item.getName()); + RedPointView tvTaskNumber = helper.getView(R.id.tv_task_number); + if (item.getActivityType() == FindEntranceInfo.ACTIVITYTYPE_TASK && item.getMissionNum() > 0) { + String numText; + if (item.getMissionNum() > 99) { + numText = "99+"; + } else { + numText = String.valueOf(item.getMissionNum()); + } + tvTaskNumber.setNumber(String.valueOf(numText)); + tvTaskNumber.setVisibility(View.VISIBLE); + } else { + tvTaskNumber.setVisibility(View.GONE); + } + boolean isVisible = (item.getActivityType() == FindEntranceInfo.ACTIVITYTYPE_SIGN_IN + && !item.isSignStatus()); + helper.setGone(R.id.stv_has_sign_stutas, isVisible); + + helper.itemView.setOnClickListener(v -> jumpByType(item)); + + } + + private void jumpByType(FindEntranceInfo info) { + int type = info.getType(); + String param = info.getParam(); + switch (type) { + case FindEntranceInfo.TYPE_H5: + //跳转H5界面 + CommonWebViewActivity.start(mContext, param); + + break; + case FindEntranceInfo.TYPE_ROOM: + //跳转聊天室界面 + if (TextUtils.isEmpty(param)) return; + try { + AVRoomActivity.start(mContext, Long.valueOf(param)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + break; + case FindEntranceInfo.TYPE_GAME: + //跳转H5 游戏 + CommonWebViewActivity.start(mContext, param); + break; + case FindEntranceInfo.TYPE_DECORATION: + long uid = AuthModel.get().getCurrentUid(); + DecorationStoreActivity.start(mContext, uid); + break; + case FindEntranceInfo.TYPE_TO_ROUTERTYPE: + //旧版保留读取type的方式,新版type=5 + //转到routerType处理 + if (info.getRouterType() == RouterType.SIGN_IN) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_FIND_SIGN_CLICK, + "签到-发现页"); + } + boolean result = RouterHandler.handle(mContext, info.getRouterType(), + info.getRouterValue()); + if (!result) { + SingleToastUtil.showToast(XChatConstants.UPDATE_VERSION_TIPS); + } + break; + default: + SingleToastUtil.showToast(XChatConstants.UPDATE_VERSION_TIPS); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewUserListAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewUserListAdapter.java new file mode 100644 index 000000000..e6cb1b14c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewUserListAdapter.java @@ -0,0 +1,55 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/30 + */ +public class FindNewUserListAdapter extends BaseQuickAdapter { + private Context context; + + public FindNewUserListAdapter(Context context, @Nullable List data) { + super(R.layout.item_home_find_new_user_list, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, UserInfo item) { + helper.setText(R.id.tv_name, item.getNick()) + .setText(R.id.tv_tutu_id, "ID:" + item.getErbanNo() + ""); + + ImageView ivAvatar = helper.getView(R.id.civ_avatar); + GlideApp.with(context) + .load(item.getAvatar()) + .dontAnimate() + .into(ivAvatar); + + if (item.getGender() == 1) { + helper.setImageResource(R.id.iv_sex, R.drawable.ic_male); + } else { + helper.setImageResource(R.id.iv_sex, R.drawable.ic_female); + } + + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + UserInfoActivity.Companion.start(context, item.getUid()); + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewerListAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewerListAdapter.java new file mode 100644 index 000000000..a0c1db367 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/FindNewerListAdapter.java @@ -0,0 +1,54 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/30 + */ +public class FindNewerListAdapter extends BaseQuickAdapter { + private Context context; + + public FindNewerListAdapter(Context context, @Nullable List data) { + super(R.layout.item_home_find_newer_list, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, UserInfo item) { + helper.setText(R.id.tv_name, item.getNick()); + + ImageView ivAvatar = helper.getView(R.id.civ_avatar); + GlideApp.with(context) + .load(item.getAvatar()) + .dontAnimate() + .into(ivAvatar); + + if (item.getGender() == 1) { + helper.setImageResource(R.id.iv_sex, R.drawable.ic_male); + } else { + helper.setImageResource(R.id.iv_sex, R.drawable.ic_female); + } + + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + UserInfoActivity.Companion.start(context, item.getUid()); + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/FindStarFamilyAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/FindStarFamilyAdapter.java new file mode 100644 index 000000000..6fdcd56e4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/FindStarFamilyAdapter.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; + +import java.util.List; + +/** + * @author jackI + * @Description + * @Date 2018/5/24 + */ + +public class FindStarFamilyAdapter extends BaseQuickAdapter { + + private Context context; + + public FindStarFamilyAdapter(Context context, @Nullable List data) { + super(R.layout.list_item_find_star_family_list_vertical, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, RankingFamilyInfo item) { + if (item == null) { + return; + } + + ImageView rivPic = helper.getView(R.id.riv_pic); + ImageLoadUtils.loadRectImage(context, item.getIcon(), rivPic, R.drawable.default_avatar, ScreenUtil.dip2px(5)); + TextView tvName = helper.getView(R.id.tv_name); + tvName.setText(item.getName()); + + TextView familyId = helper.getView(R.id.tv_family_id); + TextView familyMemberCount = helper.getView(R.id.tv_family_member_count); + if (familyId != null) { + // ID + familyId.setText(TextUtils.isEmpty(item.getId()) ? "" : "ID:" + item.getId()); + } + if (familyMemberCount != null) { + // 成员数量 + familyMemberCount.setText(item.getMemberCount() == 0 ? "" : "成员:" + item.getMemberCount()); + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/FragmentViewPagerAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/FragmentViewPagerAdapter.java new file mode 100644 index 000000000..6bd9cf6b6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/FragmentViewPagerAdapter.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.home.adapter; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.List; + +/** + * + */ +public class FragmentViewPagerAdapter extends FragmentPagerAdapter { + private List mFragmentList; + + + public FragmentViewPagerAdapter(FragmentManager fm, List fragmentList) { + super(fm); + this.mFragmentList = fragmentList; + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList == null ? 0 : mFragmentList.size(); + } + + public void setmFragmentList(List mFragmentList) { + this.mFragmentList = mFragmentList; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/GameRankAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/GameRankAdapter.java new file mode 100644 index 000000000..8e234b766 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/GameRankAdapter.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.xchat_android_core.room.game.GameRankInfo; + +import java.util.List; + +/** + */ + +public class GameRankAdapter extends BetterMarqueeView.Adapter { + private Context context; + private List vmTopMessageList; + + public GameRankAdapter(Context context, List vmTopMessageList) { + this.context = context; + this.vmTopMessageList = vmTopMessageList; + } + + @Override + public GameRankViewHolder onCreateView(ViewGroup parent) { + return new GameRankViewHolder(LayoutInflater.from(this.context).inflate(R.layout.item_game_rank, parent, false)); + } + + @Override + public void onBindViewHolder(GameRankViewHolder holder, int position) { + GameRankInfo.ListBean item = vmTopMessageList.get(position); + + holder.tvName.setText(item.getGameName()); + if (item.getUserList().size() > 0) { + holder.ivAvatar1.setVisibility(View.VISIBLE); + ImageLoadUtils.loadAvatar(context, item.getUserList().get(0).getAvatar(), holder.ivAvatar1); + } + if (item.getUserList().size() > 1) { + holder.ivAvatar2.setVisibility(View.VISIBLE); + ImageLoadUtils.loadAvatar(context, item.getUserList().get(1).getAvatar(), holder.ivAvatar2); + } + if (item.getUserList().size() > 2) { + holder.ivAvatar3.setVisibility(View.VISIBLE); + ImageLoadUtils.loadAvatar(context, item.getUserList().get(2).getAvatar(), holder.ivAvatar3); + } else { + holder.ivAvatar3.setVisibility(View.GONE); + } + + + } + + @Override + public int getSize() { + return vmTopMessageList.size(); + } + + + class GameRankViewHolder extends BetterMarqueeView.ViewHolder { + private TextView tvName; + private ImageView ivAvatar1; + private ImageView ivAvatar2; + private ImageView ivAvatar3; + + public GameRankViewHolder(View itemView) { + super(itemView); + ivAvatar2 = (ImageView) itemView.findViewById(R.id.iv_avatar2); + ivAvatar3 = (ImageView) itemView.findViewById(R.id.iv_avatar3); + tvName = (TextView) itemView.findViewById(R.id.tv_name); + ivAvatar1 = (ImageView) itemView.findViewById(R.id.iv_avatar1); + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/HallChatAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/HallChatAdapter.java new file mode 100644 index 000000000..28037173f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/HallChatAdapter.java @@ -0,0 +1,74 @@ +package com.yizhuan.erban.home.adapter; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.support.annotation.Nullable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.text.style.ImageSpan; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.business.session.emoji.MoonUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nim.uikit.support.glide.ImageLoaderKit; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.CustomImageSpan; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.HomeHallMsgInfo; + +import java.util.List; + +public class HallChatAdapter extends BaseQuickAdapter { + + public HallChatAdapter(@Nullable List data) { + super(R.layout.item_home_hall_chat, data); + } + + @Override + protected void convert(BaseViewHolder helper, HomeHallMsgInfo item) { + + CircleImageView civAvatar = (CircleImageView) helper.getView(R.id.civ_avatar); + if (!TextUtils.isEmpty(item.getSenderAvatar())) { + ImageLoadUtils.loadAvatar(mContext, item.getSenderAvatar(), civAvatar); + } else { + civAvatar.setImageResource(R.drawable.default_avatar); + } + + TextView textView = helper.getView(R.id.tv_content); + if (TextUtils.isEmpty(item.getContent())) { + textView.setText(textView.getResources().getText(R.string.not_support_message_tip)); + } else { + if (item.getMessageType() == HomeHallMsgInfo.MESSAGE_TYPE_TEXT) { + textView.setText(item.getContent()); +// MoonUtil.identifyFaceExpressionSmall(mContext, textView, item.getContent().toString(), ImageSpan.ALIGN_BOTTOM); + } else if (item.getMessageType() == HomeHallMsgInfo.MESSAGE_TYPE_GIFT) { + SpannableStringBuilder ssb = new SpannableStringBuilder("赠送 "); + String targetNick = item.getTargetNick(); + if (targetNick == null) { + targetNick = ""; + } + ssb.append(targetNick); + int start = ssb.length(); + ssb.append("["); + if (!TextUtils.isEmpty(item.getGiftName())) { + ssb.append(item.getGiftName()); + } else { + ssb.append("礼物"); + } + ssb.append("]"); + start = ssb.length(); + ssb.append("x").append(String.valueOf(item.getGiftCount())); +// ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(mContext.getResources().getColor(R.color.color_FF3D56)); +// ssb.setSpan(foregroundColorSpan, start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + textView.setText(ssb); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/HomeFragmentAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeFragmentAdapter.java new file mode 100644 index 000000000..53adf60d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeFragmentAdapter.java @@ -0,0 +1,978 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.AppCompatImageView; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nim.uikit.support.glide.GlideRequest; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemHomeTwoNBinding; +import com.yizhuan.erban.home.view.HomeConfigModule; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.LivingIconView; +import com.yizhuan.erban.ui.widget.RoomItemView; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.GridSpacingItemDecoration; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.KTVRoomInfo; +import com.yizhuan.xchat_android_core.home.bean.MakeFriendsInfo; +import com.yizhuan.xchat_android_core.home.bean.RecommendInfo; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessageInfo; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.user.bean.RecommendationUserInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.StringUtils; + +import org.jetbrains.annotations.NotNull; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + *

首页热门adapter

+ * + * @author Administrator + * @date 2017/11/16 + */ +public class HomeFragmentAdapter extends BaseMultiItemQuickAdapter { + + private int mBadgeHeight; + private Context mContext; + /** + * 校验跳转房间的频率 + */ + private long mLastOpen; + private String mTabName; + + public HomeFragmentAdapter(Context context, List data) { + super(data); + this.mContext = context; + addItemType(HomeItem.TYPE_DIV_1, R.layout.list_item_div_1); + addItemType(HomeItem.TYPE_DIV_2, R.layout.list_item_div_2); + + addItemType(HomeItem.TYPE_BANNER, R.layout.layout_rollpage_view); + addItemType(HomeItem.TYPE_TOP_MESSAGE, R.layout.list_item_home_erban_top_message); + addItemType(HomeItem.TYPE_RECOMMEND, R.layout.list_item_erban_recommend); + addItemType(HomeItem.TYPE_CONFIG, R.layout.list_item_three_plus_n); + addItemType(HomeItem.TYPE_TWO_LINES, R.layout.item_game_home_two_lines); + addItemType(HomeItem.TYPE_KTV, R.layout.list_item_home_ktv); + addItemType(HomeItem.TYPE_MAKE_FRIENDS, R.layout.list_item_home_make_friends); + + //3.1.2之后删除怪兽 + //addItemType(HomeItem.TYPE_MONSTER, R.layout.list_item_home_monster); + //3.1.2之后加入 + addItemType(HomeItem.TYPE_SQUARE_PIC, R.layout.item_erban_recommend); + addItemType(HomeItem.TYPE_LINEAR_LITTLE_PIC, R.layout.item_room_recommended); + addItemType(HomeItem.TYPE_SQUARE_EMPTY, R.layout.item_erban_grid_empty); + addItemType(HomeItem.TYPE_BLOCK_TITLE, R.layout.home_module_block_title); + + //end3.1.2 + + //添加两列单个显示 + addItemType(HomeItem.TYPE_BLOCK_SINGLE, R.layout.item_home_two_single_show); + //不带背景的banner + addItemType(HomeItem.TYPE_BANNER_NO_TOP_BG, R.layout.item_banner); + //新版首页用户信息 + addItemType(HomeItem.TYPE_USER_LINEAR, R.layout.item_user); + //两个的虚位以待 + addItemType(HomeItem.TYPE_DOUBLE_SQUARE_EMPTY, R.layout.item_erban_grid_2_empty); + + mBadgeHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + } + + @Override + public void onBindViewHolder(@NonNull BaseViewHolder holder, int position, @NonNull List payloads) { + super.onBindViewHolder(holder, position, payloads); + int viewType = holder.getItemViewType(); + if (position - getHeaderLayoutCount() < 0) { + return; + } + switch (viewType) { + case 0: + convert(holder, getItem(position - getHeaderLayoutCount()), payloads); + break; + + default: + convert(holder, getItem(position - getHeaderLayoutCount()), payloads); + break; + } + } + + @Override + protected void convert(BaseViewHolder holder, HomeItem homeItem) { + } + + protected void convert(BaseViewHolder holder, HomeItem homeItem, @NonNull List payloads) { + if (homeItem == null) { + return; + } + switch (homeItem.getItemType()) { + case HomeItem.TYPE_BANNER: + setBannerData(holder, homeItem); + break; + case HomeItem.TYPE_RECOMMEND: + setErbanRecommend(holder, homeItem); + break; + case HomeItem.TYPE_CONFIG: + setConfigRecommend(holder, homeItem); + break; + case HomeItem.TYPE_TWO_LINES: + setTwoLinesData(holder, homeItem); + break; + case HomeItem.TYPE_TOP_MESSAGE: + setErbanTopMessageData(holder, homeItem); + break; + case HomeItem.TYPE_KTV: + setKTVRoom(holder, homeItem); + break; + case HomeItem.TYPE_MAKE_FRIENDS: + setMakeFriend(holder, homeItem); + break; + case HomeItem.TYPE_SQUARE_PIC: + setSquarePicData(holder, homeItem); + break; + case HomeItem.TYPE_SQUARE_EMPTY: + setSquareEmpty(holder, homeItem); + break; + case HomeItem.TYPE_LINEAR_LITTLE_PIC: + setLinearLittlePicData(holder, homeItem); + break; + case HomeItem.TYPE_BLOCK_TITLE: + setBlockTitle(holder, homeItem); + break; + case HomeItem.TYPE_BLOCK_SINGLE: + setTwoSingle(holder, homeItem); + break; + case HomeItem.TYPE_BANNER_NO_TOP_BG: + setNoBgBannerData(holder, homeItem); + break; + case HomeItem.TYPE_USER_LINEAR: + setUserData(holder, homeItem); + break; + default: + break; + } + } + + private void setUserData(BaseViewHolder holder, HomeItem homeItem) { + Object obj = homeItem.getData(); + if (!(obj instanceof RecommendationUserInfo)) { + return; + } + RecommendationUserInfo item = (RecommendationUserInfo) obj; + + //common begin + holder.setGone(R.id.iv_noble_level, false); + holder.setGone(R.id.iv_user_level, false); + holder.setGone(R.id.iv_charm_level, false); + + //setTag + ImageView ivTag = holder.getView(R.id.iv_tag); + + //distance + holder.setGone(R.id.tv_distance, !TextUtils.isEmpty(item.getDistanceStr())) + .setText(R.id.tv_distance, item.getDistanceStr()); + + //common end + holder.setGone(R.id.iv_gender, false).setGone(R.id.tv_age, false); + + CharSequence title; + String avatar; + HomeRoom roomInfo = item.getRoomVo(); + String tag; + String badge = null; + CharSequence description; + + holder.addOnClickListener(R.id.fl_avatar); + holder.addOnClickListener(R.id.ll_sub_content); + holder.addOnClickListener(R.id.rl_opt); + + TextView tvNum = holder.getView(R.id.tv_num); + Integer num = getRoomOnlineNum(roomInfo, item.getOnlineNum()); + + if (item.getStatus() != RecommendationUserInfo.STATUS_RECOMMEND_ROOM) { + UserLevelVo userLevelVo = item.getUserLevelVo(); + AppCompatImageView ivUserLevel = holder.getView(R.id.iv_user_level); + AppCompatImageView ivCharmLevel = holder.getView(R.id.iv_charm_level); + // 是否展示等级图标 + showLevel(userLevelVo, ivUserLevel, ivCharmLevel); + + if (item.getGender() == 1) { + if (item.getAge() > 0) { + holder.setBackgroundRes(R.id.tv_age, R.drawable.ic_home_male_age) + .setText(R.id.tv_age, item.getAge() + "") + .setGone(R.id.tv_age, true) + .setGone(R.id.iv_gender, false); + + } else { + holder.setImageResource(R.id.iv_gender, R.drawable.ic_male) + .setGone(R.id.tv_age, false) + .setGone(R.id.iv_gender, true); + } + } else { + + if (item.getAge() > 0) { + holder.setBackgroundRes(R.id.tv_age, R.drawable.ic_home_female_age) + .setText(R.id.tv_age, item.getAge() + "") + .setGone(R.id.tv_age, true) + .setGone(R.id.iv_gender, false); + + } else { + holder.setImageResource(R.id.iv_gender, R.drawable.ic_female) + .setGone(R.id.iv_gender, true) + .setGone(R.id.tv_age, false); + } + } + + AppCompatImageView ivNobleLevel = holder.getView(R.id.iv_noble_level); + if (item.getNobleUsers() != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(item.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } + } + + } + + //判断类型 + switch (item.getStatus()) { + //普通 + case RecommendationUserInfo.STATUS_NORMAL: + title = item.getNick(); + avatar = item.getAvatar(); + description = item.getDescription(); + tag = item.getSkillTag(); + + if (isCpRoom(roomInfo)) { + tvNum.setVisibility(View.VISIBLE); + tvNum.setText("一起玩"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_play_together, 0, 0, 0); + } + else { + tvNum.setText("撩一下"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_accost, 0, 0, 0); + } + break; + //KTV + case RecommendationUserInfo.STATUS_KTV: + + title = getRoomTitle(roomInfo, item.getNick()); + tag = getRoomTag(roomInfo, null); + badge = getRoomBadge(roomInfo, null); + avatar = getRoomAvatar(roomInfo, item.getAvatar()); + description = getRoomDescription(roomInfo, item.getDescription()); + if (isCpRoom(roomInfo)) { + tvNum.setVisibility(View.VISIBLE); + tvNum.setText("一起玩"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_play_together, 0, 0, 0); + } else { + tvNum.setText("去找TA"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_find_ta, 0, 0, 0); + } + break; + + case RecommendationUserInfo.STATUS_GAME: + + title = getRoomTitle(roomInfo, item.getNick()); + tag = getRoomTag(roomInfo, null); + badge = getRoomBadge(roomInfo, null); + avatar = getRoomAvatar(roomInfo, item.getAvatar()); + description = getRoomDescription(roomInfo, item.getDescription()); + tvNum.setText("一起玩"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_play_together, 0, 0, 0); + break; + + case RecommendationUserInfo.STATUS_ROOM: + + title = getRoomTitle(roomInfo, item.getNick()); + avatar = getRoomAvatar(roomInfo, item.getAvatar()); + description = getRoomDescription(roomInfo, item.getDescription()); + tag = getRoomTag(roomInfo, null); + badge = getRoomBadge(roomInfo, null); + if (isCpRoom(roomInfo)) { + tvNum.setVisibility(View.VISIBLE); + tvNum.setText("一起玩"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_play_together, 0, 0, 0); + } + else { + tvNum.setText("去找TA"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_find_ta, 0, 0, 0); + } + break; + + case RecommendationUserInfo.STATUS_RECOMMEND_ROOM: + title = getRoomTitle(roomInfo, item.getNick()); + avatar = getRoomAvatar(roomInfo, item.getAvatar()); + description = getRoomDescription(roomInfo, item.getDescription()); + tag = getRoomTag(roomInfo, null); + badge = getRoomBadge(roomInfo, null); + if (isCpRoom(roomInfo)) { + tvNum.setVisibility(View.VISIBLE); + tvNum.setText("一起玩"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_play_together, 0, 0, 0); + } else if (num != null && num > 0) { + tvNum.setVisibility(View.VISIBLE); + tvNum.setText(num + "人在看"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_find_ta, 0, 0, 0); + + } else { + tvNum.setText("去找TA"); + tvNum.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_home_find_ta, 0, 0, 0); + } + break; + + default: + return; + } + holder.setText(R.id.tv_title, title); + //显示标签 + if (StringUtils.isEmpty(tag)) { + holder.setGone(R.id.iv_tag, false); + } else { + holder.setGone(R.id.iv_tag, true); + ImageLoadUtils.loadImage(mContext, tag, ivTag); + } + ImageView ivAvatarBadge = holder.getView(R.id.iv_avatar_badge); + //显示头像角标 + if (StringUtils.isEmpty(badge)) { + ivAvatarBadge.setVisibility(View.GONE); + } else { + ivAvatarBadge.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(ivAvatarBadge.getContext(), badge, ivAvatarBadge); + } + ImageView avatarView = holder.getView(R.id.noble_avatar_view); + if (StringUtils.isEmpty(avatar)) { + avatarView.setVisibility(View.GONE); + } else { + avatarView.setVisibility(View.VISIBLE); + ImageLoadUtils.loadAvatar(avatar, avatarView); + } + + holder.setGone(R.id.tv_desc, !StringUtils.isBlank(description)); + //描述 + holder.setText(R.id.tv_desc, description); + } + + private boolean isCpRoom(HomeRoom roomInfo) { + if (roomInfo == null) { + return false; + } + return roomInfo.getType() == RoomInfo.ROOMTYPE_CP; + } + + private void showLevel(UserLevelVo userLevelVo, AppCompatImageView ivUserLevel, AppCompatImageView ivCharmLevel) { + if (userLevelVo != null) { + if (!TextUtils.isEmpty(userLevelVo.getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage1(ivUserLevel.getContext(), userLevelVo.getExperUrl(), ivUserLevel); + } + + if (!TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage1(ivCharmLevel.getContext(), userLevelVo.getCharmUrl(), ivCharmLevel); + } + + } + + } + + private void setNoBgBannerData(BaseViewHolder holder, HomeItem homeItem) { + ArrayList bannerList = (ArrayList) homeItem.getData(); + + if (!ListUtils.isListEmpty(bannerList)) { + + //审核中状态,去掉跳转房间banner + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = bannerList.iterator(); + while (iterator.hasNext()) { + BannerInfo bannerInfo = iterator.next(); + if (bannerInfo.getSkipType() == 2) { + iterator.remove(); + } + } + } + + RollPagerView rollPagerView = holder.getView(R.id.roll_view); + ViewGroup.LayoutParams layoutParams = rollPagerView.getLayoutParams(); + int bannerWidth = UIUtil.getScreenWidth(mContext) - UIUtil.dip2px(mContext, 40); + layoutParams.width = bannerWidth; + layoutParams.height = bannerWidth * 80 / 345; + rollPagerView.setLayoutParams(layoutParams); + + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + BannerAdapter bannerAdapter = new BannerAdapter(bannerList, mContext); + bannerAdapter.setRoundingRadius(ScreenUtil.dip2px(12)); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + rollPagerView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + } + //审核中状态隐藏 + LinearLayout llPanelContainer = holder.getView(R.id.ll_panel_container); + if (MarketVerifyModel.get().isMarketChecking()) { + llPanelContainer.setVisibility(View.GONE); + return; + } else { + llPanelContainer.setVisibility(View.VISIBLE); + } + llPanelContainer.setVisibility(View.GONE); + } + + /** + * 房间单个item + */ + private void setTwoSingle(BaseViewHolder helper, HomeItem homeItem) { + HomeRoom item = (HomeRoom) homeItem.getData(); + if (item == null) { + return; + } + + SVGAImageView ivTabLabel = helper.getView(R.id.iv_tab_label); + ImageView livLivingIcon = helper.getView(R.id.liv_living_icon); + TextView tvOnlineNumber = helper.getView(R.id.tv_online_number); + View lockBg = helper.getView(R.id.lock_bg); + ImageView ivCover = helper.getView(R.id.iv_cover); + TextView tvTitle = helper.getView(R.id.tv_title); + String badge = item.getBadge(); + if (StringUtils.isEmpty(badge)) { + ivTabLabel.setVisibility(View.GONE); + } else { + ivTabLabel.setVisibility(View.VISIBLE); + + SVGAParser svgaParser = (SVGAParser) ivTabLabel.getTag(); + if (svgaParser == null) { + svgaParser = new SVGAParser(mContext); + ivTabLabel.setTag(svgaParser); + } + try { + svgaParser.decodeFromURL(new URL(badge), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) { + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + ivTabLabel.setImageDrawable(drawable); + ivTabLabel.startAnimation(); + } + + @Override + public void onError() { + ImageLoadUtils.loadImage(mContext, badge, ivTabLabel); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + Drawable drawable = livLivingIcon.getDrawable(); + if (drawable instanceof AnimationDrawable) { + ((AnimationDrawable) drawable).start(); + } + + //tvOnlineNumber + tvOnlineNumber.setText(String.valueOf(item.getOnlineNum())); + + //lockBg + lockBg.setVisibility(StringUtils.isEmpty(item.getRoomPwd()) ? View.GONE : View.VISIBLE); + //ivCover + String avatar = item.getAvatar(); + if (StringUtils.isEmpty(avatar)) { + ivCover.setVisibility(View.GONE); + } else { + ivCover.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, avatar, ivCover); + } + + //tvTitle + MessageView.SpannableBuilder text = new MessageView.SpannableBuilder(tvTitle) + .appendImg(item.tagPict) + .append(item.title); + tvTitle.setText(text.build()); + + helper.itemView.setOnClickListener(v -> AVRoomActivity.start(mContext, item.getUid())); + } + + /** + * 交友 + */ + private void setMakeFriend(BaseViewHolder holder, HomeItem homeItem) { + MakeFriendsInfo makeFriendsInfo = (MakeFriendsInfo) homeItem.getData(); + if (makeFriendsInfo == null) return; + holder.setText(R.id.tv_title, makeFriendsInfo.getTitle()); + holder.setText(R.id.tv_sub_title, makeFriendsInfo.getSubTitle()); + holder.getView(R.id.tv_refresh).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (actionListener != null) { + actionListener.onRefreshMakeFriendList(); + makeFriendsInfo.setVmIsLoading(true); + notifyItemChanged(holder.getAdapterPosition()); + } + } + }); + + TextView tvRefresh = holder.getView(R.id.tv_refresh); + ImageView ivRefreshArrow = holder.getView(R.id.iv_refresh_arrow); + if (makeFriendsInfo.isVmIsLoading()) { + tvRefresh.setText("我刷刷刷..."); + RotateAnimation rotateAnimation = new RotateAnimation(0, 359, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation.setRepeatCount(-1); + rotateAnimation.setDuration(300); + LinearInterpolator lin = new LinearInterpolator(); + rotateAnimation.setInterpolator(lin); + ivRefreshArrow.startAnimation(rotateAnimation); + } else { + tvRefresh.setText("换一换"); + ivRefreshArrow.clearAnimation(); + } + + List roomList = makeFriendsInfo.getRoomList(); + RecyclerView recyclerView = holder.getView(R.id.rv_list); + recyclerView.setItemAnimator(null); + recyclerView.setFocusable(false); + recyclerView.setLayoutManager(new GridLayoutManager(mContext, 3)); + if (recyclerView.getItemDecorationCount() == 0) { + recyclerView.addItemDecoration(new GridSpacingItemDecoration(holder.itemView.getContext(), 3, 10)); + } + MakeFriendAdapter makeFriendAdapter = new MakeFriendAdapter(mContext, roomList); + recyclerView.setAdapter(makeFriendAdapter); + } + + /** + * KTV 房间列表 + */ + private void setKTVRoom(BaseViewHolder holder, HomeItem homeItem) { + KTVRoomInfo ktvRoomInfo = (KTVRoomInfo) homeItem.getData(); + holder.setText(R.id.tv_title, ktvRoomInfo.getTitle()); + holder.setText(R.id.tv_sub_title, ktvRoomInfo.getSubTitle()); + holder.getView(R.id.tv_more).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (actionListener != null) { + actionListener.onMoreKTVRoom(); + } + } + }); + + ViewPager viewPager = holder.getView(R.id.vp_rooms); + viewPager.setAdapter(new HomeItemVPAdapter(mContext, ktvRoomInfo.getRoomList())); + + + MagicIndicator magicIndicator = holder.getView(R.id.mi_indicator); + CommonNavigator commonNavigator = new CommonNavigator(mContext); + KTVMagicIndicatorAdapter ktvMagicIndicatorAdapter = new KTVMagicIndicatorAdapter(mContext, ktvRoomInfo.getRoomList().size()); + commonNavigator.setAdapter(ktvMagicIndicatorAdapter); + magicIndicator.setNavigator(commonNavigator); + + ViewPagerHelper.bind(magicIndicator, viewPager); + + } + + /** + * 设置轻寻头条数据 + */ + private void setErbanTopMessageData(BaseViewHolder holder, HomeItem homeItem) { + VMTopMessageInfo topMessageInfo = (VMTopMessageInfo) homeItem.getData(); + BetterMarqueeView betterMarqueeView = holder.getView(R.id.bmv_marquee_view); + ErbanTopMessageAdapter adapter = new ErbanTopMessageAdapter(mContext, topMessageInfo.getVmTopMessageList()); + betterMarqueeView.setAdapter(adapter); + betterMarqueeView.start(); + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PublicChatHallHomeActivity.openHeadlinePage(mContext); + } + }); + } + + /** + * 设置顶部数据 + */ + private void setBannerData(BaseViewHolder holder, HomeItem homeItem) { + @SuppressWarnings("unchecked") + ArrayList bannerList = (ArrayList) homeItem.getData(); + + if (!ListUtils.isListEmpty(bannerList)) { + //审核中状态,去掉跳转房间banner + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = bannerList.iterator(); + while (iterator.hasNext()) { + BannerInfo bannerInfo = iterator.next(); + if (bannerInfo.getSkipType() == 2) { + iterator.remove(); + } + } + } + + RollPagerView rollPagerView = holder.getView(R.id.roll_view); + ViewGroup.LayoutParams layoutParams = rollPagerView.getLayoutParams(); + int bannerWidth = UIUtil.getScreenWidth(mContext) - UIUtil.dip2px(mContext, 30); + layoutParams.width = bannerWidth; + layoutParams.height = bannerWidth * 120 / 345; + rollPagerView.setLayoutParams(layoutParams); + + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + BannerAdapter bannerAdapter = new BannerAdapter(bannerList, mContext); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + rollPagerView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + } + //审核中状态隐藏 + LinearLayout llPanelContainer = (LinearLayout) holder.getView(R.id.ll_panel_container); + if (MarketVerifyModel.get().isMarketChecking()) { + llPanelContainer.setVisibility(View.GONE); + return; + } else { + llPanelContainer.setVisibility(View.VISIBLE); + } + llPanelContainer.setVisibility(View.GONE); + } + + /** + * 设置轻寻推荐item + */ + private void setErbanRecommend(BaseViewHolder holder, HomeItem homeItem) { + RecommendInfo recommendInfo = (RecommendInfo) homeItem.getData(); + holder.setText(R.id.tv_title, recommendInfo.getTitle()); + + List roomList = recommendInfo.getRoomList(); + RecyclerView recyclerView = holder.getView(R.id.rv_list); + recyclerView.setItemAnimator(null); + recyclerView.setFocusable(false); + GridLayoutManager manager = new GridLayoutManager(mContext, 3); + recyclerView.setLayoutManager(manager); + if (recyclerView.getItemDecorationCount() == 0) { + int px = UIUtil.dip2px(mContext, 15); + recyclerView.addItemDecoration(new RecommendThreeNModelDecoration(px)); + } + ErbanRecommendAdapter erbanRecommendAdapter = new ErbanRecommendAdapter(mContext, roomList); + recyclerView.setAdapter(erbanRecommendAdapter); + erbanRecommendAdapter.setSpanSizeLookup(new SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + if (position < 3) { + return 1; + } + return manager.getSpanCount(); + } + }); + } + + /** + * 设置运营可配置模块 + * + * @param holder holder + * @param homeItem homeItem + */ + private void setConfigRecommend(BaseViewHolder holder, HomeItem homeItem) { + RecommendInfo recommendInfo = (RecommendInfo) homeItem.getData(); + HomeConfigModule module = holder.getView(R.id.home_config_module); + module.setData(recommendInfo); + } + + /** + * 设置游戏首页两列的数据 + * + * @param holder holder + * @param homeItem homeItem + */ + private void setTwoLinesData(BaseViewHolder holder, HomeItem homeItem) { + RecommendInfo recommendInfo = (RecommendInfo) homeItem.getData(); + TextView textView = holder.getView(R.id.tv_title); + if (!ListUtils.isListEmpty(recommendInfo.getRoomList())) { + textView.setVisibility(View.VISIBLE); + textView.setText(recommendInfo.getTitle()); + } else { + textView.setVisibility(View.GONE); + } + RecyclerView recyclerView = holder.getView(R.id.recycler_view); + GridLayoutManager manager = new GridLayoutManager(mContext, 2) { + @Override + public boolean canScrollVertically() { + return false; + } + }; + recyclerView.setLayoutManager(manager); + BaseAdapter adapter = new BaseAdapter(R.layout.item_home_two_n, BR.homeInfo) { + @Override + protected void convert(BindingViewHolder helper, HomeRoom item) { + + super.convert(helper, item); + + ItemHomeTwoNBinding binding = (ItemHomeTwoNBinding) helper.getBinding(); + if (binding == null) { + return; + } + binding.livLivingIcon.setColor(Color.WHITE); + binding.livLivingIcon.start(); + MessageView.SpannableBuilder text = new MessageView.SpannableBuilder(binding.tvTitle) + .appendImg(item.tagPict) + .append(item.title); + binding.tvTitle.setText(text.build()); + } + }; + adapter.setOnItemClickListener((adapt, view, position) -> AVRoomActivity.start(mContext, adapter.getItem(position).getUid())); + recyclerView.setAdapter(adapter); + adapter.setNewData(recommendInfo.getRoomList()); + } + + /** + * 设置3+n布局中的格子数据 + */ + private void setSquarePicData(BaseViewHolder helper, HomeItem homeItem) { + HomeRoom homeRoom = (HomeRoom) homeItem.getData(); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AVRoomActivity.start(mContext, homeRoom.getUid()); + } + }); + + LivingIconView livingIconView = helper.getView(R.id.liv_living_icon); + livingIconView.setColor(Color.WHITE); + livingIconView.start(); + + helper.setText(R.id.tv_online_number, mContext.getString(R.string.online_number_text, homeRoom.getOnlineNum())) + .setText(R.id.tv_title, homeRoom.getTitle()); + + helper.getView(R.id.lock_bg).setVisibility(!TextUtils.isEmpty(homeRoom.getRoomPwd()) ? View.VISIBLE : View.GONE); + + ImageView mIvTabLabel = helper.getView(R.id.iv_tab_label); + + boolean showTab = false; + Drawable icon = null; + if (homeItem.isShowRankHalfIcon()) { + showTab = true; + icon = mContext.getResources().getDrawable(R.drawable.icon_rank_half); + } else if (homeRoom.getIsRecom() > 0) { + showTab = true; + icon = mContext.getResources().getDrawable(R.drawable.ic_king_recommend); + } else if (!TextUtils.isEmpty(homeRoom.badge)) { + showTab = true; + } else + mIvTabLabel.setVisibility(View.INVISIBLE); + + if (showTab) { + mIvTabLabel.setVisibility(View.VISIBLE); + GlideRequest request; + if (icon != null) + request = GlideApp.with(mContext).load(icon); + else + request = GlideApp.with(mContext).load(homeRoom.badge); + + request.listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { + float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); + int width = Math.round(mBadgeHeight / ratio); + int height = mBadgeHeight; + ViewGroup.LayoutParams params = mIvTabLabel.getLayoutParams(); + params.width = width; + params.height = height; + mIvTabLabel.setLayoutParams(params); + mIvTabLabel.setImageDrawable(drawable); + return true; + } + }) + .into(mIvTabLabel); + + } + + + ImageView ivCover = helper.getView(R.id.iv_cover); + if (!TextUtils.isEmpty(homeRoom.getAvatar())) { + ImageLoadUtils.loadAvatarBig(homeRoom.getAvatar(), ivCover, R.drawable.default_cover); + } else { + GlideApp.with(mContext) + .load(R.drawable.default_cover) + .placeholder(R.drawable.default_cover) + .into(ivCover); + } + } + + /** + * 设置3+N布局中,虚位以待的数据 + */ + private void setSquareEmpty(BaseViewHolder holder, HomeItem homeItem) { + + } + + /** + * 设置3+N布局中,小图列表的数据 + */ + private void setLinearLittlePicData(BaseViewHolder helper, HomeItem homeItem) { + HomeRoom homeRoom = (HomeRoom) homeItem.getData(); + RoomItemView roomItemView = helper.getView(R.id.riv_room_view); + roomItemView.bindData(homeRoom); + } + + /** + * 设置每个模块的标题 + */ + private void setBlockTitle(BaseViewHolder holder, HomeItem homeItem) { + holder.setText(R.id.tv_title, (String) homeItem.getData()); + } + + private String getRoomTitle(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getTitle())) { + return defaultValue; + } + return roomInfo.getTitle(); + } + + private String getRoomTag(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getSkillTag())) { + return getRoomTagPic(roomInfo, defaultValue); + } + return roomInfo.getSkillTag(); + } + + private String getRoomTagPic(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getTagPict())) { + return defaultValue; + } + return roomInfo.getTagPict(); + } + + private String getRoomBadge(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getIcon())) { + return defaultValue; + } + return roomInfo.getIcon(); + } + + private String getRoomAvatar(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getAvatar())) { + return defaultValue; + } + return roomInfo.getAvatar(); + } + + private String getRoomDescription(HomeRoom roomInfo, String defaultValue) { + if (roomInfo == null || StringUtils.isEmpty(roomInfo.getDescription())) { + return defaultValue; + } + return roomInfo.getDescription(); + } + + private Integer getRoomOnlineNum(HomeRoom roomInfo, Integer defaultValue) { + if (roomInfo == null || roomInfo.getOnlineNum() == 0) { + return defaultValue; + } + return roomInfo.getOnlineNum(); + } + + public interface OnActionListener { + void onRefreshMakeFriendList(); + + void onMoreKTVRoom(); + + void onGoTalkHall(); + } + + private OnActionListener actionListener; + + public void setActionListener(OnActionListener actionListener) { + this.actionListener = actionListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/HomeHallAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeHallAdapter.java new file mode 100644 index 000000000..4c4fa4fe0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeHallAdapter.java @@ -0,0 +1,145 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatImageView; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.text.style.ImageSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.business.session.emoji.MoonUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.CustomImageSpan; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.HomeHallMsgInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/21 + */ +public class HomeHallAdapter extends BaseMultiItemQuickAdapter { + + private Context context; + + public HomeHallAdapter(Context context, @Nullable List data) { + super(data); + this.context = context; + + addItemType(HomeHallMsgInfo.ITEM_TYPE_LEFT, R.layout.item_home_hall_left); + addItemType(HomeHallMsgInfo.ITEM_TYPE_RIGHT, R.layout.item_home_hall_right); + addItemType(HomeHallMsgInfo.ITEM_TYPE_TIP, R.layout.item_home_hall_tip); + } + + @Override + protected View getItemView(int layoutResId, ViewGroup parent) { + return LayoutInflater.from(context).inflate(layoutResId, null); + } + + @Override + protected void convert(BaseViewHolder helper, HomeHallMsgInfo item) { + helper.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + if (HomeHallMsgInfo.ITEM_TYPE_TIP == item.getItemType()) { + helper.setText(R.id.tv_tip_text, item.getFormatTime()); + return; + } + + + helper.setText(R.id.tv_user_name, item.getNick()); + + TextView textView = helper.getView(R.id.tv_content); + if (TextUtils.isEmpty(item.getContent())) { + textView.setText(textView.getResources().getText(R.string.not_support_message_tip)); + } else { + if (item.getMessageType() == HomeHallMsgInfo.MESSAGE_TYPE_TEXT) { + MoonUtil.identifyFaceExpression(context, textView, item.getContent().toString(), ImageSpan.ALIGN_BOTTOM); + } else if (item.getMessageType() == HomeHallMsgInfo.MESSAGE_TYPE_GIFT) { + SpannableStringBuilder ssb = new SpannableStringBuilder("赠送 "); + String targetNick = item.getTargetNick(); + if (targetNick == null) { + targetNick = ""; + } + ssb.append(targetNick).append("\n"); + int start = ssb.length(); + if (!TextUtils.isEmpty(item.getGiftImage())) { + ssb.append("-"); + CustomImageSpan imageSpan = new CustomImageSpan(new ColorDrawable(Color.TRANSPARENT), + textView, item.getGiftImage(), Utils.dip2px(mContext, 35), Utils.dip2px(mContext, 35)); + ssb.setSpan(imageSpan, start, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } else { + ssb.append("礼物"); + } + start = ssb.length(); + ssb.append("x").append(String.valueOf(item.getGiftCount())); + ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(mContext.getResources().getColor(R.color.color_FF3D56)); + ssb.setSpan(foregroundColorSpan, start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + textView.setText(ssb); + } + } + + CircleImageView civAvatar = (CircleImageView) helper.getView(R.id.civ_avatar); + if (!TextUtils.isEmpty(item.getSenderAvatar())) { + GlideApp.with(context) + .load(item.getSenderAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(civAvatar); + } else { + civAvatar.setImageResource(R.drawable.default_avatar); + } + + // 官字 + helper.getView(R.id.message_item_name_icon_official).setVisibility(item.isOfficial() ? View.VISIBLE : View.GONE); + // 新字 + helper.getView(R.id.message_item_name_icon_new).setVisibility(item.isNewUser() ? View.VISIBLE : View.GONE); + // 靓字 + helper.getView(R.id.message_item_name_icon_pretty).setVisibility(item.isPrettyErbanNo() ? View.VISIBLE : View.GONE); + + AppCompatImageView ivNobleLevel = (AppCompatImageView) helper.getView(R.id.iv_noble_level); + if (!TextUtils.isEmpty(item.getNobleLevel())) { + String badgeUrl = NobleUtil.getBadgeByLevel(JavaUtil.str2int(item.getNobleLevel())); + if (!TextUtils.isEmpty(badgeUrl)) { + ivNobleLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(badgeUrl, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + AppCompatImageView ivUserLevel = (AppCompatImageView) helper.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (!TextUtils.isEmpty(item.getUserLevelUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = (AppCompatImageView) helper.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (!TextUtils.isEmpty(item.getUserCharmLevelUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserCharmLevelUrl(), ivCharmLevel); + } + + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/HomeItemVPAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeItemVPAdapter.java new file mode 100644 index 000000000..371860f0b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeItemVPAdapter.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.NonNull; +import android.support.v4.view.PagerAdapter; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; + +import java.util.List; + + +/** + * @author jack + * @Description + * @Date 2018/10/30 + */ +public class HomeItemVPAdapter extends PagerAdapter { + private Context context; + private List> data; + + + public HomeItemVPAdapter(Context context, List> data) { + this.context = context; + this.data = data; + } + + @Override + public int getCount() { + return data.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + List homeRoomList = data.get(position); + View rootView = LayoutInflater.from(context).inflate(R.layout.item_home_ktv_vp, container, false); + RecyclerView recyclerView = rootView.findViewById(R.id.rv_list); + recyclerView.setItemAnimator(null); + recyclerView.setFocusable(false); + recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); + if (recyclerView.getItemDecorationCount() == 0) { + recyclerView.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, Utils.dip2px(context, 10), 0, false)); + } + KTVRoomAdapter ktvRoomAdapter = new KTVRoomAdapter(context, homeRoomList); + recyclerView.setAdapter(ktvRoomAdapter); + + container.addView(rootView); + return rootView; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView((View) object); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/HomeRoomAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeRoomAdapter.java new file mode 100644 index 000000000..6042a337d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/HomeRoomAdapter.java @@ -0,0 +1,111 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.view.View; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.RoomItemView; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.OtherBannerInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/2 + */ +public class HomeRoomAdapter extends BaseMultiItemQuickAdapter { + + private Context context; + + public HomeRoomAdapter(Context context, List data) { + super(data); + this.context = context; + addItemType(HomeRoomItem.TYPE_HOME_ROOM, R.layout.list_item_home_room_room); + addItemType(HomeRoomItem.TYPE_BANNER, R.layout.list_item_home_room_banner); + + } + + @Override + protected void convert(BaseViewHolder helper, HomeRoomItem item) { + if (item == null) { + return; + } + switch (item.getItemType()) { + case HomeRoomItem.TYPE_HOME_ROOM: + setRoom(helper, item); + break; + case HomeRoomItem.TYPE_BANNER: + setOtherBanner(helper, item); + break; + } + } + + /** + * 设置房间 + * + * @param holder + * @param item + */ + private void setRoom(BaseViewHolder holder, HomeRoomItem item) { + HomeRoom homeRoom = (HomeRoom) item.getData(); + RoomItemView roomItemView = holder.getView(R.id.riv_room_view); + roomItemView.bindData(homeRoom); + } + + /** + * 设置中间的scrollView page + * + * @param holder + * @param homeItem + */ + private void setOtherBanner(BaseViewHolder holder, HomeRoomItem homeItem) { + List bannerInfos = (List) homeItem.getData(); + if (!ListUtils.isListEmpty(bannerInfos)) { + RollPagerView rollPagerView = holder.getView(R.id.rpv_other_banner); + + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + OtherBannerAdapter bannerAdapter = new OtherBannerAdapter(mContext, bannerInfos); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + rollPagerView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + } + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/KTVMagicIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVMagicIndicatorAdapter.java new file mode 100644 index 000000000..45d916403 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVMagicIndicatorAdapter.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + +import java.util.List; + +/** + *

公共多个滑动tab样式

+ * + * @author Administrator + * @date 2017/11/15 + */ +public class KTVMagicIndicatorAdapter extends CommonNavigatorAdapter { + + private Context mContext; + private int size; + + public KTVMagicIndicatorAdapter(Context context, int size) { + mContext = context; + this.size = size; + } + + @Override + public int getCount() { + return size; + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + ColorPagerTitleView colorPagerTitleView = new ColorPagerTitleView(context); + + return colorPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + + class ColorPagerTitleView extends RelativeLayout implements IPagerTitleView { + View view; + + public ColorPagerTitleView(Context context) { + super(context); + view = new View(context); + LayoutParams lp = new LayoutParams(16, 4); + lp.setMargins(5, 0, 5, 0); + addView(view, lp); + } + + @Override + public void onSelected(int index, int totalCount) { + view.setBackgroundColor(getResources().getColor(R.color.appColor)); + } + + @Override + public void onDeselected(int index, int totalCount) { + view.setBackgroundColor(getResources().getColor(R.color.color_CCCCCC)); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/KTVRoomAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVRoomAdapter.java new file mode 100644 index 000000000..5cc7d5efd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVRoomAdapter.java @@ -0,0 +1,106 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.LivingIconView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class KTVRoomAdapter extends BaseMultiItemQuickAdapter { + + private Context mContext; + private int mRound, mTagHeight, mBadgeHeight; + + public KTVRoomAdapter(Context context, @Nullable List data) { + super(data); + this.mContext = context; + mRound = Utils.dip2px(mContext, 9); + mTagHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + mBadgeHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + + addItemType(KTVRoom.TYPE_GIRD, R.layout.item_home_ktv_room); + addItemType(KTVRoom.TYPE_GIRD_EMPTY, R.layout.item_home_empty_ktv_room); + + } + + @Override + protected void convert(BaseViewHolder helper, KTVRoom homeRoom) { + + View view = helper.getView(R.id.ll_container); + ViewGroup.LayoutParams lp = view.getLayoutParams(); + lp.width = (Utils.getWindowWidth(mContext) - Utils.dip2px(mContext, 50)) / 3; + view.setLayoutParams(lp); + + + if (homeRoom.getItemType() == KTVRoom.TYPE_GIRD_EMPTY) { + // FIXME: 2018/11/15 使用 ContentWrapViewPager 下面两句代码不能去掉,否则显示异常。 + ImageView ivCover = helper.getView(R.id.iv_cover); + GlideApp.with(mContext) + .load(R.mipmap.bg_item_empty_ktv_room) + .skipMemoryCache(true) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .into(ivCover); + } else { + + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// AVRoomActivity.start(mContext, Long.parseLong(homeRoom.getRoomUid())); + AVRoomActivity.start(mContext, homeRoom.getRoomUid()); + } + }); + + helper.getView(R.id.lock_bg).setVisibility(!TextUtils.isEmpty(homeRoom.getRoomPwd()) ? View.VISIBLE : View.GONE); + + LivingIconView livingIconView = helper.getView(R.id.liv_living_icon); + livingIconView.setColor(Color.WHITE); + livingIconView.start(); + + helper.setText(R.id.tv_online_number, mContext.getString(R.string.online_number_text, homeRoom.getOnlineNum())) + .setText(R.id.tv_title, homeRoom.getTitle()); + + if (!TextUtils.isEmpty(homeRoom.getSingingMusicName())) { + helper.setText(R.id.tv_singing_song, String.format(mContext.getResources().getString(R.string.home_ktv_singing_song), homeRoom.getSingingMusicName())); + } else { + helper.setText(R.id.tv_singing_song, mContext.getResources().getString(R.string.home_ktv_no_singing_song)); + } + + ImageView ivCover = helper.getView(R.id.iv_cover); + if (!TextUtils.isEmpty(homeRoom.getAvatar())) { + ImageLoadUtils.loadRectImage(mContext, homeRoom.getAvatar(), ivCover, R.drawable.default_cover, mRound); + } else { + GlideApp.with(mContext) + .load(R.drawable.default_cover) + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(mRound)) + .into(ivCover); + } + } + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/KTVTypeRoomAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVTypeRoomAdapter.java new file mode 100644 index 000000000..4b915f571 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/KTVTypeRoomAdapter.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public class KTVTypeRoomAdapter extends BaseQuickAdapter { + private Context context; + private int[] bgIds = new int[]{R.drawable.ktv_room_bg_1, + R.drawable.ktv_room_bg_2, + R.drawable.ktv_room_bg_3, + R.drawable.ktv_room_bg_4}; + + public KTVTypeRoomAdapter(Context context, @Nullable List data) { + super(R.layout.item_ktv_type_room, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, KTVRoom item) { + + int index = helper.getAdapterPosition() % bgIds.length; + helper.setBackgroundRes(R.id.ll_container, bgIds[index]); + + helper.setText(R.id.tv_title, item.getTitle()) + .setText(R.id.tv_member_count, mContext.getString(R.string.online_number_text, item.getOnlineNum())); + + if (!TextUtils.isEmpty(item.getSingingMusicName())) { + helper.setText(R.id.tv_sing_song, String.format(mContext.getResources().getString(R.string.home_ktv_singing_song), item.getSingingMusicName())); + } else { + helper.setText(R.id.tv_sing_song, mContext.getResources().getString(R.string.home_ktv_no_singing_song)); + } + + helper.getView(R.id.iv_lock).setVisibility(!TextUtils.isEmpty(item.getRoomPwd()) ? View.VISIBLE : View.GONE); + + ImageView ivCover = helper.getView(R.id.civ_avatar); + if (!TextUtils.isEmpty(item.getAvatar())) { + GlideApp.with(mContext) + .load(item.getAvatar()) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(ivCover); + } else { + GlideApp.with(mContext) + .load(R.drawable.default_cover) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(ivCover); + } + + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AVRoomActivity.start(context, item.getRoomUid()); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/MainMagicIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/MainMagicIndicatorAdapter.java new file mode 100644 index 000000000..d26bb1fd0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/MainMagicIndicatorAdapter.java @@ -0,0 +1,65 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + +import java.util.List; + +public class MainMagicIndicatorAdapter extends CommonNavigatorAdapter { + private final Context mContext; + private final List mTitleList; + + public MainMagicIndicatorAdapter(Context context, List charSequences) { + this.mContext = context; + this.mTitleList = charSequences; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true, 8); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_B3B3B3)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(0.7f); + scaleTransitionPagerTitleView.setTextSize(21); + int padding = UIUtil.dip2px(context, 6); + scaleTransitionPagerTitleView.setPadding(padding,0,padding,0); +// scaleTransitionPagerTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 36); + scaleTransitionPagerTitleView.setText(mTitleList.get(i)); + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i, scaleTransitionPagerTitleView); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position, TextView view); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/MakeFriendAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/MakeFriendAdapter.java new file mode 100644 index 000000000..c90906381 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/MakeFriendAdapter.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/30 + */ +public class MakeFriendAdapter extends BaseQuickAdapter { + private Context context; + + public MakeFriendAdapter(Context context, @Nullable List data) { + super(R.layout.item_home_make_friends_room, data); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, HomeRoom item) { + helper.setText(R.id.tv_title, item.getTitle()) + .setText(R.id.tv_online_number, + String.format(context.getResources().getString(R.string.online_number_text), item.getOnlineNum())); + + ImageLoadUtils.loadAvatar(context, item.getAvatar(), helper.getView(R.id.civ_avatar)); + helper.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AVRoomActivity.start(mContext, item.getUid()); + } + }); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/OtherBannerAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/OtherBannerAdapter.java new file mode 100644 index 000000000..dc8ed0f73 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/OtherBannerAdapter.java @@ -0,0 +1,81 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.jude.rollviewpager.adapter.StaticPagerAdapter; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.RoomItemView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class OtherBannerAdapter extends StaticPagerAdapter { + + private Context mContext; + private List data; + + public OtherBannerAdapter(Context context, List data) { + this.data = data; + this.mContext = context; + } + + + @Override + public View getView(ViewGroup container, int position) { + View view = LayoutInflater.from(mContext).inflate(R.layout.list_item_other_banner_cover,container,false); + ImageView ivCover = view.findViewById(R.id.iv_cover); + BannerInfo bannerInfo = data.get(position); + String url = bannerInfo.getSkipUri(); + ImageLoadUtils.loadGameBannerRoundBackground(mContext, bannerInfo.getBannerPic(), ivCover); + + ivCover.setOnClickListener(v -> { + if (TextUtils.isEmpty(url)) return; + if (bannerInfo.getSkipType() == BannerInfo.SKIP_TYP_H5) { + Intent intent = new Intent(mContext, CommonWebViewActivity.class); + intent.putExtra("url", url); + mContext.startActivity(intent); + } else if (bannerInfo.getSkipType() == BannerInfo.SKIP_TYP_CHAT_ROOM) { + if (TextUtils.isEmpty(url)) return; + try { + AVRoomActivity.start(mContext, Long.valueOf(url)); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + }); + + return view; + } + + @Override + public int getCount() { + if (data != null) { + return data.size(); + }else{ + return 0; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/RecommendThreeNModelDecoration.java b/app/src/main/java/com/yizhuan/erban/home/adapter/RecommendThreeNModelDecoration.java new file mode 100644 index 000000000..f887874cf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/RecommendThreeNModelDecoration.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.home.adapter; + +import android.graphics.Rect; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +/** + * 推荐 3+n 界面专用的分割线 + * Created by lvzebiao on 2019/2/18. + */ + +public class RecommendThreeNModelDecoration extends RecyclerView.ItemDecoration{ + + private int valuePx; + + public RecommendThreeNModelDecoration(int valuePx) { + this.valuePx = valuePx; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + if (parent.getLayoutManager() == null || !(parent.getLayoutManager() instanceof GridLayoutManager)) { + return; + } + int position = parent.getChildAdapterPosition(view); + GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + int column = position % spanCount; + int spanSize = layoutManager.getSpanSizeLookup().getSpanSize(position); + if (spanSize == spanCount) { + //独占一行的,不需要左右分割线 + outRect.set(0, 0, 0, 0); + } else { + getGridItemOffsets(outRect, column, spanCount); + } + } + + private void getGridItemOffsets(Rect outRect, int column, int spanCount) { + outRect.left = valuePx * column / spanCount; + outRect.right = valuePx * (spanCount - 1 - column) / spanCount; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/RoomActAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomActAdapter.java new file mode 100644 index 000000000..8f0baef09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomActAdapter.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.home.adapter; + +import android.app.Activity; +import android.content.Context; +import android.support.v4.app.FragmentActivity; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.jude.rollviewpager.adapter.StaticPagerAdapter; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.fragment.DialogWebFragment; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.redPacket.bean.ActionDialogInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +public class RoomActAdapter extends StaticPagerAdapter { + + private Context mContext; + private List data; + private SVGAParser svgaParser; + + public void setInRoom(boolean inRoom) { + this.inRoom = inRoom; + } + + private boolean inRoom = true; + public RoomActAdapter(Context context, List data) { + this.data = data; + this.mContext = context; + svgaParser = new SVGAParser(context); + } + + @Override + public View getView(ViewGroup container, int position) { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_room_act,container,false); + SVGAImageView ivCover = view.findViewById(R.id.iv_cover); + ActionDialogInfo bannerInfo = data.get(position); + String url = bannerInfo.getSkipUrl(); + String actId = bannerInfo.getActId(); + if ("png".equals(bannerInfo.getImageType())) { + ivCover.setScaleType(ImageView.ScaleType.FIT_XY); + ImageLoadUtils.loadImage(mContext, bannerInfo.getAlertWinPic(), ivCover, R.drawable.default_cover); + } else if ("svga".equals(bannerInfo.getImageType())) { + ivCover.setScaleType(ImageView.ScaleType.FIT_CENTER); + playSvag(ivCover, bannerInfo.getAlertWinPic()); + } + + ivCover.setOnClickListener(v -> { + if (TextUtils.isEmpty(url)) return; + + if (inRoom) { + if (AvRoomDataManager.get().isCpRoom()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.cp_room_activity, "陪伴房活动点击"); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.mp_room_activity, "普通房活动点击"); + } + AvRoomModel.get().activityClickLog("2", actId).subscribe(); + } else { + AvRoomModel.get().activityClickLog("1", actId).subscribe(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_activity, "首页活动点击"); + } + if (!TextUtils.isEmpty(actId) && "19".equals(actId)) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_ROOM_RECOMMEND_CLICK, "我要上推荐"); + } + if (JavaUtil.str2int(bannerInfo.getSkipType()) == RouterType.H5 && bannerInfo.isDialogWeb()) { + if (listener != null) { + listener.onWebClick(bannerInfo.getSkipUrl()); + } + } else { + RouterHandler.handle(mContext, JavaUtil.str2int(bannerInfo.getSkipType()), + String.valueOf(bannerInfo.getSkipUrl())); + } + //新埋点 + String actName = bannerInfo.getActName(); + if (actName == null) { + actName = ""; + } + if (bannerInfo.getEntrancePosition() == 2) { + //左上角 + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_ROOM_ACTIVITY_ENTRANCE, + "房间左上角活动入口-区分活动:" + actName); + } else { + //右下角 + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_ROOM_ACTIVITY_ENTRANCE_B, + "房间右下角活动入口-区分活动:" + actName); + } + + }); + + return view; + } + + @Override + public int getCount() { + if (data != null) { + return data.size(); + }else{ + return 0; + } + } + + private void playSvag(SVGAImageView svgaImageView, String effect) { + if (TextUtils.isEmpty(effect)) return; + try { + svgaParser.parse(new URL(effect), + new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + svgaImageView.setImageDrawable(new SVGADrawable(svgaVideoEntity)); + svgaImageView.startAnimation(); + } + + @Override + public void onError() { + svgaImageView.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + private RoomActClickListener listener; + + public void setRoomActClickListener(RoomActClickListener listener) { + this.listener = listener; + } + + public interface RoomActClickListener { + void onWebClick(String url); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryIndicatorAdapter.java new file mode 100644 index 000000000..d7368faae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryIndicatorAdapter.java @@ -0,0 +1,117 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.makeramen.roundedimageview.RoundedImageView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public class RoomCategoryIndicatorAdapter extends CommonNavigatorAdapter { + private List mTitleList; + private Context mContext; + + public RoomCategoryIndicatorAdapter(Context mContext, List mTitleList) { + this.mTitleList = mTitleList; + this.mContext = mContext; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + CategoryPagerTitleView categoryPagerTitleView = new CategoryPagerTitleView(context, mTitleList.get(index)); + categoryPagerTitleView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mOnItemSelectListener) { + mOnItemSelectListener.onItemSelect(index); + } + } + }); + return categoryPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } + + class CategoryPagerTitleView extends RelativeLayout implements IPagerTitleView { + + private RelativeLayout rlContainer; + private RoundedImageView ivIcon; + private TextView tvName; + private TabInfo tabInfo; + private View vCover; + + public CategoryPagerTitleView(Context context, TabInfo tabInfo) { + super(context); + this.tabInfo = tabInfo; + LayoutInflater.from(context).inflate(R.layout.item_room_category, this, true); + + rlContainer = (RelativeLayout) findViewById(R.id.rl_container); + ivIcon = (RoundedImageView) findViewById(R.id.iv_icon); + tvName = (TextView) findViewById(R.id.tv_name); + + + vCover = (View) findViewById(R.id.v_cover); + + ImageLoadUtils.loadImage(context, tabInfo.getPict(), ivIcon); +// tvName.setText(tabInfo.getName()); + + } + + + @Override + public void onSelected(int index, int totalCount) { + vCover.setBackgroundResource(R.drawable.shape_room_category_selected); +// tvName.setTextColor(getResources().getColor(R.color.black)); + } + + @Override + public void onDeselected(int index, int totalCount) { + vCover.setBackgroundResource(R.drawable.shape_room_category_unselected); +// tvName.setTextColor(getResources().getColor(R.color.white)); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryViewPagerAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryViewPagerAdapter.java new file mode 100644 index 000000000..466996d8a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomCategoryViewPagerAdapter.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.home.adapter; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.util.SparseArray; + +import com.yizhuan.erban.home.fragment.RoomListFragment; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + *

房间 adapter

+ * Created by Administrator on 2017/11/15. + */ +public class RoomCategoryViewPagerAdapter extends FragmentPagerAdapter { + private SparseArray mFragmentList; + private List mTitleList; + + public RoomCategoryViewPagerAdapter(FragmentManager fm, List titleList) { + super(fm); + this.mTitleList = titleList; + mFragmentList = new SparseArray<>(); + int size = titleList.size(); + for (int i = 0; i < size; i++) { + mFragmentList.put(i, RoomListFragment.newInstance(titleList.get(i))); + } + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/RoomTabAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomTabAdapter.java new file mode 100644 index 000000000..2423aa7fe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/RoomTabAdapter.java @@ -0,0 +1,151 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.RoomItemView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.SpacingDecoration; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +public class RoomTabAdapter extends BaseMultiItemQuickAdapter { + + private Context context; + private int mScreenWidth; + + public RoomTabAdapter(Context context, List data) { + super(data); + this.context = context; + addItemType(HomeRoomItem.TYPE_HOME_ROOM, R.layout.list_item_home_room_room); +// addItemType(HomeRoomItem.TYPE_BANNER, R.layout.list_item_home_room_banner); + addItemType(HomeRoomItem.TYPE_BANNER, R.layout.layout_rollpage_view); + addItemType(HomeRoomItem.TYPE_TOP_THREE, R.layout.list_top_three); + addItemType(HomeRoomItem.TYPE_TOP_EMPTY, R.layout.layout_top_empty); + mScreenWidth = Utils.getWindowWidth(context) - Utils.dip2px(context, 30); + } + + @Override + protected void convert(BaseViewHolder helper, HomeRoomItem item) { + if (item == null) { + return; + } + switch (item.getItemType()) { + case HomeRoomItem.TYPE_HOME_ROOM: + setRoom(helper, item); + break; + case HomeRoomItem.TYPE_BANNER: + setOtherBanner(helper, item); + break; + + case HomeRoomItem.TYPE_TOP_THREE: + setTopThree(helper, item); + break; + } + } + + private void setTopThree(BaseViewHolder holder, HomeRoomItem item) { + ArrayList roomList = (ArrayList) item.getData(); + + RecyclerView recyclerView = holder.getView(R.id.rv_list); + recyclerView.setItemAnimator(null); + recyclerView.setFocusable(false); + GridLayoutManager manager = new GridLayoutManager(mContext, 3); + recyclerView.setLayoutManager(manager); + if (recyclerView.getItemDecorationCount() == 0) { + int px = UIUtil.dip2px(mContext, 15); + recyclerView.addItemDecoration(new RecommendThreeNModelDecoration(px)); + } + + ErbanRecommendAdapter erbanRecommendAdapter = new ErbanRecommendAdapter(mContext, roomList); + recyclerView.setAdapter(erbanRecommendAdapter); + erbanRecommendAdapter.setSpanSizeLookup(((gridLayoutManager, position) -> { + if (position < 3) { + return 1; + } + return manager.getSpanCount(); + + })); + } + + /** + * 设置房间 + * + * @param holder + * @param item + */ + private void setRoom(BaseViewHolder holder, HomeRoomItem item) { + HomeRoom homeRoom = (HomeRoom) item.getData(); + RoomItemView roomItemView = holder.getView(R.id.riv_room_view); + roomItemView.bindData(homeRoom); + } + + /** + * 设置中间的scrollView page + * + * @param holder + * @param homeItem + */ + private void setOtherBanner(BaseViewHolder holder, HomeRoomItem homeItem) { + List bannerInfos = (List) homeItem.getData(); + + if (!ListUtils.isListEmpty(bannerInfos)) { + RollPagerView rollPagerView = holder.getView(R.id.roll_view); + ViewGroup.LayoutParams layoutParams = rollPagerView.getLayoutParams(); + int bannerWidth = UIUtil.getScreenWidth(mContext) - UIUtil.dip2px(mContext, 30); + layoutParams.width = bannerWidth; + layoutParams.height = bannerWidth * 120 / 345; + rollPagerView.setLayoutParams(layoutParams); +// RollPagerView rollPagerView = holder.getView(R.id.rpv_other_banner); + + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + OtherBannerAdapter bannerAdapter = new OtherBannerAdapter(mContext, bannerInfos); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + rollPagerView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/TopMagicIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/TopMagicIndicatorAdapter.java new file mode 100644 index 000000000..849ac464f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/TopMagicIndicatorAdapter.java @@ -0,0 +1,73 @@ +package com.yizhuan.erban.home.adapter; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.util.TypedValue; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + *

公共多个滑动tab样式

+ * + * @author Administrator + * @date 2017/11/15 + */ +public class TopMagicIndicatorAdapter extends CommonNavigatorAdapter { + + private Context mContext; + private List mTitleList; + + public TopMagicIndicatorAdapter(Context context, List titleList) { + mContext = context; + mTitleList = titleList; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, true, 2); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(0.8f); + scaleTransitionPagerTitleView.setTextSize(20); +// scaleTransitionPagerTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 36); + scaleTransitionPagerTitleView.setText(mTitleList.get(i)); + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/adapter/TwoXNAdapter.java b/app/src/main/java/com/yizhuan/erban/home/adapter/TwoXNAdapter.java new file mode 100644 index 000000000..7e71339a6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/adapter/TwoXNAdapter.java @@ -0,0 +1,48 @@ +package com.yizhuan.erban.home.adapter; + +import android.graphics.Color; + +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.databinding.ItemHomeTwoNBinding; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; + +public class TwoXNAdapter extends BaseAdapter { + + public TwoXNAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, HomeRoom item) { + super.convert(helper, item); + ItemHomeTwoNBinding binding = (ItemHomeTwoNBinding) helper.getBinding(); + binding.livLivingIcon.setColor(Color.WHITE); + binding.livLivingIcon.start(); + /*GlideApp.with(mContext) + .asDrawable() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .dontAnimate() + .dontTransform() + .load(item.tagPict) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + if (resource == null) return true; + MessageView.SpannableBuilder text = new MessageView.SpannableBuilder(binding.tvTitle) + .append(resource,resource.getIntrinsicWidth(),resource.getIntrinsicHeight()) + .append(item.title); + binding.tvTitle.setText(text.build()); + binding.tvTitle.postInvalidate(); + + return true; + } + }) + .submit();*/ + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/dialog/CreateRoomDialog.java b/app/src/main/java/com/yizhuan/erban/home/dialog/CreateRoomDialog.java new file mode 100644 index 000000000..24511003e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/dialog/CreateRoomDialog.java @@ -0,0 +1,53 @@ +package com.yizhuan.erban.home.dialog; + +import android.content.Context; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogCreateRoomBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.dialog_create_room) +public class CreateRoomDialog extends BaseBindingDialog { + private OpenRoomListener openRoomListener; + + public CreateRoomDialog(Context context, OpenRoomListener openRoomListener) { + super(context); + this.openRoomListener = openRoomListener; + } + + @Override + protected void init() { + binding.tvCp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeDialog(); + if (openRoomListener != null) { + openRoomListener.onCpRoom(); + } + } + }); + binding.tvNormal.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeDialog(); + if (openRoomListener != null) { + openRoomListener.onNormalRoom(); + } + } + }); + binding.tvExplain.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new RoomShowsDialog(getContext()).openDialog(); + } + }); + } + + public interface OpenRoomListener { + void onNormalRoom(); + + void onCpRoom(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/dialog/FiltrateDialog.java b/app/src/main/java/com/yizhuan/erban/home/dialog/FiltrateDialog.java new file mode 100644 index 000000000..76db51205 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/dialog/FiltrateDialog.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.home.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetDialog; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.DialogFiltrateBinding; +import com.yizhuan.erban.home.model.UserMatchVm; +import com.yizhuan.xchat_android_core.DemoCache; + +public class FiltrateDialog extends BottomSheetDialog implements View.OnClickListener { + + private DialogFiltrateBinding mBinding; + private UserMatchVm userMatchVm; + + public FiltrateDialog(@NonNull Context context, UserMatchVm userMatchVm) { + super(context); + this.userMatchVm = userMatchVm; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_filtrate); + mBinding = DataBindingUtil.bind(findViewById(R.id.root)); + + WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + + try { + ViewGroup parent = (ViewGroup) mBinding.root.getParent(); + parent.setBackgroundResource(android.R.color.transparent); + } catch (Exception e) { + e.printStackTrace(); + } + + init(); + } + + private void init() { + mBinding.setClick(this); + if (userMatchVm.getFindType() == UserMatchVm.NO_LIMIT) { + mBinding.rbNo.setChecked(true); + } else if (userMatchVm.getFindType() == UserMatchVm.GIRL) { + mBinding.rbGirl.setChecked(true); + } else if (userMatchVm.getFindType() == UserMatchVm.BOY) { + mBinding.rbBoy.setChecked(true); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.rb_no: + userMatchVm.setFindType(UserMatchVm.NO_LIMIT); + DemoCache.saveFilTrateType(UserMatchVm.NO_LIMIT); + break; + case R.id.rb_girl: + userMatchVm.setFindType(UserMatchVm.GIRL); + DemoCache.saveFilTrateType(UserMatchVm.GIRL); + break; + case R.id.rb_boy: + userMatchVm.setFindType(UserMatchVm.BOY); + DemoCache.saveFilTrateType(UserMatchVm.BOY); + break; + case R.id.tv_cancel: + dismiss(); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/dialog/RecommendRoomForNewerDialog.java b/app/src/main/java/com/yizhuan/erban/home/dialog/RecommendRoomForNewerDialog.java new file mode 100644 index 000000000..1eff2ce83 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/dialog/RecommendRoomForNewerDialog.java @@ -0,0 +1,97 @@ +package com.yizhuan.erban.home.dialog; + +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.user.IUserModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + + +/** + * @author jack + * @Description 新人推荐房间dialog + * @Date 2018/7/9 + */ + +public class RecommendRoomForNewerDialog extends AppCompatDialog implements View.OnClickListener{ + + private ImageView ivContent; + private ImageView ivGoRoom; + private ImageView imgClose; + + + public RecommendRoomForNewerDialog(Context context) { + super(context, R.style.common_dialog_theme); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.dialog_recommend_room_for_newer); + Window window = getWindow(); + if (window != null) { +// window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.gravity = Gravity.CENTER_HORIZONTAL; + window.setAttributes(windowParams); + } + + + ivContent = (ImageView) findViewById(R.id.iv_content); + + ivGoRoom = findViewById(R.id.tv_go_room); + imgClose = (ImageView) findViewById(R.id.img_close); + ivGoRoom.setOnClickListener(this); + imgClose.setOnClickListener(this); + + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null){ + return; + } + if (userInfo.getGender() == 1){ + ivContent.setImageResource(R.mipmap.bg_recommend_room_girls); + }else if (userInfo.getGender() == 2){ + ivContent.setImageResource(R.mipmap.bg_recommend_room_boys); + } + + } + + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == ivGoRoom.getId()){ + if (this.actionListener != null){ + this.actionListener.onGoIntoRoom(this); + } + }else if (id == imgClose.getId()){ + if (this.actionListener != null){ + this.actionListener.onCancel(this); + } + } + } + + private onActionListener actionListener; + + public void setActionListener(onActionListener actionListener) { + this.actionListener = actionListener; + } + + public interface onActionListener{ + void onGoIntoRoom(DialogInterface dialogInterface); + void onCancel(DialogInterface dialogInterface); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/dialog/RoomShowsDialog.java b/app/src/main/java/com/yizhuan/erban/home/dialog/RoomShowsDialog.java new file mode 100644 index 000000000..58a85af6e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/dialog/RoomShowsDialog.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.home.dialog; + +import android.content.Context; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogRoomShowsBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.dialog_room_shows) +public class RoomShowsDialog extends BaseBindingDialog { + public RoomShowsDialog(Context context) { + super(context); + } + + @Override + protected void init() { + binding.ivClose.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/dialog/SexMatchDialog.java b/app/src/main/java/com/yizhuan/erban/home/dialog/SexMatchDialog.java new file mode 100644 index 000000000..a4b0fed7f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/dialog/SexMatchDialog.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.home.dialog; + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogSexMatchBinding; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.im.CustomNotifyType; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.room.game.GameMatchInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +@ActLayoutRes(R.layout.dialog_sex_match) +public class SexMatchDialog extends BaseBindingDialog { + private final String SEX_MATCH_SVGA = "https://img.erbanyy.com/sexMatch.svga"; + + private SVGAParser mSVGAParser; + private Disposable subscribe; + private Observer observer; + private Consumer timeOutConsumer; + + public SexMatchDialog(Context context) { + super(context); + } + + public void setTimeOutConsumer(Consumer timeOutConsumer) { + this.timeOutConsumer = timeOutConsumer; + } + + @Override + protected void init() { + setCancelable(false); + setCanceledOnTouchOutside(false); + + HomeModel.get().addIsomerism() + .doOnError(throwable -> { + if (throwable instanceof PmRoomLimitException) { + if (context instanceof MainActivity) { + ((MainActivity) context).handleOpenRoomWhenPmLimit(throwable.getMessage()); + } + } else { + SingleToastUtil.showToast(throwable.getMessage()); + } + closeDialog(); + }) + .subscribe(); + + observer = (Observer) message -> { + // 在这里处理自定义通知。 + if (message != null) { + try { + if (subscribe != null) { + subscribe.dispose(); + } + LogUtil.e("SexMatchDialog系统消息" + message.getContent()); + JSONObject object = JSON.parseObject(message.getContent()); + GameMatchInfo matchInfo = new Gson().fromJson(object.toJSONString(), GameMatchInfo.class); + if (matchInfo == null || matchInfo.getData() == null || matchInfo.getFirst() != CustomNotifyType.SEX_MATCH) + return; + binding.tvTime.setVisibility(View.GONE); + binding.tvCancel.setVisibility(View.GONE); + binding.tvText.setText("匹配成功"); + binding.tvText2.setVisibility(View.VISIBLE); + binding.tvCancel.postDelayed(() -> { + AVRoomActivity.start(getContext(), matchInfo.getData().getRoomId()); + closeDialog(); + }, 2000); + + } catch (Exception e) { + } + } + }; + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, true); + + mSVGAParser = new SVGAParser(getContext()); + playSvag(SEX_MATCH_SVGA); + + subscribe = Observable.interval(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> { + if (aLong == 15) { + // SingleToastUtil.showToast("匹配超时,请尝试重新匹配"); + closeDialog(); + Single.just("").subscribe(timeOutConsumer); + } + binding.tvTime.setText((aLong + 1) + "s"); + }); + + setOnDismissListener(dialog -> { + if (subscribe != null) { + subscribe.dispose(); + } + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + HomeModel.get().removeIsomerism().subscribe(); + }); + + binding.tvCancel.setOnClickListener(v -> closeDialog()); + } + + private void playSvag(String effect) { + if (TextUtils.isEmpty(effect)) return; + try { + mSVGAParser.parse(new URL(effect), + new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + binding.svgaImageview.setLoops(100); + binding.svgaImageview.setClearsAfterStop(true); + binding.svgaImageview.setImageDrawable(new SVGADrawable(svgaVideoEntity)); + binding.svgaImageview.startAnimation(); + } + + @Override + public void onError() { + binding.svgaImageview.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/AttentionFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/AttentionFragment.java new file mode 100644 index 000000000..32ca711f1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/AttentionFragment.java @@ -0,0 +1,270 @@ +package com.yizhuan.erban.home.fragment; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.relation.adapter.AttentionListAdapter; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.tutu.room_chat.activity.NimRoomP2PMessageActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.erban.R.id.swipe_refresh; +import static com.yizhuan.erban.friend.action.AbstractSelectFriendAction.ROOM_MSG; + +/** + *

主页关注界面

+ * + * @author Administrator + * @date 2017/11/14 + */ +public class AttentionFragment extends BaseFragment { + public static final String TAG = "AttentionFragment"; + + private RecyclerView mRecylcerView; + private SwipeRefreshLayout swipeRefreshLayout; + private AttentionListAdapter adapter; + private List mAttentionInfoList = new ArrayList<>(); + private int mPage = Constants.PAGE_START; + private int type; + + private SelectFriendActivity friendActivity; + + public static AttentionFragment newInstance(int type) { + AttentionFragment attentionFragment = new AttentionFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(AbstractSelectFriendAction.KEY_TYPE, type); + attentionFragment.setArguments(bundle); + return attentionFragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof SelectFriendActivity) { + friendActivity = (SelectFriendActivity) activity; + } + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + //需要踩人等东西,所以进入这个界面需要强制刷新 + if (isVisibleToUser) { + firstLoadData(); + } + } + + @Override + public void onFindViews() { + if (getArguments() != null) { + type = getArguments().getInt(AbstractSelectFriendAction.KEY_TYPE); + } + mRecylcerView = mView.findViewById(R.id.recycler_view); + swipeRefreshLayout = mView.findViewById(swipe_refresh); + mRecylcerView.setLayoutManager(new LinearLayoutManager(getContext())); + } + + @Override + public void onSetListener() { + swipeRefreshLayout.setOnRefreshListener(onRefreshLisetener); + adapter = new AttentionListAdapter(mAttentionInfoList); + adapter.setType(type); + adapter.setRylListener(new AttentionListAdapter.onClickListener() { + @Override + public void rylListeners(AttentionInfo attentionInfo) { + if (type == ROOM_MSG) { + NimRoomP2PMessageActivity.start(getActivity(), String.valueOf(attentionInfo.getUid())); + } else { + UserInfoActivity.Companion.start(getContext(), attentionInfo.getUid()); + } + } + + @Override + public void findHimListeners(AttentionInfo attentionInfo) { + if (attentionInfo.getUserInRoom() != null) + AVRoomActivity.start(getContext(), attentionInfo.getUserInRoom().getUid()); + } + + @Override + public void sendListener(AttentionInfo attentionInfo) { + if (friendActivity != null) { + friendActivity.showSureDialog(String.valueOf(attentionInfo.getUid()), attentionInfo.avatar, attentionInfo.getNick()); + } + } + }); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mPage++; + onRefreshing(); + } + }, mRecylcerView); + } + + @Override + public void initiate() { + mRecylcerView.setAdapter(adapter); + swipeRefreshLayout.setRefreshing(true); + firstLoadData(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_fans_list; + } + + SwipeRefreshLayout.OnRefreshListener onRefreshLisetener = this::firstLoadData; + + public void firstLoadData() { + mPage = Constants.PAGE_START; + onRefreshing(); + } + + private void onRefreshing() { + AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + mPage, + Constants.PAGE_SIZE + ) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List attentionInfos) { + onGetAttentionList(attentionInfos, mPage); + } + + @Override + public void onError(Throwable e) { + onGetAttentionListFail(e.getMessage(), mPage); + } + }); + } + + public void onGetAttentionList(List attentionInfoList, int page) { + mPage = page; + if (!ListUtils.isListEmpty(attentionInfoList)) { + if (mPage == Constants.PAGE_START) { + hideStatus(); + swipeRefreshLayout.setRefreshing(false); + mAttentionInfoList.clear(); + adapter.setNewData(attentionInfoList); + if (attentionInfoList.size() < Constants.PAGE_SIZE) { + adapter.setEnableLoadMore(false); + } + } else { + adapter.loadMoreComplete(); + adapter.addData(attentionInfoList); + } + } else { + if (mPage == Constants.PAGE_START) { + swipeRefreshLayout.setRefreshing(false); + if (adapter != null) { + mAttentionInfoList.clear(); + adapter.setNewData(attentionInfoList); + } + showNoData(R.drawable.icon_common_failure, getString(R.string.no_attention_text)); + } else { + adapter.loadMoreEnd(true); + } + + } + } + + public void onGetAttentionListFail(String error, int page) { + mPage = page; + if (mPage == Constants.PAGE_START) { + swipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + adapter.loadMoreFail(); + toast(error); + } + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.frg_no_data_large_iv_transparent, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + // ------------------关注动作回调 begin------------------- + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + if (event.isFailed()) { + return; + } + onRefreshing(); + } + // ------------------关注动作回调 end------------------- + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + onRefreshing(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + mPage = Constants.PAGE_START; + showLoading(); + onRefreshing(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/CommunityNoticeAct.java b/app/src/main/java/com/yizhuan/erban/home/fragment/CommunityNoticeAct.java new file mode 100644 index 000000000..451620509 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/CommunityNoticeAct.java @@ -0,0 +1,188 @@ +package com.yizhuan.erban.home.fragment; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.community.dynamic.view.DynamicDetailActivity; +import com.yizhuan.erban.home.adapter.CommunityNoticeAdapter; +import com.yizhuan.erban.home.presenter.CommunityNoticePresenter; +import com.yizhuan.erban.home.view.ICommunityNoticeAct; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.community.bean.CommunityNoticeInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +@CreatePresenter(CommunityNoticePresenter.class) +public class CommunityNoticeAct extends BaseMvpActivity + implements ICommunityNoticeAct { + + @BindView(R.id.swipe_refresh) + SwipeRefreshLayout swipeRefreshLayout; + @BindView(R.id.recycler_view) + RecyclerView recyclerView; + + private Unbinder mUnbinder; + private CommunityNoticeAdapter mCommunityNoticeAdapter; + + public static void start(Context context) { + context.startActivity(new Intent(context, CommunityNoticeAct.class)); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.act_community_notice); + mUnbinder = ButterKnife.bind(this); + initTitleBar("全部消息", new TitleBar.TextAction("清空") { + @Override + public void performAction(View view) { + getDialogManager().showOkCancelWithTitleDialog("清空后所有互动通知将被删除\n确定清空吗?", "确定", + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + getMvpPresenter().delete(AuthModel.get().getCurrentUid()); + } + }); + } + }); + + swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + getMvpPresenter().refresh(AuthModel.get().getCurrentUid()); + } + }); + + mCommunityNoticeAdapter = new CommunityNoticeAdapter(); + mCommunityNoticeAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMore(AuthModel.get().getCurrentUid()); + + } + }, recyclerView); + mCommunityNoticeAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List list = adapter.getData(); + if (list.size() > 0 && position < list.size()) { + CommunityNoticeInfo info = list.get(position); + + if (info != null) { + switch (view.getId()) { + case R.id.cl_community_notice_list: + DynamicDetailActivity.start(CommunityNoticeAct.this, info.getDynamicId(), info.getWorldId(), 4); + break; + + case R.id.civ_avatar_community_notice_list: + UserInfoActivity.Companion.start(context, info.getUid()); + break; + } + + } + } + } + }); + recyclerView.setAdapter(mCommunityNoticeAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + + getMvpPresenter().refresh(AuthModel.get().getCurrentUid()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mUnbinder != null) { + mUnbinder.unbind(); + } + } + + @Override + public void getMsgListSuccess(List list) { + hideStatus(); + int page = getMvpPresenter().getPage(); + if (page == 1 && swipeRefreshLayout != null) { + swipeRefreshLayout.setRefreshing(false); + } else if (page > 1 && mCommunityNoticeAdapter != null) { + mCommunityNoticeAdapter.loadMoreComplete(); + } + + if (mCommunityNoticeAdapter != null) { + if (getMvpPresenter().getPage() > 1) { + mCommunityNoticeAdapter.addData(list); + } else { + mCommunityNoticeAdapter.setNewData(list); + } + + } + + } + + @Override + public void getMsgListFail(String error) { + + if (getMvpPresenter().getPage() == 1) { + showNoData(); + } + + swipeRefreshLayout.setRefreshing(false); + if (!TextUtils.isEmpty(error)) { + if (error.equals("无数据")) { + if (mCommunityNoticeAdapter != null) { + mCommunityNoticeAdapter.loadMoreEnd(); + } + } else { + if (mCommunityNoticeAdapter != null) { + mCommunityNoticeAdapter.loadMoreFail(); + } + + } + } + + } + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + showLoading(); + getMvpPresenter().refresh(AuthModel.get().getCurrentUid()); + } + }; + } + + @Override + public void clearSuccess() { + showNoData(); + swipeRefreshLayout.setRefreshing(false); + if (mCommunityNoticeAdapter != null) { + mCommunityNoticeAdapter.setNewData(null); + mCommunityNoticeAdapter.loadMoreEnd(); + } + + } + + @Override + public void clearFail(String error) { + toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/ContactsListFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/ContactsListFragment.java new file mode 100644 index 000000000..dfcb3fa26 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/ContactsListFragment.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.home.adapter.CommonMagicIndicatorAdapter; +import com.yizhuan.erban.home.adapter.ContactsIndicatorAdapter; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.ui.im.friend.FriendListFragment; +import com.yizhuan.erban.ui.im.recent.RecentListFragment; +import com.yizhuan.erban.ui.relation.FansListFragment; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public class ContactsListFragment extends BaseFragment implements ContactsIndicatorAdapter.OnItemSelectListener { + + private MagicIndicator indicator; + private ViewPager viewpager; + + public static Fragment newInstance() { + return new ContactsListFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_contact_list; + } + + @Override + public void onFindViews() { + super.onFindViews(); + indicator = getView().findViewById(R.id.indicator); + viewpager = getView().findViewById(R.id.viewpager); + + } + + @Override + public void initiate() { + List tabInfoList = new ArrayList<>(); + tabInfoList.add(getString(R.string.friend)); + tabInfoList.add(getString(R.string.attention)); + tabInfoList.add(getString(R.string.fan)); + + List mTabs = new ArrayList<>(); + mTabs.add(new FriendListFragment()); + mTabs.add(AttentionFragment.newInstance(AbstractSelectFriendAction.TYPE_NORMAL)); + mTabs.add(FansListFragment.newInstance(Constants.FAN_MAIN_PAGE_TYPE)); + + ContactsIndicatorAdapter mMsgIndicatorAdapter = new ContactsIndicatorAdapter(mContext, tabInfoList, 0); + mMsgIndicatorAdapter.setOnItemSelectListener(this); + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + commonNavigator.setAdjustMode(true); + commonNavigator.setAdapter(mMsgIndicatorAdapter); + indicator.setNavigator(commonNavigator); + // must after setNavigator + LinearLayout titleContainer = commonNavigator.getTitleContainer(); + titleContainer.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + + viewpager.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), mTabs)); + viewpager.setOffscreenPageLimit(3); + ViewPagerHelper.bind(indicator, viewpager); + + } + + + @Override + public void onItemSelect(int position) { + viewpager.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/FamilyFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/FamilyFragment.java new file mode 100644 index 000000000..822c4598e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/FamilyFragment.java @@ -0,0 +1,423 @@ +package com.yizhuan.erban.home.fragment; + +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.family.view.activity.FamilyPlazaActivity; +import com.yizhuan.erban.family.view.adapter.FamilyBannerAdapter; +import com.yizhuan.erban.home.adapter.FindStarFamilyAdapter; +import com.yizhuan.erban.home.presenter.FamilyFragmentPresenter; +import com.yizhuan.erban.home.view.IFamilyFragmentView; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.HorizontalDecoration; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.family.bean.CustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyCustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FindBannerInfo; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.Observer; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +@CreatePresenter(FamilyFragmentPresenter.class) +public class FamilyFragment extends BaseMvpFragment + implements IFamilyFragmentView, View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { + + private SwipeRefreshLayout srlRefreshContainer; + private LinearLayout rlBannerContainer; + + + private RollPagerView rpvFamilyPlaza; + private LinearLayout llFamilyPlaza; + private LinearLayout llCreateFamily; + private LinearLayout llMyFamilyContainer; + private TextView tvTitle; + private LinearLayout llMyFamily; + private SquareImageView ivCover; + private TextView tvFamilyName; + private TextView tvFamilyId; + private TextView tvFamilyMemberCount; + private LinearLayout llStarFamilyContainer; + private RecyclerView rvStartFamilyList; + + private LinearLayout llFamilyCustomerService; + private LinearLayout llFamilyInstruction; +// private TextView tvCustomerServiceHotline; +// private TextView tvCustomerServiceId; + + + private FamilyBannerAdapter bannerAdapter; + private FindStarFamilyAdapter starFamilyAdapter; + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + + // 模拟展示家族tab的操作 + if (isVisibleToUser) { + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.HOME_FAMILY_CLICK, "家族tab", null); + } + } + + public static Fragment newInstance() { + return new FamilyFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_family; + } + + @Override + public void onFindViews() { + srlRefreshContainer = (SwipeRefreshLayout) getView().findViewById(R.id.srl_refresh_container); + + rlBannerContainer = getView().findViewById(R.id.rl_banner_container); + rpvFamilyPlaza = (RollPagerView) getView().findViewById(R.id.rpv_family_plaza); + + llFamilyPlaza = (LinearLayout) getView().findViewById(R.id.ll_family_plaza); + llCreateFamily = (LinearLayout) getView().findViewById(R.id.ll_create_family); + + llMyFamilyContainer = (LinearLayout) getView().findViewById(R.id.ll_my_family_container); + tvTitle = (TextView) getView().findViewById(R.id.tv_title); + llMyFamily = (LinearLayout) getView().findViewById(R.id.ll_my_family); + ivCover = (SquareImageView) getView().findViewById(R.id.iv_cover); + tvFamilyName = (TextView) getView().findViewById(R.id.tv_family_name); + tvFamilyId = (TextView) getView().findViewById(R.id.tv_family_id); + tvFamilyMemberCount = (TextView) getView().findViewById(R.id.tv_family_member_count); + + llStarFamilyContainer = (LinearLayout) getView().findViewById(R.id.ll_star_family_container); + rvStartFamilyList = (RecyclerView) getView().findViewById(R.id.rv_start_family_list); + + llFamilyCustomerService = (LinearLayout) getView().findViewById(R.id.ll_family_customer_service); + llFamilyInstruction = (LinearLayout) getView().findViewById(R.id.ll_family_instruction); +// tvCustomerServiceHotline = (TextView) getView().findViewById(R.id.tv_customer_service_hotline); +// tvCustomerServiceId = (TextView) getView().findViewById(R.id.tv_customer_service_id); + + + } + + @Override + public void onSetListener() { + srlRefreshContainer.setOnRefreshListener(this); + llFamilyPlaza.setOnClickListener(this); + llCreateFamily.setOnClickListener(this); + llMyFamily.setOnClickListener(this); + llFamilyCustomerService.setOnClickListener(this); + llFamilyInstruction.setOnClickListener(this); + } + + @Override + public void initiate() { +// rvStartFamilyList.setLayoutManager(new FullyGridLayoutManager(getActivity(), 3)); +// rvStartFamilyList.addItemDecoration(new SpacingDecoration(0, 30, true)); + rvStartFamilyList.setLayoutManager(new LinearLayoutManager(mContext)); + rvStartFamilyList.addItemDecoration(new HorizontalDecoration(ScreenUtil.dip2px(17), true, true)); + starFamilyAdapter = new FindStarFamilyAdapter(getActivity(), new ArrayList<>()); + starFamilyAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + RankingFamilyInfo familyInfo = (RankingFamilyInfo) adapter.getData().get(position); + FamilyHomeActivity.start(getActivity(), familyInfo.getId()); + } + }); + rvStartFamilyList.setAdapter(starFamilyAdapter); + + bannerAdapter = new FamilyBannerAdapter(new ArrayList<>(), getContext()); + rpvFamilyPlaza.setAdapter(bannerAdapter); + rpvFamilyPlaza.setPlayDelay(3000); + //设置透明度 + rpvFamilyPlaza.setAnimationDurtion(500); + rpvFamilyPlaza.setVisibility(View.VISIBLE); + rpvFamilyPlaza.setHintView(new ColorPointHintView(getContext(), Color.WHITE, this.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(getContext().getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + } + + + @Override + public void onResume() { + super.onResume(); + loadData(); + getMvpPresenter().showCustomerServiceInfo().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FamilyCustomServiceInfo familyCustomServiceInfo) { + onCustomServiceInfo(familyCustomServiceInfo); + } + + @Override + public void onError(Throwable e) { + onCustomServiceFail(e.getMessage()); + } + }); + + getMvpPresenter().checkMyFamilyInfo(); + + if (ListUtils.isListEmpty(starFamilyAdapter.getData())) { + loadWeeklyStarList(); + } + } + + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); +// if (!hidden){ +// loadWeeklyStarList(); +// } + + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == llFamilyPlaza.getId()) { + FamilyPlazaActivity.start(this.getActivity()); + } else if (id == llCreateFamily.getId()) { + CommonWebViewActivity.start(this.getActivity(), UriProvider.getCreateFamilyUrl()); + } else if (id == llMyFamily.getId()) { + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.FAMILY_MY_FAMILY_CLICK, "我的家族", null); + + FamilyHomeActivity.start(getActivity(), getMvpPresenter().getMyFamily().getFamilyId()); + } else if (id == llFamilyCustomerService.getId()) { + getMvpPresenter().contactCustomerService().subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + NimP2PMessageActivity.start(getContext(), s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } else if (id == llFamilyInstruction.getId()) { + CommonWebViewActivity.start(getContext(), UriProvider.getFamilyInstructionUrl()); + } + } + + @Override + public void showMyFamilyInfo(FamilyInfo familyInfo) { + if (null != familyInfo) { + llMyFamilyContainer.setVisibility(View.VISIBLE); + GlideApp.with(this) + .load(familyInfo.getFamilyIcon()) + .dontAnimate() + .transforms(new CenterCrop(), new RoundedCorners(10)) + .into(ivCover); + tvFamilyName.setText(familyInfo.getFamilyName()); + tvFamilyId.setText(String.format(Locale.CHINA, "ID:%s", familyInfo.getFamilyId())); + tvFamilyMemberCount.setText(String.format(Locale.CHINA, "成员:%s", String.valueOf(familyInfo.getMemberCount()))); + + llCreateFamily.setVisibility(View.GONE); + } else { + llCreateFamily.setVisibility(View.VISIBLE); + llMyFamilyContainer.setVisibility(View.GONE); + } + } + + @Override + public void onCustomServiceInfo(FamilyCustomServiceInfo customServiceInfo) { + List customServiceInfoList = customServiceInfo.getServices(); + for (int i = 0; i < customServiceInfoList.size(); i++) { + CustomServiceInfo serviceInfo = customServiceInfoList.get(i); + if (serviceInfo.getType() == CustomServiceInfo.TYPE_ONLINE) { +// tvCustomerServiceId.setText(String.format(getResources().getString(R.string.family_customer_service_hint), +// serviceInfo.getContent())); + } else if (serviceInfo.getType() == CustomServiceInfo.TYPE_PHONE) { +// tvCustomerServiceHotline.setText(String.format(getResources().getString(R.string.family_customer_service_hotline), +// serviceInfo.getContent())); + } + } + } + + @Override + public void onCustomServiceFail(String reason) { + toast(reason); + } + + private void loadWeeklyStarList() { + getMvpPresenter().loadWeeklyStarList().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List list) { + if (ListUtils.isListEmpty(list)) { + llStarFamilyContainer.setVisibility(View.GONE); + return; + } + llStarFamilyContainer.setVisibility(View.VISIBLE); + starFamilyAdapter.setNewData(list); + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + @Override + public void onRefresh() { + loadData(); + } + + private void loadData() { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + getMvpPresenter().loadBannerDate().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List bannerInfoList) { + emitter.onNext(1); + if (ListUtils.isListEmpty(bannerInfoList)) { + rlBannerContainer.setVisibility(View.GONE); + return; + } + rlBannerContainer.setVisibility(View.VISIBLE); + bannerAdapter.setNewData(bannerInfoList); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + emitter.onNext(1); + } + }); + + getMvpPresenter().loadWeeklyStarList().subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List list) { + emitter.onNext(1); + if (ListUtils.isListEmpty(list)) { + llStarFamilyContainer.setVisibility(View.GONE); + return; + } + llStarFamilyContainer.setVisibility(View.VISIBLE); + starFamilyAdapter.setNewData(list); + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + emitter.onNext(1); + } + }); + } + }).subscribe(new Observer() { + Disposable disposable; + int i = 0; + + @Override + public void onSubscribe(Disposable d) { + disposable = d; + mCompositeDisposable.add(d); + } + + @Override + public void onNext(Integer integer) { + i += integer; + if (i == 2) { + srlRefreshContainer.setRefreshing(false); + disposable.dispose(); + } + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/FindFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/FindFragment.java new file mode 100644 index 000000000..a970ce247 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/FindFragment.java @@ -0,0 +1,574 @@ +package com.yizhuan.erban.home.fragment; + +import android.app.Activity; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.jude.rollviewpager.RollPagerView; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.home.adapter.BannerAdapter; +import com.yizhuan.erban.home.adapter.ErbanTopMessageAdapter; +import com.yizhuan.erban.home.adapter.FindAdapter; +import com.yizhuan.erban.home.adapter.HomeHallAdapter; +import com.yizhuan.erban.home.presenter.FindFragmentPresenter; +import com.yizhuan.erban.home.view.IFindFragmentView; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.erban.public_chat_hall.msg.viewholder.ChatRoomViewHolderHelper; +import com.yizhuan.erban.ui.widget.InterceptTouchLayout; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.SpacingDecoration; +import com.yizhuan.tutu.mentoring_relationship.activity.MentoringRelationshipActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.LoginEvent; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftReceiveInfo; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.FindEntranceInfo; +import com.yizhuan.xchat_android_core.home.bean.FindInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeHallMsgInfo; +import com.yizhuan.xchat_android_core.home.bean.MakeFriendsHallInfo; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessageInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameRespondAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; +import com.yizhuan.xchat_android_core.level.UserLevelResourceType; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.public_chat_hall.attachment.AitFriendsAttachment; +import com.yizhuan.xchat_android_core.public_chat_hall.bean.AitFriendsInfo; +import com.yizhuan.xchat_android_core.public_chat_hall.event.PublicChatHallAitMeEvent; +import com.yizhuan.xchat_android_core.public_chat_hall.event.PublicChatHallHistoryEvent; +import com.yizhuan.xchat_android_core.public_chat_hall.event.PublicChatHallMsgIncomingEvent; +import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager; +import com.yizhuan.xchat_android_core.radish.event.ReceivePrizeEvent; +import com.yizhuan.xchat_android_core.radish.event.SignInSuccessEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.list.NoScrollingLinearLayoutManager; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * @author jack + * @Description + * @Date 2018/5/22 + */ +@CreatePresenter(FindFragmentPresenter.class) +public class FindFragment extends BaseMvpFragment + implements IFindFragmentView, View.OnClickListener { + public final static String TAG = FindFragment.class.getSimpleName(); + + private RecyclerView rvEntrance; + private LinearLayout llMentoringRelationship; + private InterceptTouchLayout llPublicChatHallContainer; + + private FindAdapter findAdapter; + private View tvMore; + private TextView tvHallNewAitTips; + private RecyclerView publicChatHallMsgView; + private MakeFriendsHallInfo makeFriendsHallInfo; + private SimpleDateFormat chatHallTimeFormater = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()); + private ChatRoomMessage tempMsg = null; + private final int hallMsgMaxSize = 30; + private HomeHallAdapter homeHallAdapter; +// private CircleImageView newUserAvatarOne; +// private CircleImageView newUserAvatarTwo; +// private CircleImageView newUserAvatarThree; + + //banner + private RollPagerView rollPagerView; + //头条 + private BetterMarqueeView betterMarqueeView; + + private View llTopMsgContainer; + + private SwipeRefreshLayout swipeRefresh; + + public static Fragment newInstance() { + return new FindFragment(); + } + + + @Override + public int getRootLayoutId() { + return R.layout.fragment_find; + } + + + @Override + public void onFindViews() { + rvEntrance = (RecyclerView) getView().findViewById(R.id.rv_entrance); + + tvMore = getView().findViewById(R.id.tv_more); + tvHallNewAitTips = getView().findViewById(R.id.tv_new_ait_tip); + publicChatHallMsgView = getView().findViewById(R.id.rv_hall_msg_list); + + llPublicChatHallContainer = getView().findViewById(R.id.ll_public_chat_hall_container); + llMentoringRelationship = getView().findViewById(R.id.ll_mentoring_relationship); + +// newUserAvatarOne = getView().findViewById(R.id.iv_new_user_1); +// newUserAvatarTwo = getView().findViewById(R.id.iv_new_user_2); +// newUserAvatarThree = getView().findViewById(R.id.iv_new_user_3); + + rollPagerView = getView().findViewById(R.id.roll_view); + betterMarqueeView = getView().findViewById(R.id.bmv_marquee_view); + llTopMsgContainer = getView().findViewById(R.id.ll_top_msg_container); + + swipeRefresh = getView().findViewById(R.id.swipe_refresh); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = super.onCreateView(inflater, container, savedInstanceState); + EventBus.getDefault().register(this); + return mView; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onSetListener() { + tvMore.setOnClickListener(this); + tvHallNewAitTips.setOnClickListener(this); + llPublicChatHallContainer.setOnClickListener(this); + llMentoringRelationship.setOnClickListener(this); + } + + @Override + public void initiate() { + Activity activity = getActivity(); + if (activity == null) { + return; + } + rvEntrance.setLayoutManager(new GridLayoutManager(mContext, 4)); + + findAdapter = new FindAdapter(getActivity(), new ArrayList<>()); + rvEntrance.setAdapter(findAdapter); + rvEntrance.addItemDecoration(new SpacingDecoration(ScreenUtil.dip2px(12), ScreenUtil.dip2px(10), false)); + + makeFriendsHallInfo = new MakeFriendsHallInfo(); + makeFriendsHallInfo.setAitUserName(null); + ArrayList list = new ArrayList<>(PublicChatHallDataManager.get().getMessages()); + Collections.reverse(list); + while (list.size() > hallMsgMaxSize) { + list.remove(0); + } + makeFriendsHallInfo.setMsgList(transformChatRoomMessage(list)); + List chatRoomMessageList = makeFriendsHallInfo.getMsgList(); + publicChatHallMsgView.setItemAnimator(null); + publicChatHallMsgView.setFocusable(false); + NoScrollingLinearLayoutManager noScrollingLinearLayoutManager = + new NoScrollingLinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false); + noScrollingLinearLayoutManager.setScrollEnabled(false); + publicChatHallMsgView.setLayoutManager(noScrollingLinearLayoutManager); + if (publicChatHallMsgView.getItemDecorationCount() == 0) { + publicChatHallMsgView.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(mContext, 10), false)); + } + homeHallAdapter = new HomeHallAdapter(mContext, chatRoomMessageList); + publicChatHallMsgView.setAdapter(homeHallAdapter); + publicChatHallMsgView.scrollToPosition(homeHallAdapter.getItemCount() - 1); + //增加刷新功能 + swipeRefresh.setOnRefreshListener(() -> getMvpPresenter().loadData()); + + } + + /** + * 设置轻寻头条数据 + */ + private void setTuTuTopMessageData(VMTopMessageInfo topMessageInfo) { + ErbanTopMessageAdapter adapter = new ErbanTopMessageAdapter(mContext, topMessageInfo.getVmTopMessageList()); + betterMarqueeView.setAdapter(adapter); + betterMarqueeView.start(); + llTopMsgContainer.setOnClickListener(v -> PublicChatHallHomeActivity.openHeadlinePage(mContext)); + } + + + @Override + public void onResume() { + super.onResume(); + if (null == getMvpPresenter().getFindInfo()) { + getMvpPresenter().loadData(); +// getMvpPresenter().loadNewerList(); + } + } + + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (!hidden) { + getMvpPresenter().loadData(); +// getMvpPresenter().loadNewerList(); + } + + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvMore.getId() || id == tvHallNewAitTips.getId() || id == llPublicChatHallContainer.getId()) { + PublicChatHallHomeActivity.openPublicChatHallPage(mContext); + makeFriendsHallInfo.setAitUserName(null); + if (tvHallNewAitTips.getVisibility() == View.VISIBLE) { + tvHallNewAitTips.setVisibility(View.GONE); + } + } else if (id == llMentoringRelationship.getId()) { + MentoringRelationshipActivity.start(mContext); + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.FIND_APPRENTICE_ENTRANCE, "收个徒弟赢金币"); + } + } + + @Override + public void onLoadData(FindInfo findInfo) { + swipeRefresh.setRefreshing(false); + findAdapter.setNewData(findInfo.getBanners()); + //设置banner + setBannerData(findInfo.getBannerVos()); + VMTopMessageInfo info = getMvpPresenter().transformHomeData2TopMessageInfos(findInfo.getTopLineVos()); + if (info == null) { + llTopMsgContainer.setVisibility(View.GONE); + } else { + llTopMsgContainer.setVisibility(View.VISIBLE); + setTuTuTopMessageData(info); + } + } + + private void setBannerData(List bannerList) { + if (!ListUtils.isListEmpty(bannerList)) { + //审核中状态,去掉跳转房间banner + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = bannerList.iterator(); + while (iterator.hasNext()) { + BannerInfo bannerInfo = iterator.next(); + if (bannerInfo.getSkipType() == 2) { + iterator.remove(); + } + } + } + ViewGroup.LayoutParams layoutParams = rollPagerView.getLayoutParams(); + int bannerWidth = UIUtil.getScreenWidth(mContext) - UIUtil.dip2px(mContext, 20) * 2; + layoutParams.width = bannerWidth; + layoutParams.height = bannerWidth * 232 / 670; + rollPagerView.setLayoutParams(layoutParams); + + rollPagerView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + BannerAdapter bannerAdapter = new BannerAdapter(bannerList, mContext); + rollPagerView.setAdapter(bannerAdapter); + rollPagerView.setPlayDelay(3000); + //设置透明度 + rollPagerView.setAnimationDurtion(500); + rollPagerView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + } else { + rollPagerView.setVisibility(View.GONE); + } + } + + @Override + public void onLoadDataFail(String error) { + swipeRefresh.setRefreshing(false); +// Toast.makeText(this.getContext(), error, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(error); + } + +// @Override +// public void onLoadNewUserList(List userInfoList) { +// if (!ListUtils.isListEmpty(userInfoList)) { +// newUserAvatarOne.setVisibility(View.GONE); +// newUserAvatarTwo.setVisibility(View.GONE); +// newUserAvatarThree.setVisibility(View.GONE); +// for (int i = 0; i < userInfoList.size(); i++) { +// if (i == 0) { +// newUserAvatarOne.setVisibility(View.VISIBLE); +// ImageLoadUtils.loadAvatar(getContext(), userInfoList.get(i).getAvatar(), newUserAvatarOne); +// } +// if (i == 1) { +// newUserAvatarTwo.setVisibility(View.VISIBLE); +// ImageLoadUtils.loadAvatar(getContext(), userInfoList.get(i).getAvatar(), newUserAvatarTwo); +// } +// if (i == 2) { +// newUserAvatarThree.setVisibility(View.VISIBLE); +// ImageLoadUtils.loadAvatar(getContext(), userInfoList.get(i).getAvatar(), newUserAvatarThree); +// } +// } +// } +// } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPublicChatHallHistoryEvent(PublicChatHallHistoryEvent event) { + ArrayList list = new ArrayList<>(event.getMessages()); + Collections.reverse(list); + while (list.size() > hallMsgMaxSize) { + list.remove(0); + } + updateHallData(list); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPublicChatHallMsgIncomingEvent(PublicChatHallMsgIncomingEvent event) { + ArrayList chatRoomMessages = new ArrayList<>(); + chatRoomMessages.add(event.getChatRoomMessage()); + updateHallData(chatRoomMessages); + } + + + private void updateHallData(List messageList) { + if (ListUtils.isListEmpty(makeFriendsHallInfo.getMsgList())) { + ArrayList list = new ArrayList<>(messageList); + makeFriendsHallInfo.setMsgList(transformChatRoomMessage(list)); + } else { + while (makeFriendsHallInfo.getMsgList().size() > hallMsgMaxSize) { + makeFriendsHallInfo.getMsgList().remove(0); + } + makeFriendsHallInfo.getMsgList().addAll(transformChatRoomMessage(messageList)); + } + + List chatRoomMessageList = makeFriendsHallInfo.getMsgList(); + homeHallAdapter.setNewData(chatRoomMessageList); + publicChatHallMsgView.scrollToPosition(homeHallAdapter.getItemCount() - 1); + + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPublicChatHallAitMeEvent(PublicChatHallAitMeEvent event) { + makeFriendsHallInfo.setAitUserName(event.getNick()); + if (!TextUtils.isEmpty(makeFriendsHallInfo.getAitUserName())) { + tvHallNewAitTips.setVisibility(View.VISIBLE); + String temp = makeFriendsHallInfo.getAitUserName(); + if (temp.length() >= 6) { + temp = temp.substring(0, 4).concat("..."); + } + tvHallNewAitTips.setText(String.format(mContext.getResources().getString(R.string.hall_new_ait_tip), temp)); + } else { + tvHallNewAitTips.setVisibility(View.GONE); + } + + } + + /** + * 把chatRoomMessage 转换成我们首页显示上的bean + * + * @param messageList + * @return + */ + private List transformChatRoomMessage(List messageList) { + List homeHallMsgInfos = new ArrayList<>(); + + for (ChatRoomMessage chatRoomMessage : messageList) { + if (chatRoomMessage.getAttachment() instanceof GameRespondAttachment + || chatRoomMessage.getAttachment() instanceof ImTipAttachment) { + continue; + } + + if (isNeedShowTimeFlag(chatRoomMessage, tempMsg)) { + HomeHallMsgInfo item = new HomeHallMsgInfo(); + item.setItemType(HomeHallMsgInfo.ITEM_TYPE_TIP); + item.setMessageType(HomeHallMsgInfo.MESSAGE_TYPE_TIME); + item.setFormatTime(chatHallTimeFormater.format(new Date(chatRoomMessage.getTime()))); + homeHallMsgInfos.add(item); + } + tempMsg = chatRoomMessage; + + HomeHallMsgInfo item = new HomeHallMsgInfo(); + item.setFromAccount(chatRoomMessage.getFromAccount()); + if (item.getFromAccount().equals(String.valueOf(AuthModel.get().getCurrentUid()))) { + item.setItemType(HomeHallMsgInfo.ITEM_TYPE_RIGHT); + } else { + item.setItemType(HomeHallMsgInfo.ITEM_TYPE_LEFT); + } + final com.netease.nimlib.sdk.uinfo.model.UserInfo userInfo = NimUIKit.getUserInfoProvider().getUserInfo(chatRoomMessage.getFromAccount()); + if (userInfo != null) { + item.setSenderAvatar(userInfo.getAvatar()); + } + item.setNick(ChatRoomViewHolderHelper.getNameText(chatRoomMessage)); + if (chatRoomMessage.getAttachment() instanceof ImGameAttachment) { + item.setContent("发起了一条游戏邀请"); + } else { + item.setContent(chatRoomMessage.getContent()); + } + + //贵族等级,等级,魅力等级相关 + Map remoteExtension = chatRoomMessage.getRemoteExtension(); + if (remoteExtension != null) { + Map extension = (Map) remoteExtension.get(chatRoomMessage.getFromAccount()); + if (extension != null) { + item.setNobleLevel(extension.get(NobleResourceType.KEY_LEVEL) + ""); + item.setUserLevelUrl((String) extension.get(UserLevelResourceType.EXPER_URL)); + item.setUserCharmLevelUrl((String) extension.get(UserLevelResourceType.CHARM_URL)); + if (extension.get(UserInfo.IS_OFFICIAL) != null) { + item.setOfficial((Boolean) extension.get(UserInfo.IS_OFFICIAL)); + } else { + if (extension.get(UserInfo.DEF_USER) != null) { + int userType = (int) extension.get(UserInfo.DEF_USER); + item.setOfficial(userType == UserInfo.USER_TYPE_OFFICIAL); + } + } + if (extension.get(UserInfo.IS_NEW_USER) != null) { + item.setNewUser((Boolean) extension.get(UserInfo.IS_NEW_USER)); + } + if (extension.get(UserInfo.HAS_PRETTY) != null) { + item.setPrettyErbanNo((Boolean) extension.get(UserInfo.HAS_PRETTY + )); + } + } + } + + //礼物的消息的时候 + MsgAttachment attachment = chatRoomMessage.getAttachment(); + if (attachment != null) { + CustomAttachment customAttachment = (CustomAttachment) chatRoomMessage.getAttachment(); + int first = customAttachment.getFirst(); + int second = customAttachment.getSecond(); + if (first == CustomAttachment.CUSTOM_MSG_PUBLIC_CHAT_HALL) { + if (second == CustomAttachment.CUSTOM_MSG_SUB_PUBLIC_CHAT_HALL_GIFT) { + GiftAttachment giftAttachment = (GiftAttachment) customAttachment; + GiftReceiveInfo giftReceiveInfo = giftAttachment.getGiftReceiveInfo(); + item.setMessageType(HomeHallMsgInfo.MESSAGE_TYPE_GIFT); + item.setTargetNick(giftReceiveInfo.getTargetNick()); + item.setGiftCount(giftReceiveInfo.getGiftNum()); + GiftInfo giftInfo = giftReceiveInfo.getGift(); + if (giftInfo == null) { + giftInfo = GiftModel.get().findGiftInfoById(giftReceiveInfo.getGiftId()); + } + if (null != giftInfo) { + item.setGiftImage(giftInfo.getGiftUrl()); + } + + //这里使得内容不为空 + String sb = "赠送 " + giftReceiveInfo.getTargetNick() + "\n" + + "礼物" + + "x" + + giftReceiveInfo.getGiftNum(); + item.setContent(sb); + } else if (second == CustomAttachment.CUSTOM_MSG_SUB_PUBLIC_CHAT_HALL_AIT) { + AitFriendsAttachment aitFriendsAttachment = (AitFriendsAttachment) customAttachment; + AitFriendsInfo aitFriendsInfo = aitFriendsAttachment.getAitFriendsInfo(); + item.setContent(aitFriendsInfo.getContent()); + } + } + } + + homeHallMsgInfos.add(item); + } + return homeHallMsgInfos; + } + + private boolean isNeedShowTimeFlag(ChatRoomMessage message, @Nullable ChatRoomMessage anchor) { + boolean update = false; + if (anchor == null) { + return true; + } + long time = anchor.getTime(); + long now = message.getTime(); + if (now - time > (long) (5 * 60 * 1000)) { + update = true; + } + return update; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginEvent(LoginEvent event) { + //不同用户的,签到和任务状态不同,需要刷新 + getMvpPresenter().loadData(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSignInSuccessEvent(SignInSuccessEvent event) { + //签到成功,做一下数字处理 + if (findAdapter == null) { + return; + } + List list = findAdapter.getData(); + if (ListUtils.isListEmpty(list)) { + return; + } + for (FindEntranceInfo info : list) { + if (info == null) { + continue; + } + if (info.getActivityType() == FindEntranceInfo.ACTIVITYTYPE_SIGN_IN) { + info.setSignStatus(true); + } else if (info.getActivityType() == FindEntranceInfo.ACTIVITYTYPE_TASK) { + int num = info.getMissionNum() - 1; + if (num < 0) { + num = 0; + } + info.setMissionNum(num); + } + } + findAdapter.notifyDataSetChanged(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceivePrizeEvent(ReceivePrizeEvent event) { + getMvpPresenter().loadData(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/FindTabFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/FindTabFragment.java new file mode 100644 index 000000000..250181ab8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/FindTabFragment.java @@ -0,0 +1,229 @@ +package com.yizhuan.erban.home.fragment; + +import android.annotation.SuppressLint; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CoordinatorLayout; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.widget.DragLayout; +import com.yizhuan.erban.community.publish.view.PublishActivity; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.home.adapter.TopMagicIndicatorAdapter; +import com.yizhuan.erban.home.presenter.FindTabFragmentPresenter; +import com.yizhuan.erban.home.view.IFindTabFragmentView; +import com.yizhuan.erban.community.square.SquareFragment; +import com.yizhuan.erban.ui.behavior.FixAppBarBehavior; +import com.yizhuan.erban.ui.widget.OnPageSelectedListener; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.community.event.UnReadCountEvent; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.functions.BiConsumer; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + +@CreatePresenter(FindTabFragmentPresenter.class) +public class FindTabFragment extends BaseMvpFragment + implements IFindTabFragmentView, TopMagicIndicatorAdapter.OnItemSelectListener, View.OnClickListener { + + public static final String TAG = "FindTabFragment"; + + private MagicIndicator miHomeIndicator; + private ViewPager mainViewpager; + + private FrameLayout flContactList; + private TextView tvCommunityUnread; + private AppBarLayout appBarLayout; + private RelativeLayout rlTopGroup; + private DragLayout ivSquarePublish; + + public static Fragment newInstance() { + return new FindFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_find_tab; + } + + @Override + public void onFindViews() { + miHomeIndicator = mView.findViewById(R.id.mi_home_indicator); + mainViewpager = mView.findViewById(R.id.main_viewpager); + + flContactList = mView.findViewById(R.id.fl_contact_list); + tvCommunityUnread = mView.findViewById(R.id.msg_number); + appBarLayout = mView.findViewById(R.id.app_bar_layout); + + rlTopGroup = mView.findViewById(R.id.rl_top_group); + ivSquarePublish = mView.findViewById(R.id.iv_square_publish); + } + + @Override + public void onSetListener() { + if (flContactList != null) { + flContactList.setOnClickListener(this); + } + + if (ivSquarePublish != null) { + ivSquarePublish.setOnClickListener(this); + } + } + + @Override + public void initiate() { + EventBus.getDefault().register(this); + + List mTabInfoList = new ArrayList<>(); + List fragmentList = new ArrayList<>(); + + //广场 1.3.2版本添加 + mTabInfoList.add(getResources().getString(R.string.dys_find_tab_square)); + fragmentList.add(SquareFragment.newInstance()); + + mTabInfoList.add(getResources().getString(R.string.main_find)); + fragmentList.add(FindFragment.newInstance()); + + if (!MarketVerifyModel.get().isMarketChecking()) { + mTabInfoList.add(getResources().getString(R.string.main_tab_family)); + fragmentList.add(FamilyFragment.newInstance()); + } + + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + TopMagicIndicatorAdapter magicIndicatorAdapter = new TopMagicIndicatorAdapter(getContext(), mTabInfoList); + magicIndicatorAdapter.setOnItemSelectListener(this); + + commonNavigator.setAdapter(magicIndicatorAdapter); + miHomeIndicator.setNavigator(commonNavigator); + mainViewpager.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), fragmentList)); + mainViewpager.setOffscreenPageLimit(3); + ViewPagerHelper.bind(miHomeIndicator, mainViewpager); + + getUnReadCount(); + mainViewpager.addOnPageChangeListener(new OnPageSelectedListener() { + @Override + public void onPageSelected(int position) { + updateTopView(position); + } + }); + updateTopView(0); + + } + + private void updateTopView(int currPos) { + AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) rlTopGroup.getLayoutParams(); + if (currPos == 0) { + ivSquarePublish.setVisibility(VISIBLE); + flContactList.setVisibility(VISIBLE); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL); + } else { + ivSquarePublish.setVisibility(GONE); + flContactList.setVisibility(View.INVISIBLE); + params.setScrollFlags(0); + } + rlTopGroup.setLayoutParams(params); + } + + + public void scrollToTop() { + try { + FixAppBarBehavior behavior = (FixAppBarBehavior) + ((CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams()) + .getBehavior(); + if (behavior != null) { + behavior.setTopAndBottomOffset(0); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void onItemSelect(int position) { + mainViewpager.setCurrentItem(position); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onUnReadCount(UnReadCountEvent event) { + setNumber(event.getTotal()); + } + + @SuppressLint("SetTextI18n") + public void setNumber(int number) { + if(tvCommunityUnread instanceof BubbleView){ + ((BubbleView) tvCommunityUnread).setNumText(number); + return; + } + tvCommunityUnread.setVisibility(number <= 0 ? GONE : VISIBLE); + if (number > 99) { + tvCommunityUnread.setText("99+"); + } else + tvCommunityUnread.setText(String.valueOf(number)); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoadLoginUserInfoEvent event) { + getUnReadCount(); + } + + @SuppressWarnings("CheckResult") + private void getUnReadCount() { + HomeModel.get().getUnreadCount(AuthModel.get().getCurrentUid()) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(Integer integer, Throwable throwable) throws Exception { + if (integer != null) { + EventBus.getDefault().post(new UnReadCountEvent(integer)); + } + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.fl_contact_list: + CommunityNoticeAct.start(mContext); + break; + + case R.id.iv_square_publish: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_PUBLISH_MOMENTS_B, + "发布动态-广场"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_PUBLISH_MOMENTS, + "发布动态-区分小世界-无小世界"); + PublishActivity.start(getDialogManager()); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/GameHomeFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/GameHomeFragment.java new file mode 100644 index 000000000..00df10cc9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/GameHomeFragment.java @@ -0,0 +1,1130 @@ +package com.yizhuan.erban.home.fragment; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.DynamicDrawableSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.ImageSpan; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.PopupWindow; +import android.widget.TextView; + +import com.amap.api.location.AMapLocation; +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationClientOption; +import com.amap.api.location.AMapLocationListener; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; +import com.bumptech.glide.request.RequestOptions; +import com.jude.rollviewpager.Util; +import com.jude.rollviewpager.hintview.ColorPointHintView; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.avroom.game.MatchActivity; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.base.list.BaseViewHolder; +import com.yizhuan.erban.base.list.CommonAdapter; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.FragmentGameHomeBinding; +import com.yizhuan.erban.home.adapter.BannerAdapter; +import com.yizhuan.erban.home.adapter.MainMagicIndicatorAdapter; +import com.yizhuan.erban.home.dialog.CreateRoomDialog; +import com.yizhuan.erban.home.presenter.MainFragmentPresenter; +import com.yizhuan.erban.home.view.IMainFragmentView; +import com.yizhuan.erban.location.LocationUploadEvent; +import com.yizhuan.erban.radish.signin.SignInActivity; +import com.yizhuan.erban.ui.search.SearchActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.OnPageSelectedListener; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.erban.utils.CommonJumpHelper; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.certification.CertificationModel; +import com.yizhuan.xchat_android_core.family.bean.HomeBannerInfo; +import com.yizhuan.xchat_android_core.family.bean.HomeTitleInfo; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.TagListInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.erban.location.LocationManager; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.settings.SettingsModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.CurrentUserInfoCompleteEvent; +import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.jetbrains.annotations.NotNull; + +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Observable; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_FORCE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_GUIDE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_NONE; +import static com.yizhuan.xchat_android_core.home.bean.BannerInfo.SKIP_TYPE_ROUTER; +import static com.yizhuan.xchat_android_core.home.bean.BannerInfo.SKIP_TYP_APP; +import static com.yizhuan.xchat_android_core.home.bean.BannerInfo.SKIP_TYP_H5; + +/** + * 轻寻首页 + */ +@CreatePresenter(MainFragmentPresenter.class) +public class GameHomeFragment extends BaseMvpFragment + implements IMainFragmentView, View.OnClickListener, MainMagicIndicatorAdapter.OnItemSelectListener { + public static final String TAG = "GameHomeFragment"; + private FragmentGameHomeBinding mBinding; + + //声明AMapLocationClient类对象 + public AMapLocationClient mLocationClient = null; + //声明定位回调监听器 + public AMapLocationListener mLocationListener = new AMapLocationListener() { + + @Override + public void onLocationChanged(AMapLocation aMapLocation) { + long uid = AuthModel.get().getCurrentUid(); + if (aMapLocation != null && aMapLocation.getErrorCode() == 0 && uid != 0L) { + try { + LocationManager.saveUploadTime(); + getMvpPresenter().uploadAddress(AuthModel.get().getCurrentUid(), aMapLocation.getAddress(), Integer.parseInt(aMapLocation.getAdCode()), aMapLocation.getLongitude(), aMapLocation.getLatitude()); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + }; + //声明AMapLocationClientOption对象 + public AMapLocationClientOption mLocationOption = null; + private List mHomeTitleInfos; + private List mFragments; + private volatile boolean isUserLogin; + private volatile boolean initHomeTitle; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_open_room: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_createroom_click, "创建房间按钮"); + openRoom(); + break; + + case R.id.tv_search_room: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_SEARCH, "搜索"); + SearchActivity.start(getActivity()); + break; + + case R.id.iv_to_sign_in: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_GAME_HOMEPAGE_SIGN_CLICK, + "签到-首页"); + SignInActivity.start(mContext); + SharedPreferenceUtils.put("sign_entrance_" + AuthModel.get().getCurrentUid(), 1); + break; + + case R.id.layout_empty: + getHomeBannerInfo(); + break; + } + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_game_home; + } + + @Override + public void onFindViews() { + mBinding = DataBindingUtil.bind(mView); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onSetListener() { + mBinding.setClick(this); + mBinding.setOpenVisible(true); + } + + @Override + public void initiate() { + isUserLogin = AuthModel.get().getCurrentUid() != 0; + mBinding.rollView.setVisibility(View.GONE); + getHomeBannerInfo(); + + initLocation(); + initGuide(); + } + + private void getHomeBannerInfo() { + getMvpPresenter().getHomeBannerInfo(); + } + + private void initLocation() { + //初始化定位 + mLocationClient = new AMapLocationClient(getContext().getApplicationContext()); + //设置定位回调监听 + mLocationClient.setLocationListener(mLocationListener); + + mLocationOption = new AMapLocationClientOption(); + mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); + mLocationOption.setOnceLocation(true); + mLocationOption.setNeedAddress(true); + mLocationOption.setMockEnable(true); + mLocationClient.setLocationOption(mLocationOption); + } + + /** + * 初始化tab + */ + private void initTitleTab(List homeTitleInfos) { + if (ListUtils.isListEmpty(homeTitleInfos)) { + return; + } + initHomeTitle = true; + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + int gender = 3; + if (userInfo != null) { + gender = userInfo.getGender(); + } + List mTabInfoList = new ArrayList<>(); + if (!ListUtils.isListEmpty(mFragments)) { + mFragments.clear(); + } + mFragments = new ArrayList<>(); + + // 审核中模式去掉这个 tab + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = homeTitleInfos.iterator(); + while (iterator.hasNext()) { + HomeTitleInfo next = iterator.next(); + // 没法准确判断「合拍男神女神」只能是把第一个可以下拉的 item 给删除掉 + if (!ListUtils.isListEmpty(next.getOpts())) { + iterator.remove(); + } + } + } + + for (HomeTitleInfo homeTitleInfo : homeTitleInfos) { + //过滤对象是空和没有标签名同时也没有子标签的情况 + if (homeTitleInfo == null || (TextUtils.isEmpty(homeTitleInfo.getName()) && !homeTitleInfo.hasSubTitle())) { + continue; + } + Log.e(TAG, "initTitleTab: " + homeTitleInfo); + HomeTitleInfo defaultValue = homeTitleInfo.getDefault(gender); + CharSequence title; + int tabId; + Fragment fragment; + if (defaultValue != null) { + String name = defaultValue.getName(); + if (name != null) { + name = name.trim(); + } + title = getArrowSpannableString(false, name); + tabId = defaultValue.getId(); + fragment = RecommendationFragment.newInstance(String.valueOf(tabId)); + + } else { + String name = homeTitleInfo.getName(); + if (name != null) { + name = name.trim(); + } + title = name; + tabId = homeTitleInfo.getTabId(); + fragment = HomeOtherTabFragment.newInstance(tabId); + } + mFragments.add(fragment); + mTabInfoList.add(title); + + } + + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + MainMagicIndicatorAdapter magicIndicatorAdapter = new MainMagicIndicatorAdapter(getContext(), mTabInfoList); + magicIndicatorAdapter.setOnItemSelectListener(this); + + commonNavigator.setAdapter(magicIndicatorAdapter); + mBinding.magicIndicator.setNavigator(commonNavigator); + commonNavigator.getTitleContainer().setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + + mBinding.viewPager.setOffscreenPageLimit(5); + mBinding.viewPager.setAdapter(new RoomContributeListAdapter(getChildFragmentManager(), mFragments)); + mBinding.viewPager.addOnPageChangeListener(new OnPageSelectedListener() { + @Override + public void onPageSelected(int position) { + mLastPosition = position; + } + }); + ViewPagerHelper.bind(mBinding.magicIndicator, mBinding.viewPager); + + } + + private void exitRoom(BaseAdapter adapter, int position) { + if (DemoCache.readFirstMatchDialog()) { + DemoCache.saveFirstMatchDialog(); + getDialogManager().showOkCancelDialog("匹配玩家将关闭当前房间(进房限制取消)并解散房内的用户", + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + getDialogManager().showProgressDialog(getActivity()); + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + getDialogManager().dismissDialog(); + MatchActivity.start(getActivity(), adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("退出房间失败"); + } + }); + + } + }); + } else { + getDialogManager().showProgressDialog(getActivity()); + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + getDialogManager().dismissDialog(); + MatchActivity.start(getActivity(), adapter.getItem(position)); + } + + @Override + public void onFail(int code, String error) { + getDialogManager().dismissDialog(); + toast("退出房间失败"); + } + }); + } + } + + private void openRoom() { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null && !userInfo.isCertified()) { + switch (CertificationModel.get().getCertificationType()) { + default: + case CER_TYPE_NONE: + // do nothing + openCreateRoomTypeDialog(); + break; + + case CER_TYPE_FORCE: + getDialogManager().showTipsDialog(getCertificationTips(), + getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(getContext(), + UriProvider.getTutuRealNamePage()); + } + }); + break; + + case CER_TYPE_GUIDE: + getDialogManager().showTipsDialog(getCertificationTips(), + getString(R.string.go_to_certification), + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + openCreateRoomTypeDialog(); + } + + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(getContext(), + UriProvider.getTutuRealNamePage()); + } + }); + break; + } + } else { + openCreateRoomTypeDialog(); + } + + } + + private void openCreateRoomTypeDialog() { + new CreateRoomDialog(getActivity(), new CreateRoomDialog.OpenRoomListener() { + @Override + public void onNormalRoom() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_createroom_ordinary_click, "创建普通房"); + getRoomInfo(RoomInfo.ROOMTYPE_HOME_PARTY); + } + + @Override + public void onCpRoom() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_createroom_cp_click, "创建陪伴房"); + getRoomInfo(RoomInfo.ROOMTYPE_CP); + } + }).openDialog(); + } + + @NonNull + private SpannableStringBuilder getCertificationTips() { + String tips = getString(R.string.tips_need_to_certification); + SpannableStringBuilder builder = new SpannableStringBuilder(tips); + builder.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), + tips.length() - 4, tips.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + return builder; + } + + private void getRoomInfo(int roomType) { + AvRoomModel.get().requestRoomInfoFromService(String.valueOf(AuthModel.get().getCurrentUid()), + new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + if (data.getType() != 0 + && data.getType() != roomType + && data.isValid()) { + String message = roomType == RoomInfo.ROOMTYPE_CP ? "创建陪伴房,将关闭当前房间并解散房间内的用户" + : "创建普通房,将关闭当前房间并解散房间内的用户"; + getDialogManager().showOkCancelDialog( + message, + "确认", + "取消", + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { +// openRoom(roomType); + changeRoomState(data.getWorldId(), roomType); + } + }); + } else { +// openRoom(roomType); + changeRoomState(data.getWorldId(), roomType); + } + } + + @Override + public void onFail(int code, String error) { +// openRoom(roomType); + changeRoomState(0, roomType); + } + + }); + } + + private int mRoomType; + + private void changeRoomState(long worldId, int roomType) { + mRoomType = roomType; + if (worldId == 0) { + openRoom(roomType); + + } else { + getMvpPresenter().roomWorldModeClose(AuthModel.get().getCurrentUid()); + } + } + + private void openRoom(int roomType) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + if (roomInfo.getUid() == AuthModel.get().getCurrentUid() + && roomInfo.getType() == roomType) { + AVRoomActivity.start(mContext, roomInfo.getUid()); + } else { + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), getBaseActivity().getString(R.string.waiting_text)); + getMvpPresenter().requestExitRoom(roomType); + } + } else { + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), getBaseActivity().getString(R.string.waiting_text)); + getMvpPresenter().requestOpenRoom(roomType); + } + } + + @Override + public void requestOpenRoomResult(int openRoomFailType, Object... arg) { + getBaseActivity().getDialogManager().dismissDialog(); + if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_SUCCESS) { + RoomInfo roomInfo = (RoomInfo) arg[0]; + AVRoomActivity.start(getActivity(), roomInfo.getUid()); + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_TYPE_IN_ROOM) { + RoomInfo roomInfo = (RoomInfo) arg[0]; + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), "请稍后..."); + getMvpPresenter().requestExitRoom(roomInfo.getType()); + + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL) { + String error = (String) arg[0]; + getBaseActivity().toast(error); + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_ALREADY_OPENED_ROOM) { + RoomInfo roomInfo = (RoomInfo) arg[0]; + AVRoomActivity.start(getActivity(), roomInfo.getUid()); + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_PM_LIMIT_TIME) { + if (getActivity() != null && getActivity() instanceof MainActivity) { + if (arg != null && arg.length > 0 && arg[0] instanceof String) { + ((MainActivity) getActivity()).handleOpenRoomWhenPmLimit((String)arg[0]); + } + } + } + } + + @Override + public void showByMarketCheckingStatus(List tagListInfoList) { + if (MarketVerifyModel.get().isMarketChecking() && mHomeTitleInfos != null) { + Iterator iterator = mHomeTitleInfos.iterator(); + while (iterator.hasNext()) { + HomeTitleInfo next = iterator.next(); + // 没法准确判断「合拍男神女神」只能是把第一个可以下拉的 item 给删除掉 + if (!ListUtils.isListEmpty(next.getOpts())) { + iterator.remove(); + initHomeTitle = false; + break; + } + } + refreshData(); + } + } + + @Override + public void titleListSuccess(List tagListInfoList) { + + } + + @Override + public void titleListFail(String msg) { + + } + + private int mLastPosition = 0; + + @Override + public void onItemSelect(int position, TextView view) { + if (mHomeTitleInfos == null) { + return; + } + if (mFragments == null || mFragments.isEmpty()) { + return; + } + Fragment fragment = mFragments.get(position); + if (fragment == null) { + return; + } + //两次点击 如果是下拉式菜单就弹出 + if (position == mLastPosition) { + HomeTitleInfo homeTitleInfo = mHomeTitleInfos.get(position); + if (homeTitleInfo.hasSubTitle()) { + + showPopup(homeTitleInfo.getOpts(), view, position); + mLastPosition = position; + + return; + } + } + mBinding.viewPager.setCurrentItem(position); + mLastPosition = position; + + } + + private List convert(@NonNull List homeTitleInfos) { + List list = new ArrayList<>(homeTitleInfos.size()); + for (HomeTitleInfo homeTitleInfo : homeTitleInfos) { + list.add(homeTitleInfo.getName()); + } + return list; + } + + /** + * 显示下拉框 + * + * @param opts 下拉列表 + */ + private void showPopup(List opts, TextView targetView, int itemPosition) { + List labels = convert(opts); + + int currentPosition = 0; + if (targetView.getTag() == null) { + for (int i = 0; i < opts.size(); i++) { + HomeTitleInfo item = opts.get(i); + if (targetView.getText().toString().startsWith(item.getName())) { + currentPosition = i; + break; + } + } + } else { + currentPosition = (Integer) targetView.getTag(); + } + + View view = getLayoutInflater().inflate(R.layout.layout_home_pop_list, null); + PopupWindow popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); + popupWindow.setOutsideTouchable(true); + popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popupWindow.setFocusable(true); + ListView listView = popupWindow.getContentView().findViewById(R.id.listView); + + + int finalCurrentPosition = currentPosition; + listView.setAdapter(new ArrayAdapter(getContext(), R.layout.item_pop_list, labels) { + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + CheckBox tv = (CheckBox) super.getView(position, convertView, parent); + tv.setChecked(finalCurrentPosition == position); + tv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + targetView.setText(labels.get(position)); + targetView.setTag(position); + popupWindow.dismiss(); + refreshFragment(itemPosition, String.valueOf(opts.get(position).getId()), opts.get(position).getName()); + opts.get(position).saveDefault(); + } + }); + return tv; + } + }); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + setTabArrow(targetView, false); + backgroundAlpha(1.0f); + } + }); + popupWindow.showAsDropDown(targetView, ScreenUtil.dip2px(6), 0); + backgroundAlpha(0.6f); + setTabArrow(targetView, true); + } + + private void refreshFragment(int itemPosition, String type, String name) { + if (mFragments == null) { + return; + } + Fragment fragment = mFragments.get(itemPosition); + if (fragment == null) { + return; + } + if (fragment instanceof RecommendationFragment) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_GODDESS_OF_HARMONY, "首页-" + name); + ((RecommendationFragment) fragment).setTypeAndRefresh(type, name); + } + + } + + private void setTabArrow(TextView tv, boolean isUp) { + String text = tv.getText().toString(); + SpannableString ss = getArrowSpannableString(isUp, text); + tv.setText(ss); + LogUtil.i("test", tv.getText().toString()); + } + + /** + * 转换成带箭头的文本 + */ + @NotNull + private SpannableString getArrowSpannableString(boolean isUp, String text) { + if (!text.endsWith("[arrow]")) { + text = text + " [arrow]"; + } + SpannableString ss = new SpannableString(text); + ss.setSpan(new ImageSpan(getContext(), isUp ? R.drawable.ic_home_arrow_up_black : R.drawable.ic_home_arrow_down_black, DynamicDrawableSpan.ALIGN_BASELINE), text.length() - "[arrow]".length(), text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return ss; + } + + @Override + public void onGetFirstPageBannerFailed(String message) { + toast(message); + } + + @Override + public void roomWorldModeCloseSuccess() { + openRoom(mRoomType); + } + + @Override + public void roomWorldModeCloseFail(String error) { + toast(error); + } + + /** + * 获取首页信息成功 + * + * @param homeBannerInfo + */ + @Override + public void onGetFirstPageBannerSucceeded(HomeBannerInfo homeBannerInfo) { + if (homeBannerInfo == null || homeBannerInfo.isEmpty()) { + //数据为空的时候显示empty + mBinding.layoutEmpty.setVisibility(View.VISIBLE); + return; + } + mBinding.layoutEmpty.setVisibility(View.GONE); + initHomeBanner(homeBannerInfo.getFirstPageBannerVos()); + this.mHomeTitleInfos = homeBannerInfo.getAllVo(); + if (isUserLogin) { + initTitleTab(homeBannerInfo.getAllVo()); + } + + initQxTopBanner(homeBannerInfo.getTopBanners()); + + } + + /** + * 初始化顶部banner位 + * + * @param bannerInfos + */ + private void initHomeBanner(List bannerInfos) { + if (ListUtils.isListEmpty(bannerInfos)) { + mView.findViewById(R.id.home_banner_group).setVisibility(View.GONE); + return; + } + mView.findViewById(R.id.home_banner_group).setVisibility(View.VISIBLE); + // 遍历去掉 小世界 这个 item + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = bannerInfos.iterator(); + while (iterator.hasNext()) { + BannerInfo next = iterator.next(); + if (Objects.equals(next.getBannerName(), "轻寻-小世界")) { + iterator.remove(); + break; + } + } + } + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false) { + @Override + public boolean canScrollVertically() { + return false; + } + }); + + CommonAdapter + baseQuickAdapter = new CommonAdapter(R.layout.item_image_banner, bannerInfos) { + + @Override + protected void convert(BaseViewHolder holder, BannerInfo item) { + + } + + @Override + protected void convert(BaseViewHolder helper, BannerInfo item, int position) { + super.convert(helper, item, position); + if (null == item) { + return; + } + ImageView imageView = helper.getView(R.id.iv_icon); + ImageLoadUtils.loadImage(imageView.getContext(), item.getBannerPic(), imageView); + helper.getAdapterPosition(); + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) helper.itemView.getLayoutParams(); + if (position == 0) { + params.leftMargin = 0; + } else { + params.leftMargin = -UIUtil.dip2px(mContext, 28); + } + helper.itemView.setLayoutParams(params); + } + + }; + + baseQuickAdapter.setOnItemClickListener((ada, view, position) -> { + BannerInfo item = baseQuickAdapter.getItem(position); + if (null == item) { + return; + } + switch (item.getSkipType()) { + case SKIP_TYP_APP: + int routerType = JavaUtil.str2int(item.getSkipUri()); + if (routerType == 0) { + return; + } + switch (routerType) { + case RouterType.VOICE_BOTTLE_PAGE: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_SOUND_MATCHING, "首页-声音匹配"); + break; + case RouterType.GAME_MATCHING: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_SMALL_GAME, "首页-小游戏"); + break; + case RouterType.CHAT_PARTY: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_VOICE_PARTY, "首页-语音派对"); + break; + case RouterType.MINI_WORLD: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_MINI_WORLD, "首页-小世界"); + break; + default: + break; + } + break; + case SKIP_TYP_H5: + if (item.getBannerName().equals("测一测")) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_TEST, "首页-测一测"); + } + break; + + case SKIP_TYPE_ROUTER: + int routerRouterType = JavaUtil.str2int(item.getRouterType()); + switch (routerRouterType) { + case RouterType.MINI_WORLD_TEST: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_TEST, "首页-测一测"); + break; + } + break; + default: + break; + } + CommonJumpHelper.bannerJump(mContext, item); + }); + mBinding.recyclerView.setAdapter(baseQuickAdapter); + + } + + + /** + * 用户信息更新 + * + * @param event + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void loadLoginUserInfoEvent(LoadLoginUserInfoEvent event) { + refreshData(); + } + + private void refreshData() { + isUserLogin = true; + if (!initHomeTitle && mHomeTitleInfos != null) { + initTitleTab(mHomeTitleInfos); + } + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + //登录的时候显示位置,更好的 + Log.i("startLocation", "refreshData"); + startLocation(); + + // 超管不展示开房按钮 + mBinding.setOpenVisible(!(userInfo != null && userInfo.getPlatformRole() == 1)); + } + + public List getHomeBanner(int num) { + int count = mBinding.recyclerView.getChildCount(); + if (count == 0) { + return null; + } + if (num < count) { + count = num; + } + List list = new ArrayList<>(); + for (int i = 0; i < count; i++) { + View view = mBinding.recyclerView.getChildAt(i); + if (view != null) { + list.add(view); + } + } + return list; + + } + + /** + * 判断是否要显示首页引导 + */ + private void initGuide() { + mView.postDelayed(new Runnable() { + @Override + public void run() { + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_HOME)) { + + Activity activity = getActivity(); + if (activity == null) { + return; + } + View rootView = activity.findViewById(android.R.id.content); + if (!(rootView instanceof FrameLayout)) { + return; + } + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_HOME); + FrameLayout contentView = (FrameLayout) rootView; + View view = getLayoutInflater().inflate(R.layout.layout_home_guide, contentView, false); + View skipView = view.findViewById(R.id.tv_skip); + View logoIconView = view.findViewById(R.id.iv_logo_icon); + ImageView bgView = view.findViewById(R.id.iv_bg); + GlideApp.with(activity) + .load(R.drawable.ic_guide_home_1) + .apply(RequestOptions.bitmapTransform(new BitmapTransformation() { + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + + } + + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + Bitmap bitmap; + bitmap = Bitmap.createBitmap(toTransform, 0, 0, outWidth, outHeight); + return bitmap; + } + + })) + .into(bgView); + contentView.addView(view, -1, -1); + skipView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + contentView.removeView(view); + } + }); + + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (v.getTag() == null) { + GlideApp.with(activity) + .load(R.drawable.ic_guide_home_2) + .apply(RequestOptions.bitmapTransform(new BitmapTransformation() { + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + + } + + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + Bitmap bitmap; + bitmap = Bitmap.createBitmap(toTransform, 0, 0, outWidth, outHeight); + return bitmap; + } + + })) + .into(bgView); + + skipView.setVisibility(View.GONE); + logoIconView.setVisibility(View.VISIBLE); + v.setTag(1); + + } else { + contentView.removeView(view); + } + } + }); + } + } + }, 2000); + + } + + private void backgroundAlpha(float f) { + Activity activity = getActivity(); + if (activity == null) { + return; + } + WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); + lp.alpha = f; + + activity.getWindow().setAttributes(lp); + + } + + + public void initQxTopBanner(List bannerList) { + + //审核中状态,去掉跳转房间banner + if (MarketVerifyModel.get().isMarketChecking()) { + Iterator iterator = bannerList.iterator(); + while (iterator.hasNext()) { + BannerInfo bannerInfo = iterator.next(); + if (bannerInfo.getSkipType() == 2) { + iterator.remove(); + } + } + } + if (ListUtils.isListEmpty(bannerList)) { + mBinding.rollView.setVisibility(View.GONE); + return; + } + mBinding.rollView.setVisibility(View.VISIBLE); + ViewGroup.LayoutParams layoutParams = mBinding.rollView.getLayoutParams(); + int bannerWidth = UIUtil.getScreenWidth(mContext) - UIUtil.dip2px(mContext, 40); + layoutParams.width = bannerWidth; + layoutParams.height = bannerWidth * 116 / 335; + mBinding.rollView.setLayoutParams(layoutParams); + + mBinding.rollView.setHintView(new ColorPointHintView(mContext, Color.WHITE, mContext.getResources().getColor(R.color.color_66FFFFFF)) { + @Override + public Drawable makeFocusDrawable() { + GradientDrawable dotFocus = new GradientDrawable(); + dotFocus.setColor(Color.WHITE); + dotFocus.setCornerRadius(Util.dip2px(getContext(), 2)); + dotFocus.setSize(Util.dip2px(getContext(), 9), Util.dip2px(getContext(), 4)); + return dotFocus; + } + + @Override + public Drawable makeNormalDrawable() { + GradientDrawable dotNormal = new GradientDrawable(); + dotNormal.setColor(mContext.getResources().getColor(R.color.color_66FFFFFF)); + dotNormal.setCornerRadius(Util.dip2px(getContext(), 2)); + dotNormal.setSize(Util.dip2px(getContext(), 4), Util.dip2px(getContext(), 4)); + return dotNormal; + } + }); + + BannerAdapter bannerAdapter = new BannerAdapter(bannerList, mContext); + bannerAdapter.setRoundingRadius(ScreenUtil.dip2px(12)); + mBinding.rollView.setAdapter(bannerAdapter); + mBinding.rollView.setPlayDelay(3000); + //设置透明度 + mBinding.rollView.setAnimationDurtion(500); + mBinding.rollView.setVisibility(View.VISIBLE); + bannerAdapter.notifyDataSetChanged(); + + } + + @SuppressLint("CheckResult") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLocationUploadEvent(LocationUploadEvent event) { + Log.i("startLocation", "onLocationUploadEvent"); + startLocation(); + } + + @SuppressLint("CheckResult") + private void startLocation() { + Log.i("startLocation", "startLocation"); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + //登录的时候显示位置,更好的 + boolean showLocation = true; + if (userInfo != null && userInfo.getUserExpand() != null) { + showLocation = userInfo.getUserExpand().isShowLocation(); + } + + if (!showLocation) { + return; + } + + final boolean tempShowLocation = showLocation; + + Observable.create((ObservableOnSubscribe) e -> { + //等待10s + int count = 0; + while (!isResumed() && count < 50) { + Thread.sleep(200); + count ++; + } + if (isResumed()) { + e.onNext(count); + return; + } + e.onError(new Throwable("wait too long")); + + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .flatMap((Function>) aBoolean + -> checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION)) + + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .doOnNext(aBoolean -> { + Log.i("startLocation", "result:" + aBoolean); + LocationManager.saveUploadTime(); + if (aBoolean) { + if (mLocationClient != null) { + mLocationClient.startLocation(); + } + } else { + toast("给予位置权限更好的展示您的位置信息"); + Log.i("startLocation", "tempShowLocation:" + tempShowLocation); + + if (tempShowLocation) { + SettingsModel.get().showLocation(AuthModel.get().getCurrentUid(), false) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()) + .subscribe(); + + } + } + }) + .doOnError(throwable -> { + LogUtil.print("location throwable"); + }) + .subscribe(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/HomeOtherTabFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/HomeOtherTabFragment.java new file mode 100644 index 000000000..480e6eabc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/HomeOtherTabFragment.java @@ -0,0 +1,319 @@ +package com.yizhuan.erban.home.fragment; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.home.adapter.HomeFragmentAdapter; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; + +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Function; + +/** + * 语音排队 没用下拉式的tab + */ +public class HomeOtherTabFragment extends BaseFragment { + + + public static final int ROWS = 2; + + private static final int PAGE_SIZE = 20; + + + private static final String PARAM_TAB_ID = "tabId"; + private String tabId; + private RecyclerView recyclerView; + private SmartRefreshLayout smartRefreshLayout; + private int pageIndex = 1; + private HomeFragmentAdapter mHomeHotAdapter; + private final Object lock = new Object(); + /** + * 是否包含了banner + */ + private boolean isContainsBanner = false; + /** + * 广告 + */ + private HomeItem> bannerHomeItem; + + /** + * 用于显示的数据 + */ + private List totalHomeItemList = new ArrayList<>(); + + public static HomeOtherTabFragment newInstance(int tabId) { + + Bundle args = new Bundle(); + args.putString(PARAM_TAB_ID, String.valueOf(tabId)); + HomeOtherTabFragment fragment = new HomeOtherTabFragment(); + fragment.setArguments(args); + return fragment; + } + + public HomeOtherTabFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + tabId = getArguments().getString(PARAM_TAB_ID); + } + } + + + @Override + public int getRootLayoutId() { + return R.layout.fragment_home_other_tab; + } + + @Override + public void onFindViews() { + super.onFindViews(); + recyclerView = mView.findViewById(R.id.recycler_view); + smartRefreshLayout = mView.findViewById(R.id.smart_refresh_layout); + initRefreshView(); + initRecyclerView(); + + } + + private void initRefreshView() { + + smartRefreshLayout.setEnableRefresh(true); + smartRefreshLayout.setOnRefreshListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshlayout) { + loadMoreData(); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + refreshData(); + } + }); + smartRefreshLayout.setEnableLoadmore(false); + + } + + /** + * 刷新数据 + */ + public void refresh() { + smartRefreshLayout.autoRefresh(); + } + + /** + * 刷新数据 + */ + private void refreshData() { + pageIndex = 1; + getData(true); + } + + private void loadMoreData() { + getData(false); + } + + /** + * 请求数据 + */ + @SuppressLint("CheckResult") + private void getData(boolean isRefresh) { + HomeModel.get() + .getTabRoomList(pageIndex, PAGE_SIZE, tabId) + .map(new Function, List>() { + @Override + public List apply(List homeRooms) throws Exception { + + if (ListUtils.isListEmpty(homeRooms)) { + return new ArrayList<>(); + } + List list = new ArrayList<>(homeRooms.size()); + for (HomeRoom homeRoom : homeRooms) { + HomeItem homeItem = new HomeItem(HomeItem.TYPE_BLOCK_SINGLE, homeRoom); + list.add(homeItem); + } + return list; + } + }) + .compose(RxHelper.handleSchedulers()) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List homeItems, Throwable throwable) throws Exception { + if (throwable == null) { + if (ListUtils.isListEmpty(homeItems)) { + mHomeHotAdapter.setEnableLoadMore(false); + if (isRefresh) { + totalHomeItemList.clear(); + mHomeHotAdapter.notifyDataSetChanged(); + } + } else { + pageIndex++; + //添加虚位以待 + int count = homeItems.size() % ROWS; + if (count != 0) { + count = ROWS - count; + } + for (int i = 0; i < count; i++) { + homeItems.add(new HomeItem(HomeItem.TYPE_DOUBLE_SQUARE_EMPTY)); + } + synchronized (lock) { + if (isRefresh) { + totalHomeItemList.clear(); + + totalHomeItemList.addAll(homeItems); + isContainsBanner = false; + recombinationData(); + } else { + totalHomeItemList.addAll(homeItems); + mHomeHotAdapter.notifyDataSetChanged(); + } + mHomeHotAdapter.setEnableLoadMore(true); + } + } + + } else { + if (!(throwable instanceof CancellationException)) { + toast("请求失败,请稍后再试!!" + throwable.getMessage()); + } + } + if (isRefresh) { + smartRefreshLayout.finishRefresh(); + mHomeHotAdapter.loadMoreComplete(); + } else { + mHomeHotAdapter.loadMoreComplete(); + } + + } + }); + } + + private void initRecyclerView() { + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setItemAnimator(null); + mHomeHotAdapter = new HomeFragmentAdapter(getContext(), totalHomeItemList); + mHomeHotAdapter.setEnableLoadMore(false); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), ROWS); + mHomeHotAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + HomeItem homeItem = mHomeHotAdapter.getItem(position); + if (homeItem != null && (homeItem.getItemType() == HomeItem.TYPE_BLOCK_SINGLE || homeItem.getItemType() == HomeItem.TYPE_DOUBLE_SQUARE_EMPTY)) { + return 1; + } + return gridLayoutManager.getSpanCount(); + } + }); + mHomeHotAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + loadMoreData(); + } + }, recyclerView); + mHomeHotAdapter.setEnableLoadMore(false); + recyclerView.setLayoutManager(gridLayoutManager); + recyclerView.setAdapter(mHomeHotAdapter); + + View emptyView = getLayoutInflater().inflate(R.layout.layout_home_empty_no_header, null); + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + emptyView.setLayoutParams(lp); + mHomeHotAdapter.setEmptyView(emptyView); + + } + + @Override + public void initiate() { + refresh(); + initBanner(); + } + + private void initBanner() { + HomeModel.get() + .getTabBanner(tabId) + .map(new Function, HomeItem>>() { + @Override + public HomeItem> apply(ArrayList bannerInfos) throws Exception { + if (ListUtils.isListEmpty(bannerInfos)) { + return null; + } + HomeItem homeItem = new HomeItem(HomeItem.TYPE_BANNER_NO_TOP_BG, bannerInfos); + return homeItem; + } + }) + .compose(RxHelper.handleSchedulers()) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer>, Throwable>() { + @Override + public void accept(HomeItem> homeItem, Throwable throwable) throws Exception { + if (throwable == null) { + bannerHomeItem = homeItem; + recombinationData(); + } + } + }); + } + + private void recombinationData() { + synchronized (lock) { + List homeItems = totalHomeItemList; + if (bannerHomeItem != null && !isContainsBanner) { + + totalHomeItemList.add(homeItems.size() > 4 ? 4 : homeItems.size(), bannerHomeItem); + isContainsBanner = true; + } + mHomeHotAdapter.notifyDataSetChanged(); + } + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + if (view == null) { + MLog.error(this, "xuwakao, showNoData view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.layout_home_empty_no_header, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/HottestKTVRoomFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/HottestKTVRoomFragment.java new file mode 100644 index 000000000..5603f77ef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/HottestKTVRoomFragment.java @@ -0,0 +1,146 @@ +package com.yizhuan.erban.home.fragment; + +import android.graphics.Color; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.home.adapter.KTVTypeRoomAdapter; +import com.yizhuan.erban.home.presenter.HottestKTVRoomFragmentPresenter; +import com.yizhuan.erban.home.view.IHottestKTVRoomFragmentView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; +import com.yizhuan.xchat_android_core.home.bean.KTVRoomInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +@CreatePresenter(HottestKTVRoomFragmentPresenter.class) +public class HottestKTVRoomFragment extends BaseMvpFragment + implements IHottestKTVRoomFragmentView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + + private SwipeRefreshLayout srlRefreshContainer; + private RecyclerView rvList; + + private KTVTypeRoomAdapter adapter; + + public static Fragment newInstance() { + return new HottestKTVRoomFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_hottest_ktv; + } + + @Override + public void onFindViews() { + srlRefreshContainer = (SwipeRefreshLayout) getView().findViewById(R.id.srl_refresh_container); + rvList = (RecyclerView) getView().findViewById(R.id.rv_list); + rvList.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); + rvList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(getContext(), 10), false)); + adapter = new KTVTypeRoomAdapter(getContext(), null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, rvList); + rvList.setAdapter(adapter); + } + + @Override + public void onSetListener() { + srlRefreshContainer.setOnRefreshListener(this); + } + + @Override + public void initiate() { + } + + @Override + public void onResume() { + super.onResume(); + onRefresh(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + onRefresh(); + } + + @Override + public void onRefresh() { + getMvpPresenter().refreshData() + .observeOn(AndroidSchedulers.mainThread()) + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + srlRefreshContainer.setRefreshing(false); + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List roomList) { + if (ListUtils.isListEmpty(roomList)) { + showNoData(); + return; + } + hideStatus(); + adapter.setNewData(roomList); + } + + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List strings) { + if (!ListUtils.isListEmpty(strings)) { + adapter.addData(strings); + adapter.loadMoreComplete(); + } else { + adapter.loadMoreEnd(true); + } + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/KTVFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/KTVFragment.java new file mode 100644 index 000000000..9af944580 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/KTVFragment.java @@ -0,0 +1,93 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.home.adapter.CommonMagicIndicatorAdapter; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.home.presenter.KTVFragmentPresenter; +import com.yizhuan.erban.home.view.IKTVFragmentView; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +@CreatePresenter(KTVFragmentPresenter.class) +public class KTVFragment extends BaseMvpFragment + implements IKTVFragmentView, CommonMagicIndicatorAdapter.OnItemSelectListener { + + private MagicIndicator miIndicator; + private ViewPager vpKtv; + + + public static Fragment newInstance() { + return new KTVFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_ktv; + } + + @Override + public void onFindViews() { + miIndicator = (MagicIndicator) getView().findViewById(R.id.mi_indicator); + vpKtv = (ViewPager) getView().findViewById(R.id.vp_ktv); + + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + List tabInfoList = new ArrayList<>(); + tabInfoList.add(new TabInfo(1, getString(R.string.home_ktv_newest))); + tabInfoList.add(new TabInfo(2, getString(R.string.home_ktv_hottest))); + + + List mTabs = new ArrayList<>(); + mTabs.add(NewestKTVRoomFragment.newInstance()); + mTabs.add(HottestKTVRoomFragment.newInstance()); + + + CommonMagicIndicatorAdapter mMsgIndicatorAdapter = new CommonMagicIndicatorAdapter(mContext, tabInfoList, 5); + mMsgIndicatorAdapter.setOnItemSelectListener(this); + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + commonNavigator.setAdjustMode(true); + commonNavigator.setAdapter(mMsgIndicatorAdapter); + miIndicator.setNavigator(commonNavigator); + // must after setNavigator + LinearLayout titleContainer = commonNavigator.getTitleContainer(); + titleContainer.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + + vpKtv.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), mTabs)); + ViewPagerHelper.bind(miIndicator, vpKtv); + + } + + @Override + public void onResume() { + super.onResume(); + + } + + @Override + public void onItemSelect(int position) { + vpKtv.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/MainFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/MainFragment.java new file mode 100644 index 000000000..90406722b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/MainFragment.java @@ -0,0 +1,419 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewPager; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.mcxiaoke.packer.helper.PackerNg; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.home.adapter.TopMagicIndicatorAdapter; +import com.yizhuan.erban.home.dialog.CreateRoomDialog; +import com.yizhuan.erban.home.presenter.MainFragmentPresenter; +import com.yizhuan.erban.home.view.IMainFragmentTabBg; +import com.yizhuan.erban.home.view.IMainFragmentView; +import com.yizhuan.erban.ui.search.SearchActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.erban.ui.widget.magicindicator.ext.MainCommonNavigatorAdapter; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.certification.CertificationModel; +import com.yizhuan.xchat_android_core.family.bean.HomeBannerInfo; +import com.yizhuan.xchat_android_core.home.bean.TagListInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import java.util.ArrayList; +import java.util.List; + +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_FORCE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_GUIDE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_NONE; + +/** + *

首页 fragment

+ * + * @author Administrator + * @date 2017/11/14 + * 修改 jack + */ + +@CreatePresenter(MainFragmentPresenter.class) +public class MainFragment extends BaseMvpFragment + implements IMainFragmentView, View.OnClickListener, TopMagicIndicatorAdapter.OnItemSelectListener, + IMainFragmentTabBg { + + + public static final String TAG = MainFragment.class.getSimpleName(); + + + private MagicIndicator miHomeIndicator; + private ImageView ivSearchRoom; + private ImageView ivOpenRoom; + private ViewPager mainViewpager; + + private LinearLayout llHomeTitle; + private boolean mIsBannerTop = true; + + @Override + public int getRootLayoutId() { + return R.layout.fragment_main; + } + + @Override + public void onFindViews() { + miHomeIndicator = mView.findViewById(R.id.mi_home_indicator); + ivSearchRoom = (ImageView) mView.findViewById(R.id.iv_search_room); + ivOpenRoom = (ImageView) mView.findViewById(R.id.iv_open_room); + mainViewpager = (ViewPager) mView.findViewById(R.id.main_viewpager); + + llHomeTitle = mView.findViewById(R.id.ll_home_title); + + } + @Override + public void onSetListener() { + ivSearchRoom.setOnClickListener(this); + ivOpenRoom.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == ivSearchRoom.getId()) { + SearchActivity.start(getActivity()); +// startActivity(new Intent(getActivity(), TestActivity.class)); + }else if (id == ivOpenRoom.getId()){ + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null && !userInfo.isCertified()) { + switch (CertificationModel.get().getCertificationType()) { + default: + case CER_TYPE_NONE: + // do nothing + openCreateRoomTypeDialog(); + break; + + case CER_TYPE_FORCE: + getDialogManager().showTipsDialog(getCertificationTips(), + getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(getContext(), + UriProvider.getTutuRealNamePage()); + } + }); + break; + + case CER_TYPE_GUIDE: + getDialogManager().showTipsDialog(getCertificationTips(), + getString(R.string.go_to_certification), + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + openCreateRoomTypeDialog(); + } + + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(getContext(), + UriProvider.getTutuRealNamePage()); + } + }); + break; + } + } else { + openCreateRoomTypeDialog(); + } + } + } + + @NonNull + private SpannableStringBuilder getCertificationTips() { + String tips = getString(R.string.tips_need_to_certification); + SpannableStringBuilder builder = new SpannableStringBuilder(tips); + builder.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), + tips.length() - 4, tips.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + return builder; + } + + private void openCreateRoomTypeDialog() { + new CreateRoomDialog(getActivity(), new CreateRoomDialog.OpenRoomListener() { + @Override + public void onNormalRoom() { + getRoomInfo(RoomInfo.ROOMTYPE_HOME_PARTY); + } + + @Override + public void onCpRoom() { + getRoomInfo(RoomInfo.ROOMTYPE_CP); + } + }).openDialog(); + } + + private void getRoomInfo(int roomType) { + AvRoomModel.get().requestRoomInfoFromService(String.valueOf(AuthModel.get().getCurrentUid()), + new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + if (data.getType() != 0 + && data.getType() != roomType + && data.isValid()) { + String message = roomType == RoomInfo.ROOMTYPE_CP ? "创建陪伴房,将关闭当前房间并解散房间内的用户" + : "创建普通房,将关闭当前房间并解散房间内的用户"; + getDialogManager().showOkCancelDialog( + message, + "确认", + "取消", + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { +// openRoom(roomType); + changeRoomState(data.getWorldId(), roomType); + } + }); + } else { +// openRoom(roomType); + changeRoomState(data.getWorldId(), roomType); + } + } + + @Override + public void onFail(int code, String error) { +// openRoom(roomType); + changeRoomState(0, roomType); + } + }); + } + + private int mRoomType; + private void changeRoomState(long worldId, int roomType) { + mRoomType = roomType; + if (worldId == 0) { + openRoom(roomType); + + } else { + getMvpPresenter().roomWorldModeClose(AuthModel.get().getCurrentUid()); + } + } + private void openRoom(int roomType) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + if (roomInfo.getUid() == AuthModel.get().getCurrentUid() + && roomInfo.getType() == roomType) { + AVRoomActivity.start(mContext, roomInfo.getUid()); + } else { + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), getBaseActivity().getString(R.string.waiting_text)); + getMvpPresenter().requestExitRoom(roomType); + } + } else { + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), getBaseActivity().getString(R.string.waiting_text)); + getMvpPresenter().requestOpenRoom(roomType); + } + } + + @Override + public void initiate() { + //初始化延迟到获取到审核结果后 + if (!"baidutg".equals(PackerNg.getChannel(getActivity()))) { +// showByMarketCheckingStatus(); + getMvpPresenter().tagList(); + } + } + + + @Override + public void requestOpenRoomResult(int openRoomFailType, Object... arg) { + getBaseActivity().getDialogManager().dismissDialog(); + if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_SUCCESS){ + RoomInfo roomInfo = (RoomInfo) arg[0]; + AVRoomActivity.start(getActivity(), roomInfo.getUid()); + + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_TYPE_IN_ROOM){ + RoomInfo roomInfo = (RoomInfo) arg[0]; + getBaseActivity().getDialogManager().showProgressDialog(getActivity(), "请稍后..."); + getMvpPresenter().requestExitRoom(roomInfo.getType()); + + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL){ + String error = (String) arg[0]; + getBaseActivity().toast(error); + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_ALREADY_OPENED_ROOM){ + RoomInfo roomInfo = (RoomInfo) arg[0]; + AVRoomActivity.start(getActivity(), roomInfo.getUid()); + } else if (openRoomFailType == MainFragmentPresenter.OPEN_ROOM_FAIL_PM_LIMIT_TIME) { + + } + } + + private void initTabIndicator(List mTabInfoList) { + CommonNavigator commonNavigator = new CommonNavigator(mContext, UIUtil.dip2px(mContext, 20)); + MainCommonNavigatorAdapter commonNavigatorAdapter = new MainCommonNavigatorAdapter(mContext, mTabInfoList); + commonNavigatorAdapter.setOnTabClickListener(index -> mainViewpager.setCurrentItem(index)); + commonNavigator.setAdapter(commonNavigatorAdapter); + miHomeIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(miHomeIndicator, mainViewpager); + + if (showGuide) + showGuide(); +// mBinding.mainViewpager.setOffscreenPageLimit(7); + } + + /** + * 审核包,隐藏,重新刷新 + */ + @Override + public void showByMarketCheckingStatus(List tagListInfoList){ + //审核包隐藏搜索 + if (MarketVerifyModel.get().isMarketChecking()){ + ivSearchRoom.setVisibility(View.INVISIBLE); + ivSearchRoom.setEnabled(false); + + }else { + ivSearchRoom.setVisibility(View.VISIBLE); + ivSearchRoom.setEnabled(true); + } + + List mTabInfoList = new ArrayList<>(); + List fragmentList = new ArrayList<>(); + + + mTabInfoList.add(getResources().getString(R.string.main_tab_recommend)); + fragmentList.add(RecommendFragment.newInstance(this)); + for (TagListInfo tagListInfo : tagListInfoList) { + mTabInfoList.add(tagListInfo.getTitleName()); + fragmentList.add(RoomTabFragment.newInstance(tagListInfo.getTitleId(), this)); + } + mainViewpager.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), fragmentList)); + initTabIndicator(mTabInfoList); + } + + @Override + public void titleListSuccess(List tagListInfoList) { + showByMarketCheckingStatus(tagListInfoList); + + } + + @Override + public void titleListFail(String msg) { + showByMarketCheckingStatus(new ArrayList<>()); + } + + @Override + public void onItemSelect(int position) { + mainViewpager.setCurrentItem(position); + } + + public void goToKTVTab() { + mainViewpager.setCurrentItem(3, true); + } + + @Override + public void isBannerTop(boolean isBannerTop) { + if (mIsBannerTop != isBannerTop) { + +// if (isBannerTop) { +// +// if (llHomeTitle != null) +// llHomeTitle.setBackgroundResource(R.drawable.game_img_bg); +// +// } else { +// +// if (llHomeTitle != null) +// llHomeTitle.setBackgroundResource(R.drawable.game_img_bg2); +// } +// llHomeTitle.setBackgroundResource(R.drawable.game_img_bg2); + + mIsBannerTop = isBannerTop; + + } + } + + // 有可能出现miHomeIndicator未初始就调用handleGuide的情况 + private boolean showGuide = false; + /** + * 处理引导 + */ + public void handleGuide() { + if (miHomeIndicator != null) { + showGuide(); + } else { + showGuide = true; + } + } + + private void showGuide() { +// if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_TAB)) { +// miHomeIndicator.post(() -> { +// if (getActivity() != null && getActivity() instanceof MainActivity) { +// if (!((MainActivity) getActivity()).isShowMainTab()) { +// return; +// } +// TuTuGuideHelper helper = new TuTuGuideHelper(mContext); +// helper.createHiGuide(() -> helper.createMainTabOverLayer(miHomeIndicator)); +// TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_TAB); +// } +// }); +// } + + showGuide = false; +// if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_TAB)) { +// miHomeIndicator.post(() -> { +// if (getActivity() != null && getActivity() instanceof MainActivity) { +// if (!((MainActivity) getActivity()).isShowMainTab()) { +// return; +// } +// TuTuGuideHelper helper = new TuTuGuideHelper(mContext); +// helper.createHiGuide(() -> helper.createMainTabOverLayer(miHomeIndicator)); +// TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_TAB); +// } +// }); +// } + } + + @Override + public void onGetFirstPageBannerSucceeded(HomeBannerInfo homeBannerInfo) { + + } + + @Override + public void onGetFirstPageBannerFailed(String message) { + + } + + @Override + public void roomWorldModeCloseSuccess() { + openRoom(mRoomType); + } + + @Override + public void roomWorldModeCloseFail(String error) { + toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/MeFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/MeFragment.java new file mode 100644 index 000000000..3a007e4b3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/MeFragment.java @@ -0,0 +1,436 @@ +package com.yizhuan.erban.home.fragment; + +import android.Manifest; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.ImageView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.target.ViewTarget; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.recommendcard.MyRecommendCardActivity; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.FragmentMeBinding; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.module_hall.HallDataManager; +import com.yizhuan.erban.module_hall.hall.activity.ModuleHallActivity; +import com.yizhuan.erban.radish.activity.RadishRecordActivity; +import com.yizhuan.erban.ui.patriarch.PatriarchModeActivity; +import com.yizhuan.erban.ui.relation.AttentionListActivity; +import com.yizhuan.erban.ui.relation.FansListActivity; +import com.yizhuan.erban.ui.wallet.WalletGoldActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.ObservableScrollView; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.erban.utils.BlurTransformation; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.customer_server.CustomerServerModel; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RelationShipEvent; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.market_verify.event.MarketVerifyUpdateEvent; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleProtocol; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_core.utils.StarUtils; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.Date; +import java.util.Locale; + +import io.reactivex.functions.BiConsumer; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_HADEXPIRE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_OPENNOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE; + +/** + * @description: 我的 界面 + * @author: hewenhao + * @date: 2018/9/4 16:53 + */ +public class MeFragment extends BaseFragment implements View.OnClickListener { + + public static final String TAG = "MeFragment"; + + private UserInfo mUserInfo; + private NobleInfo mNobleInfo; + private FragmentMeBinding mBinding; + + private ObservableScrollView scrollView; + + @Override + public int getRootLayoutId() { + return R.layout.fragment_me; + } + + @Override + public void onSetListener() { + mBinding = DataBindingUtil.bind(mView); + if (mBinding != null) { + mBinding.setClick(this); + } + if (mBinding != null) { + scrollView = mBinding.scrollView; + scrollView.setScrollViewListener((view, scrollX, scrollY, oldScrollX, oldScrollY) -> { + if (scrollY == 0) {// 目前的(滑动后)的Y轴坐标 + mBinding.tvCenterTitle.setAlpha(0); + mBinding.viewToolbarBg.setAlpha(0); + } else { + if (scrollY > 180) { + mBinding.tvCenterTitle.setAlpha(1); + mBinding.viewToolbarBg.setAlpha(1); + } else { + float alpha = scrollY / 180f; + mBinding.tvCenterTitle.setAlpha(alpha); + mBinding.viewToolbarBg.setAlpha(alpha); + } + } + }); + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void initiate() { + RxBusHelper.doOnMainThread(NobleProtocol.class, mCompositeDisposable, nobleProtocol -> { + int second = nobleProtocol.getSecond(); + if (second == CUSTOM_MESS_SUB_OPENNOBLE || second == CUSTOM_MESS_SUB_RENEWNOBLE) { + requestUpdateUserInfo(); + } else if (second == CUSTOM_MESS_SUB_HADEXPIRE) { + mBinding.ivUserNobleLevel.setVisibility(View.GONE); + mBinding.tvNobleRemainTime.setVisibility(View.GONE); + mBinding.ivAvatarHeadWear.setVisibility(View.GONE); + } + }); + + mCompositeDisposable.add( + IMNetEaseManager.get().getRelationShipEventObservable().subscribe(e -> onGetRelationShipEvent(e)) + ); + + onMarketVerifyUpdateEvent(null); + + //模厅 + HallDataManager.get().registerHallExist(this, hallExist -> { + if (hallExist != null && hallExist) { + mBinding.llModuleHall.setVisibility(View.VISIBLE); + return; + } + mBinding.llModuleHall.setVisibility(View.GONE); + }); + HallDataManager.get().registerName(this, name -> mBinding.tvModuleHall.setText(name)); + + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_ME_TAB)) { + mBinding.meItemRadish.post(() -> { + if (getActivity() != null && getActivity() instanceof MainActivity) { + if (!((MainActivity) getActivity()).isShowMeTab()) { + return; + } + TuTuGuideHelper helper = new TuTuGuideHelper(mContext); + helper.createHiGuide(() -> helper.createMeTabOverLayer(mBinding.meItemRadish)); + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_ME_TAB); + } + }); + } + + } + + private void onGetRelationShipEvent(RelationShipEvent event) { + if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) { + requestUpdateUserInfo(); + } + } + + @Override + public void onResume() { + super.onResume(); + initUserDate(); + } + + private void initUserDate() { + mUserInfo = UserModel.get().getCacheLoginUserInfo(); + setUserData(); + } + + private void setUserData() { + if (mUserInfo != null) { + mBinding.setUserInfo(mUserInfo); + + mBinding.tvUserId.setText(String.format(Locale.getDefault(), + getString(R.string.text_user_id), String.valueOf(mUserInfo.getErbanNo()))); + + int nobleExpire = mUserInfo.getRemainDay(); + if (nobleExpire > -1) { + mBinding.tvNobleRemainTime.setVisibility(View.VISIBLE); + } else { + mBinding.tvNobleRemainTime.setVisibility(View.GONE); + } + mBinding.tvNobleRemainTime.setText(getString(R.string.noble_remain_time, nobleExpire)); + + NobleInfo nobleInfo = mUserInfo.getNobleInfo(); + HeadWearInfo headWearInfo = mUserInfo.getUserHeadwear(); + if (headWearInfo != null) { + mBinding.ivAvatarHeadWear.setImageDrawable(null); + if (nobleInfo != null) { + mBinding.ivUserNobleLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(NobleUtil.getBadgeByLevel(nobleInfo.getLevel()), mBinding.ivUserNobleLevel); + } else { + mBinding.ivUserNobleLevel.setVisibility(View.GONE); + mBinding.tvNobleRemainTime.setVisibility(View.GONE); + } + NobleUtil.loadHeadWear(headWearInfo.getPic(), mBinding.ivAvatarHeadWear); + } else if (nobleInfo != null) { + mBinding.ivUserNobleLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(NobleUtil.getBadgeByLevel(nobleInfo.getLevel()), mBinding.ivUserNobleLevel); + mBinding.ivAvatarHeadWear.setImageDrawable(null); + NobleUtil.loadResource(nobleInfo.getHeadWear(), mBinding.ivAvatarHeadWear); + } else { + mBinding.ivAvatarHeadWear.setImageDrawable(null); + mBinding.ivUserNobleLevel.setVisibility(View.GONE); + mBinding.tvNobleRemainTime.setVisibility(View.GONE); + } + + String star = StarUtils.getConstellation(new Date(mUserInfo.getBirth())); + mBinding.tvConstellation.setText(star); + + // 头像遮罩 + GlideApp.with(mContext) + .load(mUserInfo.getAvatar()) + .dontAnimate() + .centerInside() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, + Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, + Target target, DataSource dataSource, boolean b) { + drawable.setColorFilter(mContext.getResources().getColor(R.color.black_transparent_20), PorterDuff.Mode.DARKEN); + ViewTarget viewTarget = (ViewTarget) target; + viewTarget.getView().setImageDrawable(drawable); + return true; + } + }) + // “23”:设置模糊度(在0.0到25.0之间),默认”25";"4":图片缩放比例,默认“1”。 + .transforms(new BlurTransformation(mContext, 25, 1)) + .into(mBinding.ivUserAvatarShadow); + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + AuthModel.get().setThirdUserInfo(null); + mUserInfo = UserModel.get().getCacheLoginUserInfo(); + setUserData(); + } + + private void requestUpdateUserInfo() { + if (mUserInfo != null) { + UserModel.get().updateCurrentUserInfo().subscribe(); + } + } + + + @Override + public void onClick(View v) { + int id = v.getId(); + switch (id) { + case R.id.me_item_my_family: + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.MY_FAMILY_CLICK, "我的家族入口", null); + + String familyId = null; + if (null != FamilyModel.Instance().getMyFamily()) { + familyId = FamilyModel.Instance().getMyFamily().getFamilyId(); + } + FamilyHomeActivity.start(mContext, familyId); + break; + case R.id.iv_user_head: + case R.id.rl_user_info: + if (mUserInfo != null) { + UIHelper.showUserInfoAct(mContext, mUserInfo.getUid()); + } + break; + + case R.id.iv_edit: + if (mUserInfo != null) { + UIHelper.showUserInfoModifyAct(mContext, mUserInfo.getUid()); + } + break; + + case R.id.tv_user_attentions: + case R.id.tv_user_attention_text: + startActivity(new Intent(mContext, AttentionListActivity.class)); + break; + + case R.id.tv_user_fans: + + case R.id.tv_user_fan_text: + startActivity(new Intent(mContext, FansListActivity.class)); + break; + + case R.id.me_item_wallet: + UIHelper.showWalletAct(mContext); + break; + case R.id.me_item_patriarch: + startActivity(new Intent(getActivity(), PatriarchModeActivity.class)); + break; + case R.id.me_item_setting: + UIHelper.showSettingAct(mContext); + break; + + case R.id.me_item_charge: + startActivity(new Intent(mContext, WalletGoldActivity.class)); + break; + + case R.id.me_item_radish: + RadishRecordActivity.startActivity(mContext); + break; + + case R.id.me_item_noble: + boolean isNoble = mNobleInfo != null && mNobleInfo.getLevel() > 0 || mUserInfo != null && mUserInfo.getNobleInfo() != null && mUserInfo.getNobleInfo().getLevel() > 0; + if (isNoble) { + CommonWebViewActivity.start(mContext, UriProvider.IM_SERVER_URL + "modules/nobles/homepage.html", + new CommonWebViewActivity.WebViewCallBack() { + @Override + public void onResult(String str) { + UserModel.get().updateCurrentUserInfo().subscribe(); + } + }); + } else { + CommonWebViewActivity.start(mContext, UriProvider.getNobleIntro(), + new CommonWebViewActivity.WebViewCallBack() { + @Override + public void onResult(String str) { + UserModel.get().updateCurrentUserInfo().subscribe(); + } + }); + } + break; + + case R.id.fl_me_level: + CommonWebViewActivity.start(mContext, UriProvider.getUserLevelUrl()); + break; + + case R.id.fl_me_charm: + CommonWebViewActivity.start(mContext, UriProvider.getUserCharmLevelUrl()); + break; + + case R.id.me_item_car_shop: + if (mUserInfo != null) { + DecorationStoreActivity.start(mContext, mUserInfo.getUid()); + } + break; + case R.id.ll_module_hall: + if (mUserInfo == null) { + return; + } + ModuleHallActivity.start(mContext); + break; + + case R.id.ll_approve: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.personal_data_101prove, "101认证"); + + CommonWebViewActivity.start(getActivity(), UriProvider.getTutuAprove()); + break; + + case R.id.ll_authen: + checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA) + .subscribe(result -> { + if (result) { + CommonWebViewActivity.start(getActivity(), UriProvider.getTutuRealNamePage()); + } else { + SingleToastUtil.showToast(getString(R.string.ask_again)); + } + }); + break; + + case R.id.ll_recommend_position: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_RECOMMEND_CLICK, "我的推荐卡"); + MyRecommendCardActivity.start(getActivity()); + break; + case R.id.ll_kf: + getDialogManager().showOkCancelDialog("点击确认后将发起客户对话框,确认联系客服吗?", + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + CustomerServerModel.getInstance().contactCustomerServer("", "我的页面", null) + .subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (throwable != null) { + toast(throwable.getMessage()); + } + } + }); + } + }); + + break; + default: + break; + } + + + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMarketVerifyUpdateEvent(MarketVerifyUpdateEvent event) { + //审核包隐藏tab + if (MarketVerifyModel.get().isMarketChecking()) { + mBinding.meItemMyFamily.setVisibility(View.GONE); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/MsgFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/MsgFragment.java new file mode 100644 index 000000000..08aa9673b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/MsgFragment.java @@ -0,0 +1,123 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.widget.LinearLayout; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.home.adapter.FragmentViewPagerAdapter; +import com.yizhuan.erban.home.adapter.TopMagicIndicatorAdapter; +import com.yizhuan.erban.ui.im.recent.RecentListFragment; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.im.RefreshInRoomListEvent; + +import org.greenrobot.eventbus.EventBus; + +import java.util.ArrayList; +import java.util.List; + +/** + *

主页消息界面

+ * + * @author Administrator + * @date 2017/11/14 + */ +public class MsgFragment extends BaseFragment implements TopMagicIndicatorAdapter.OnItemSelectListener{ + public static final String TAG = "MsgFragment"; + + private MagicIndicator indicator; + private ViewPager viewPager; + + @Override + public void onFindViews() { + indicator = mView.findViewById(R.id.indicator); + viewPager = mView.findViewById(R.id.viewpager); + } + + @Override + public void onSetListener() { + } + + @Override + public void initiate() { + List mTabInfoList = new ArrayList<>(); + mTabInfoList.add(getString(R.string.message)); + mTabInfoList.add(getResources().getString(R.string.message_contact)); + + List mTabs = new ArrayList<>(); + mTabs.add(RecentListFragment.newInstance(false)); + mTabs.add(ContactsListFragment.newInstance()); + + TopMagicIndicatorAdapter topMagicIndicatorAdapter = new TopMagicIndicatorAdapter(mContext, mTabInfoList); + topMagicIndicatorAdapter.setOnItemSelectListener(this); + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + commonNavigator.setAdapter(topMagicIndicatorAdapter); + indicator.setNavigator(commonNavigator); + // must after setNavigator + LinearLayout titleContainer = commonNavigator.getTitleContainer(); + titleContainer.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + + viewPager.setAdapter(new FragmentViewPagerAdapter(getChildFragmentManager(), mTabs)); + ViewPagerHelper.bind(indicator, viewPager); + + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MSG_TAB)) { + viewPager.post(() -> { + if (getActivity() != null && getActivity() instanceof MainActivity) { + if (!((MainActivity) getActivity()).isShowMsgTab()) { + return; + } +// TuTuGuideHelper helper = new TuTuGuideHelper(mContext); +// helper.createHiGuide(helper::createMsgTabOverLayer); +// TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MSG_TAB); + } + }); + } + + + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_msg; + } + + @Override + public void onItemSelect(int position) { + viewPager.setCurrentItem(position); + } + + /** + * 其他activity返回回调 + */ + @Override + public void onStart() { + super.onStart(); + if (!mHidden) { + reloadData(); + } + } + + private boolean mHidden = false; // 限制刷新次数,只在msgfragment页面去到二级页面返回才刷新 + + /** + * fragmentmanager show/hide 回调 + */ + @Override + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + mHidden = hidden; + + if (!hidden) { + reloadData(); + } + } + + private void reloadData() { + EventBus.getDefault().post(new RefreshInRoomListEvent()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/NewestKTVRoomFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/NewestKTVRoomFragment.java new file mode 100644 index 000000000..0406f969f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/NewestKTVRoomFragment.java @@ -0,0 +1,140 @@ +package com.yizhuan.erban.home.fragment; + +import android.graphics.Color; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.home.adapter.KTVTypeRoomAdapter; +import com.yizhuan.erban.home.presenter.NewestKTVRoomFragmentPresenter; +import com.yizhuan.erban.home.view.INewestKTVRoomFragmentView; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +@CreatePresenter(NewestKTVRoomFragmentPresenter.class) +public class NewestKTVRoomFragment extends BaseMvpFragment + implements INewestKTVRoomFragmentView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + + private SwipeRefreshLayout srlRefreshContainer; + private RecyclerView rvList; + + private KTVTypeRoomAdapter adapter; + + public static Fragment newInstance() { + return new NewestKTVRoomFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_newest_ktv; + } + + @Override + public void onFindViews() { + srlRefreshContainer = (SwipeRefreshLayout) getView().findViewById(R.id.srl_refresh_container); + rvList = (RecyclerView) getView().findViewById(R.id.rv_list); + rvList.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); + rvList.addItemDecoration(new ColorDecoration(Color.TRANSPARENT, 0, Utils.dip2px(getContext(), 10), false)); + adapter = new KTVTypeRoomAdapter(getContext(), null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, rvList); + rvList.setAdapter(adapter); + } + + @Override + public void onSetListener() { + srlRefreshContainer.setOnRefreshListener(this); + } + + @Override + public void initiate() { + } + + @Override + public void onResume() { + super.onResume(); + onRefresh(); + } + + + @Override + public void onRefresh() { + getMvpPresenter().refreshData() + .observeOn(AndroidSchedulers.mainThread()) + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + srlRefreshContainer.setRefreshing(false); + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List roomList) { + if (ListUtils.isListEmpty(roomList)) { + showNoData(); + return; + } + hideStatus(); + adapter.setNewData(roomList); + } + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMoreData() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List homeRoomList) { + if (!ListUtils.isListEmpty(homeRoomList)) { + adapter.addData(homeRoomList); + adapter.loadMoreComplete(); + } else { + adapter.loadMoreEnd(true); + } + + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RankingFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RankingFragment.java new file mode 100644 index 000000000..e36ae1af5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RankingFragment.java @@ -0,0 +1,229 @@ +package com.yizhuan.erban.home.fragment; + +import android.annotation.SuppressLint; +import android.net.http.SslError; +import android.os.Bundle; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; +import android.webkit.SslErrorHandler; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.alibaba.fastjson.JSON; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.FragmentRankingBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.webview.JSInterface; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.web.bean.WebJsBeanInfo; +import com.yizhuan.xchat_android_core.web.event.WebViewRefreshEvent; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.lang.ref.WeakReference; + +import cn.sharesdk.framework.Platform; + +/** + * 排行榜 + * 暂时继续使用 H5,后面再考虑换成原生的 + * Created by MadisonRong on 20/04/2018. + */ +@ActLayoutRes(R.layout.fragment_ranking) +public class RankingFragment extends BaseBindingFragment + implements ShareDialog.OnShareDialogItemClick { + + public static final String TAG = "RankingFragment"; + private TitleBar mTitleBar; + private WebView webView; + private ProgressBar mProgressBar; + private WebChromeClient wvcc; + private TextView mTvRightText; + + private WebJsBeanInfo mWebJsBeanInfo; + private String url; + private String targetUrl; + + private static final String POSITION = "position"; + private int mPosition; + + private int mProgress; + + private Handler mHandler = new Handler(); + + private RankingFragment.ProgressRunnable mProgressRunnable = new RankingFragment.ProgressRunnable(this); + + private static class ProgressRunnable implements Runnable { + private WeakReference mWeakReference; + + ProgressRunnable(RankingFragment activity) { + mWeakReference = new WeakReference<>(activity); + } + + @Override + public void run() { + RankingFragment activity = mWeakReference.get(); + if (activity == null) return; + if (activity.mProgress < 96) { + activity.mProgress += 3; + activity.mProgressBar.setProgress(activity.mProgress); + activity.mHandler.postDelayed(activity.mProgressRunnable, 10); + } + } + } + + @Override + protected void onInitArguments(Bundle bundle) { + url = UriProvider.JAVA_WEB_URL + "/modules/erbanRank/index.html"; + mPosition = 1; + } + + @SuppressLint("SetJavaScriptEnabled") + private void initData() { + mHandler.post(mProgressRunnable); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setUseWideViewPort(true); + webView.getSettings().setTextZoom(100); + JSInterface jsInterface = new JSInterface(webView, getActivity()); + jsInterface.setPosition(mPosition); + webView.addJavascriptInterface(jsInterface, "androidJsObj"); + webView.setWebViewClient(new WebViewClient() { + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Logger.e("shouldOverrideUrlLoading--------" + url); + targetUrl = url; + view.loadUrl(url); + return true; + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { +// super.onReceivedSslError(view, handler, error); //一定要去掉 + // handler.cancel();// Android默认的处理方式 + handler.proceed();// 接受所有网站的证书 + // handleMessage(Message msg);// 进行其他处理 + } + + @Override + public void onPageFinished(WebView view, String url) { + Logger.e("onPageFinished--------" + url); + mProgressBar.setProgress(100); + mProgressBar.setVisibility(View.GONE); + mTvRightText.setVisibility(View.GONE); + try { + webView.evaluateJavascript("showTitleRightNoticeFuck()", value -> { + if (TextUtils.isEmpty(value) || "null".equals(value.toLowerCase())) return; + mWebJsBeanInfo = JSON.parseObject(value, WebJsBeanInfo.class); + if (mWebJsBeanInfo == null) return; + WebJsBeanInfo.DataBean data = mWebJsBeanInfo.getData(); + if (data == null) return; + switch (mWebJsBeanInfo.getType()) { + case WebJsBeanInfo.TEXT: + mTvRightText.setVisibility(View.VISIBLE); + mTvRightText.setText(data.getTitle()); + mTvRightText.setOnClickListener(v -> webView.loadUrl(data.getLink())); + break; + default: + } + + }); + } catch (Exception e) { + e.printStackTrace(); + } + super.onPageFinished(view, url); + } + }); + //获取webviewtitle作为titlebar的title + wvcc = new WebChromeClient() { + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + mTitleBar.setTitle(title); + + } + + }; + // 设置setWebChromeClient对象 + webView.setWebChromeClient(wvcc); + if (mTitleBar != null) { + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + } + // 设置Webview的user-agent + webView.getSettings().setUserAgentString(webView.getSettings().getUserAgentString() + " erbanAppAndroid"); + } + + public void ShowWebView(String url) { + webView.loadUrl(url); + + } + + @Override + public void onResume() { + super.onResume(); + // 强制每次点到这个 tab 的时候就刷新数据 + ShowWebView(url); + } + + @Override + public void onInAppSharingItemClick() { + SelectFriendActivity.start(getContext()); + } + + @Override + public void onSharePlatformClick(Platform platform) { + if (mWebJsBeanInfo != null && mWebJsBeanInfo.getData() != null) { + ShareModel.get().shareH5(mWebJsBeanInfo.getData(), platform).subscribe(); + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRecieveNeedRefreshWebView(WebViewRefreshEvent event) { + if (!StringUtil.isEmpty(url)) { + ShowWebView(url); + } + } + + @Override + public void onDestroy() { + if (mHandler != null) { + mHandler.removeCallbacks(mProgressRunnable); + mProgressRunnable = null; + mHandler = null; + } + super.onDestroy(); + } + + @Override + public void onFindViews() { + webView = mBinding.webview; + mTitleBar = mBinding.title; + mProgressBar = mBinding.progressBar; + mTvRightText = mBinding.tvTitleRight; + } + + @Override + public void onSetListener() { + // + } + + @Override + public void initiate() { + initData(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendFragment.java new file mode 100644 index 000000000..902500ea6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendFragment.java @@ -0,0 +1,290 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.home.adapter.HomeFragmentAdapter; +import com.yizhuan.erban.home.presenter.RecommendFragmentPresenter; +import com.yizhuan.erban.home.view.Home3PlusNDecoration; +import com.yizhuan.erban.home.view.IMainFragmentTabBg; +import com.yizhuan.erban.home.view.IRecommendFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author jack + * @Description 推荐页面 + * @Date 2018/10/29 + */ +@CreatePresenter(RecommendFragmentPresenter.class) +public class RecommendFragment extends BaseMvpFragment + implements IRecommendFragmentView, HomeFragmentAdapter.OnActionListener { + + public static final String TAG = RecommendFragment.class.getSimpleName(); + + private SwipeRefreshLayout swipeRefreshLayout; + private RecyclerView rvMainHome; + private HomeFragmentAdapter mHomeHotAdapter; + private MainFragment mainFragment; + + private IMainFragmentTabBg iMainFragmentTabBg; + + public static Fragment newInstance(IMainFragmentTabBg iMainFragmentTabBg) { + RecommendFragment recommendFragment = new RecommendFragment(); + recommendFragment.setiMainFragmentTabBg(iMainFragmentTabBg); + return recommendFragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_recommend; + } + + @Override + public void onFindViews() { + swipeRefreshLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_refresh); + rvMainHome = (RecyclerView) mView.findViewById(R.id.rv_main_home); + } + + @Override + public void onSetListener() { + swipeRefreshLayout.setOnRefreshListener(onRefreshListener); + + } + + @Override + public void initiate() { + LogUtil.e(TAG, "initiate~~~ "); + mainFragment = (MainFragment) getParentFragment(); + mHomeHotAdapter = new HomeFragmentAdapter(mContext, new ArrayList<>()); + mHomeHotAdapter.setActionListener(this); + mHomeHotAdapter.setEnableLoadMore(false); + rvMainHome.setItemAnimator(null); + rvMainHome.addItemDecoration(new Home3PlusNDecoration(mContext, mHomeHotAdapter)); + GridLayoutManager manager = new GridLayoutManager(getActivity(), 3); + mHomeHotAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + int itemType = mHomeHotAdapter.getData().get(position).getItemType(); + if (itemType == HomeItem.TYPE_SQUARE_PIC || itemType == HomeItem.TYPE_SQUARE_EMPTY) { + return 1; + } + return gridLayoutManager.getSpanCount(); + } + }); + rvMainHome.setLayoutManager(manager); + //加载更多 + mHomeHotAdapter.setOnLoadMoreListener(() -> getMvpPresenter().loadMoreHomeData(), rvMainHome); + rvMainHome.setAdapter(mHomeHotAdapter); + + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(getMvpPresenter().getmHomeItemList())) { + swipeRefreshLayout.setRefreshing(true); + getMvpPresenter().loadHomeData(); + } else { + if (ListUtils.isListEmpty(this.mHomeHotAdapter.getData())) { + loadHomeDataSuccess(getMvpPresenter().getmHomeItemList()); + } + } + + } + + private SwipeRefreshLayout.OnRefreshListener onRefreshListener = new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + if (NetworkUtil.isNetAvailable(mContext)) { + getMvpPresenter().setPage(Constants.PAGE_START); + getMvpPresenter().loadHomeData(); + } else { + swipeRefreshLayout.setRefreshing(false); + } + } + }; + + @Override + public void onReloadData() { + super.onReloadData(); + showLoading(); + getMvpPresenter().loadHomeData(); + } + + @Override + public void loadHomeDataSuccess(List data) { + hideStatus(); + swipeRefreshLayout.setRefreshing(false); + mHomeHotAdapter.setNewData(data); + mHomeHotAdapter.disableLoadMoreIfNotFullPage(rvMainHome); + + } + + @Override + public void loadHomeDataFail(String error) { + swipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } + + @Override + public void onNoHomeData() { + swipeRefreshLayout.setRefreshing(false); + showNoData(); + } + + @Override + public void addHomeDataSuccess(List data) { + mHomeHotAdapter.loadMoreComplete(); + mHomeHotAdapter.notifyDataSetChanged(); + } + + @Override + public void onNoMoreHomeData() { + swipeRefreshLayout.setRefreshing(false); + mHomeHotAdapter.loadMoreEnd(true); + } + + @Override + public void addHomeDataFail(String error) { + mHomeHotAdapter.loadMoreFail(); + } + + + @Override + public void setEnableLoadMore(boolean b) { + mHomeHotAdapter.setEnableLoadMore(b); + } + + @Override + public void setRefreshing(boolean b) { + swipeRefreshLayout.setRefreshing(b); + } + + @Override + public void notifyDataSetChanged(int type, int position, Object payload) { +// if (IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED == type) { +// if (position < 0) { +// mHomeHotAdapter.notifyDataSetChanged(); +// } else { +// mHomeHotAdapter.notifyItemChanged(position, payload); +// } +// } else if (IRecommendFragmentView.NOTIFY_DATA_SET_REMOVE == type) { +// if (position < 0) { +// mHomeHotAdapter.notifyDataSetChanged(); +// } else { +// mHomeHotAdapter.notifyItemRemoved(position); +// } +// } + + mHomeHotAdapter.notifyDataSetChanged(); + } + + + @Override + public void showByMarketCheckingStatus() { + if (getMvpPresenter() != null) { + swipeRefreshLayout.setRefreshing(true); + getMvpPresenter().loadHomeData(); + } + } + + @Override + public void onRefreshMakeFriendListFail(String message) { + toast(message); + } + + + @Override + public void onRefreshMakeFriendList() { + getMvpPresenter().refreshMakeFriendList(); + } + + @Override + public void onMoreKTVRoom() { + mainFragment.goToKTVTab(); + } + + @Override + public void onGoTalkHall() { + + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + + if (getUserVisibleHint()) + changeTabBg(); + } + + private void changeTabBg() { + if (iMainFragmentTabBg != null && getUserVisibleHint()) + iMainFragmentTabBg.isBannerTop(true); + } + + public void setiMainFragmentTabBg(IMainFragmentTabBg iMainFragmentTabBg) { + this.iMainFragmentTabBg = iMainFragmentTabBg; + } + + @Override + public void onDestroy() { + super.onDestroy(); + iMainFragmentTabBg = null; + } + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showNoData view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.layout_home_empty, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + if (getView() == null) { + MLog.error(this, "xuwakao, showNetworkErr view is NULL"); + return; + } + View view = getView().findViewById(R.id.status_layout); + if (view == null || view.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = NetworkErrorFragment.newInstance(R.layout.layout_home_network_erro); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(view.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendationFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendationFragment.java new file mode 100644 index 000000000..062be249e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RecommendationFragment.java @@ -0,0 +1,449 @@ +package com.yizhuan.erban.home.fragment; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshListener; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.home.adapter.HomeFragmentAdapter; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.bean.RecommendationUserInfo; +import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Function; + +/** + * 推荐 合拍女神 + */ +public class RecommendationFragment extends BaseFragment implements View.OnClickListener { + + private static final String PARAM_TYPE = "type"; + private static final int PAGE_SIZE = 20; + + private String type; + private RecyclerView recyclerView; + + private SmartRefreshLayout smartRefreshLayout; + + private int pageIndex = 1; + + private HomeItem> bannerHomeItem; + private List totalHomeItemList = new ArrayList<>(); + private boolean isContainsBanner; + private HomeFragmentAdapter mHomeFragmentAdapter; + private final Object mLock = new Object(); + + private Disposable mDisposable; + + public RecommendationFragment() { + // Required empty public constructor + } + + public static RecommendationFragment newInstance(String type) { + RecommendationFragment fragment = new RecommendationFragment(); + Bundle args = new Bundle(); + args.putString(PARAM_TYPE, type); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + type = getArguments().getString(PARAM_TYPE); + } + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private long mLastOpen; + private String mTabName; + public void setTypeAndName(String type, String name) { + this.type = type; + mTabName = name; + } + + public void setTypeAndRefresh(String type, String name) { + setTypeAndName(type, name); + + if (smartRefreshLayout != null) { + if (smartRefreshLayout.isRefreshing()) { + + smartRefreshLayout.finishRefresh(); + if (mDisposable != null && !mDisposable.isDisposed()) { + mDisposable.dispose(); + } + } + } + + if (mHomeFragmentAdapter != null) { + mHomeFragmentAdapter.loadMoreComplete(); + } + refreshData(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_recommendation; + } + + @Override + public void onFindViews() { + super.onFindViews(); + recyclerView = mView.findViewById(R.id.recycler_view); + smartRefreshLayout = mView.findViewById(R.id.smart_refresh_layout); + initRefreshView(); + initRecyclerView(); + } + + private void initRefreshView() { + smartRefreshLayout.setEnableLoadmore(false); + smartRefreshLayout.setEnableRefresh(true); + smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() { + @Override + public void onRefresh(RefreshLayout refreshlayout) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_DROP_REFRESH, "首页-下拉刷新"); + refreshNoLoading(); + } + }); + } + + private void refreshNoLoading() { + pageIndex = 1; + loadData(true); + } + + private void initRecyclerView() { + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.addItemDecoration(new ColorDecoration(getResources().getColor(R.color.color_FAFAFA) + , 0, ScreenUtil.dip2px(8), true)); + recyclerView.setItemAnimator(null); + mHomeFragmentAdapter = new HomeFragmentAdapter(getContext(), totalHomeItemList); + + mHomeFragmentAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + loadData(false); + } + }, recyclerView); + mHomeFragmentAdapter.setEnableLoadMore(false); + recyclerView.setAdapter(mHomeFragmentAdapter); + + mHomeFragmentAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + try { + List items = adapter.getData(); + HomeItem item; + if (items.size() > position) { + item = items.get(position); + Object obj = item.getData(); + if (!(obj instanceof RecommendationUserInfo)) { + return; + } + RecommendationUserInfo info = (RecommendationUserInfo) obj; + + if (info.getStatus() == RecommendationUserInfo.STATUS_RECOMMEND_ROOM) { + // 推荐房点击任何区域都进房 + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_USER_LIST_STEP_INTO_ROOM, "首页-用户列表-踩进房间"); + openRoom(info.getUid(), info.isRecommendRoom()); + } else { + switch (view.getId()) { + case R.id.fl_avatar: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_PAGE_PERSONAL_PAGE, "进入个人客态页"); + UIHelper.showUserInfoAct(mContext, info.getUid()); + break; + + case R.id.ll_sub_content: + NimP2PMessageActivity.startWithChatterBox(mContext, String.valueOf(info.getUid()), null); + break; + + case R.id.rl_opt: + + switch (info.getStatus()) { + case RecommendationUserInfo.STATUS_KTV: + case RecommendationUserInfo.STATUS_GAME: + case RecommendationUserInfo.STATUS_ROOM: + case RecommendationUserInfo.STATUS_RECOMMEND_ROOM: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_USER_LIST_STEP_INTO_ROOM, "首页-用户列表-踩进房间"); + openRoom(info.getUid(), info.isRecommendRoom()); + break; + + case RecommendationUserInfo.STATUS_NORMAL: + default: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_PAGE_HOOK_UP, "撩一下"); + NimP2PMessageActivity.startWithAccost(mContext, String.valueOf(info.getUid())); + } + break; + } + + } + + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }); + } + + @SuppressWarnings("CheckResult") + private void openRoom(long uid, boolean isRecommendRoom) { + if (System.currentTimeMillis() - mLastOpen < 1000) { + return; + } + + if (mContext instanceof BaseMvpActivity) { + if (!TextUtils.isEmpty(mTabName)) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MATCH_MALE_ENTER_ROOM, mTabName + "-进入房间"); + } + mLastOpen = System.currentTimeMillis(); + BaseMvpActivity activity = (BaseMvpActivity) mContext; + activity.getDialogManager().showProgressDialog(mContext, "请稍后..."); + + if (isRecommendRoom) { + AvRoomModel.get().requestRoomInfoByUser(String.valueOf(uid)) + .compose(activity.bindToLifecycle()) + .subscribe(roomInfo -> { + if (roomInfo != null && roomInfo.getUid() > 0) { + AVRoomActivity.start(mContext, roomInfo.getUid(), roomInfo.getType()); + } else { + SingleToastUtil.showToast("对方不在房间内"); + } + activity.getDialogManager().dismissDialog(); + + }); + + } else { + AvRoomModel.get() + .getUserRoom(uid) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()) + .compose(activity.bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(RoomInfo roomInfo, Throwable throwable) throws Exception { + if (throwable == null) { + if (roomInfo != null && roomInfo.getUid() > 0) { + AVRoomActivity.start(mContext, roomInfo.getUid(), roomInfo.getType()); + } else { + SingleToastUtil.showToast("对方不在房间内"); + } + } else { + SingleToastUtil.showToast("可能暂时不在房间哟"); + } + activity.getDialogManager().dismissDialog(); + } + }); + + } + + } else { + SingleToastUtil.showToast("出现异常"); + } + + } + + @Override + public void initiate() { + refreshData(); + } + + private void refreshData() { + if (smartRefreshLayout != null) { + smartRefreshLayout.autoRefresh(); + } + } + + @SuppressLint("CheckResult") + private void loadData(boolean isRefresh) { + long uid = AuthModel.get().getCurrentUid(); + mDisposable = HomeModel.get() + .getGodList(uid, pageIndex, PAGE_SIZE, type) + .map(new Function, List>>() { + @Override + public List> apply(List recommendationUserInfos) throws Exception { + if (ListUtils.isListEmpty(recommendationUserInfos)) { + return new ArrayList<>(); + } + List> homeItemList = new ArrayList<>(); + for (RecommendationUserInfo recommendationUserInfo : recommendationUserInfos) { + if (recommendationUserInfo == null) { + continue; + } + //推荐房间修改状态处理 + if (recommendationUserInfo.isRecommendRoom()) { + recommendationUserInfo.setStatus(RecommendationUserInfo.STATUS_RECOMMEND_ROOM); + } + homeItemList.add(new HomeItem(HomeItem.TYPE_USER_LINEAR, recommendationUserInfo)); + } + return homeItemList; + } + }) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .compose(RxHelper.handleSchedulers()) + .subscribe(new BiConsumer>, Throwable>() { + @Override + public void accept(List> recommendationUserInfos, Throwable throwable) throws Exception { + if (throwable == null) { + if (!ListUtils.isListEmpty(recommendationUserInfos)) { + pageIndex++; + if (isRefresh) { + mHomeFragmentAdapter.setEnableLoadMore(true); + } + } else { + loadEnd(); + } + + synchronized (mLock) { + if (isRefresh) { + totalHomeItemList.clear(); + totalHomeItemList.addAll(recommendationUserInfos); + isContainsBanner = false; + recombinationData(); +// showGuide(); + } else { + totalHomeItemList.addAll(recommendationUserInfos); + mHomeFragmentAdapter.notifyDataSetChanged(); + } + } + if (isRefresh) { + smartRefreshLayout.finishRefresh(); + } else { + mHomeFragmentAdapter.loadMoreComplete(); + } + } else { + if (isRefresh) { + smartRefreshLayout.finishRefresh(); + } else { + loadEnd(); + } + } + + + } + }); + } + + private void loadEnd() { + mHomeFragmentAdapter.loadMoreComplete(); + mHomeFragmentAdapter.loadMoreEnd(); + mHomeFragmentAdapter.setEnableLoadMore(false); + } + + /** + * 用户信息更新 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void loadLoginUserInfoEvent(LoadLoginUserInfoEvent event) { + if (smartRefreshLayout != null && !smartRefreshLayout.isRefreshing()) { + refreshData(); + } + } + + @Override + public void onClick(View v) { + + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + } + + private void recombinationData() { + synchronized (mLock) { + List homeItems = totalHomeItemList; + if (bannerHomeItem != null && !isContainsBanner) { + + totalHomeItemList.add(homeItems.size() > 3 ? 3 : homeItems.size(), bannerHomeItem); + isContainsBanner = true; + } + mHomeFragmentAdapter.notifyDataSetChanged(); + } + } + + /** + * 显示引导 + */ + private void showGuide() { + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_HOME)) { + recyclerView.postDelayed(new Runnable() { + @Override + public void run() { + Fragment fragment = getParentFragment(); + if (!(fragment instanceof GameHomeFragment)) { + return; + } + List views = ((GameHomeFragment) fragment).getHomeBanner(3); + if (views == null) { + return; + } + int count = recyclerView.getChildCount(); + if (count < 1) { + return; + } + View view = recyclerView.getChildAt(1); + if (view == null) { + return; + } + view = view.findViewById(R.id.ll_left_content); + if (view == null) { + return; + } + + View finalView = view; + TuTuGuideHelper helper = new TuTuGuideHelper(getContext()); + helper.createHiGuide(() -> helper.createMainHomeGuide(views, finalView)); + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_MAIN_HOME); + } + }, 500); + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RoomCategoryFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomCategoryFragment.java new file mode 100644 index 000000000..927f5f58e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomCategoryFragment.java @@ -0,0 +1,76 @@ +package com.yizhuan.erban.home.fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.home.adapter.CommonMagicIndicatorAdapter; +import com.yizhuan.erban.home.adapter.RoomCategoryIndicatorAdapter; +import com.yizhuan.erban.home.adapter.RoomCategoryViewPagerAdapter; +import com.yizhuan.erban.home.presenter.RoomCategoryFragmentPresenter; +import com.yizhuan.erban.home.view.IRoomCategoryFragmentView; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +@CreatePresenter(RoomCategoryFragmentPresenter.class) +public class RoomCategoryFragment extends BaseMvpFragment + implements IRoomCategoryFragmentView, RoomCategoryIndicatorAdapter.OnItemSelectListener { + + private MagicIndicator mainIndicator; + private ViewPager vpRoomCategoryViewpager; + + public static Fragment newInstance() { + return new RoomCategoryFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_room_category; + } + + @Override + public void onFindViews() { + mainIndicator = (MagicIndicator) mView.findViewById(R.id.main_indicator); + vpRoomCategoryViewpager = (ViewPager) mView.findViewById(R.id.vp_room_category_viewpager); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + List mTabInfoList = getMvpPresenter().getTabInfoList(); + if (ListUtils.isListEmpty(mTabInfoList)) { + getMvpPresenter().loadTabInfoList(); + return; + } + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + RoomCategoryIndicatorAdapter magicIndicatorAdapter = new RoomCategoryIndicatorAdapter(getContext(), mTabInfoList); + magicIndicatorAdapter.setOnItemSelectListener(this); + commonNavigator.setAdapter(magicIndicatorAdapter); + mainIndicator.setNavigator(commonNavigator); + vpRoomCategoryViewpager.setAdapter(new RoomCategoryViewPagerAdapter(getChildFragmentManager(), mTabInfoList)); + ViewPagerHelper.bind(mainIndicator, vpRoomCategoryViewpager); + } + + @Override + public void onItemSelect(int position) { + vpRoomCategoryViewpager.setCurrentItem(position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RoomListFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomListFragment.java new file mode 100644 index 000000000..71a2ea2bf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomListFragment.java @@ -0,0 +1,163 @@ +package com.yizhuan.erban.home.fragment; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.home.adapter.HomeRoomAdapter; +import com.yizhuan.erban.home.presenter.RoomListPresenter; +import com.yizhuan.erban.home.view.IRoomListFragmentView; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +/** + * @author jack + * @Description + * @Date 2018/11/2 + */ +@CreatePresenter(RoomListPresenter.class) +public class RoomListFragment extends BaseMvpFragment + implements IRoomListFragmentView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + + private HomeRoomAdapter adapter; + + public static Fragment newInstance(TabInfo tabInfo) { + Fragment fragment = new RoomListFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(BundleKeys.KEY_EXTRA_1, tabInfo); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_room_list; + } + + @Override + public void onFindViews() { + swipeRefresh = (SwipeRefreshLayout) getView().findViewById(R.id.swipe_refresh); + recyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view); + + } + + @Override + public void onSetListener() { + swipeRefresh.setOnRefreshListener(this); + } + + @Override + public void initiate() { + Bundle bundle = getArguments(); + if (bundle != null) { + TabInfo tabInfo = (TabInfo) bundle.getSerializable(BundleKeys.KEY_EXTRA_1); + getMvpPresenter().setTabInfo(tabInfo); + } + + adapter = new HomeRoomAdapter(getContext(), null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerView.setAdapter(adapter); + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())) { + refreshData(); + } + } + + @Override + public void onRefresh() { + refreshData(); + } + + @Override + public void onLoadMoreRequested() { + loadMoreData(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + refreshData(); + } + + private void loadMoreData() { + getMvpPresenter().loadMoreData() + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List homeRoomItems) { + if (!ListUtils.isListEmpty(homeRoomItems)) { + adapter.addData(homeRoomItems); + adapter.loadMoreComplete(); + } else { + adapter.loadMoreEnd(true); + } + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + + private void refreshData() { + getMvpPresenter().refreshData() + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + swipeRefresh.setRefreshing(false); + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List homeRoomItems) { + if (ListUtils.isListEmpty(homeRoomItems)) { + showNoData(); + return; + } + hideStatus(); + adapter.setNewData(homeRoomItems); + } + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/fragment/RoomTabFragment.java b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomTabFragment.java new file mode 100644 index 000000000..06994c188 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/fragment/RoomTabFragment.java @@ -0,0 +1,239 @@ +package com.yizhuan.erban.home.fragment; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.NetworkErrorFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.constants.BundleKeys; +import com.yizhuan.erban.home.adapter.RoomTabAdapter; +import com.yizhuan.erban.home.presenter.RoomTabPresenter; +import com.yizhuan.erban.home.view.IMainFragmentTabBg; +import com.yizhuan.erban.home.view.IRoomTabView; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; + +@CreatePresenter(RoomTabPresenter.class) +public class RoomTabFragment extends BaseMvpFragment + implements IRoomTabView, SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener { + + private SwipeRefreshLayout swipeRefresh; + private RecyclerView recyclerView; + + private RoomTabAdapter adapter; + + private IMainFragmentTabBg iMainFragmentTabBg; + + public static Fragment newInstance(long titleId, IMainFragmentTabBg iMainFragmentTabBg) { + RoomTabFragment fragment = new RoomTabFragment(); + fragment.setiMainFragmentTabBg(iMainFragmentTabBg); + Bundle bundle = new Bundle(); + bundle.putSerializable(BundleKeys.KEY_EXTRA_1, titleId); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_room_tab; + } + + @Override + public void onFindViews() { + swipeRefresh = getView().findViewById(R.id.swipe_refresh); + recyclerView = getView().findViewById(R.id.recycler_view); + } + + @Override + public void onSetListener() { + swipeRefresh.setOnRefreshListener(this); + } + + @Override + public void initiate() { + Bundle bundle = getArguments(); + if (bundle != null) { + long mTitleId = bundle.getLong(BundleKeys.KEY_EXTRA_1, -1); + getMvpPresenter().setmTitleId(mTitleId); + } + + adapter = new RoomTabAdapter(getContext(), null); + adapter.setEnableLoadMore(true); + adapter.setOnLoadMoreListener(this, recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerView.setAdapter(adapter); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + + if (getUserVisibleHint()) + changeTabBg(); + } + + @Override + public void onResume() { + super.onResume(); + if (ListUtils.isListEmpty(adapter.getData())) { + refreshData(); + } else + changeTabBg(); + } + + @Override + public void onRefresh() { + refreshData(); + } + + @Override + public void onLoadMoreRequested() { + loadMoreData(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + refreshData(); + } + + private void loadMoreData() { + getMvpPresenter().loadMoreData() + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List homeRoomItems) { + if (!ListUtils.isListEmpty(homeRoomItems)) { + adapter.addData(homeRoomItems); + adapter.loadMoreComplete(); + } else { + adapter.loadMoreEnd(true); + } + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + + @Override + public void showNetworkErr() { + if (!checkActivityValid()) { + return; + } + + if (getView() == null) { + MLog.error(this, "xuwakao, showNetworkErr view is NULL"); + return; + } + View view = getView().findViewById(R.id.status_layout); + if (view == null || view.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NetworkErrorFragment fragment = NetworkErrorFragment.newInstance(R.layout.layout_home_network_erro); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(view.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + public void setiMainFragmentTabBg(IMainFragmentTabBg iMainFragmentTabBg) { + this.iMainFragmentTabBg = iMainFragmentTabBg; + } + + private void changeTabBg() { + + boolean isBannerTop = false; + + if (adapter == null) + return; + + List list = adapter.getData(); + if (!ListUtils.isListEmpty(list)) { + HomeRoomItem homeRoomItem = list.get(0); + isBannerTop = homeRoomItem.getItemType() == HomeRoomItem.TYPE_BANNER; + } + + if (iMainFragmentTabBg != null && getUserVisibleHint()) { + iMainFragmentTabBg.isBannerTop(isBannerTop); + } + } + + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + MLog.error(this, "xuwakao, showNoData view is NULL"); + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + MLog.error(this, "xuwakao, had not set layout id "); + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.layout_home_empty, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + private void refreshData() { + getMvpPresenter().refreshData() + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + swipeRefresh.setRefreshing(false); + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List homeRoomItems) { + if (ListUtils.isListEmpty(homeRoomItems)) { + showNoData(); + return; + } + hideStatus(); + adapter.setNewData(homeRoomItems); + changeTabBg(); + } + + @Override + public void onError(Throwable e) { + showNetworkErr(); + toast(e.getMessage()); + } + }); + } + + @Override + public void onDestroy() { + super.onDestroy(); + iMainFragmentTabBg = null; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/helper/JumpHelper.java b/app/src/main/java/com/yizhuan/erban/home/helper/JumpHelper.java new file mode 100644 index 000000000..4acaf217d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/helper/JumpHelper.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.home.helper; + +import android.content.Context; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; + +/** + * @author jack + * @Description 跳转本地页面配置 + * @Date 2018/4/25 + */ + +public class JumpHelper { + public final static String TYPE_RANK_BOARD = "1";//1为排行榜 + public final static String JUMP_RANK_BOARD_STRING = "JUMP_RANK_BOARD_STRING"; + public final static String TYPE_SHOP = "2";//跳转商城 + + public static void jumpByType(Context context, String type){ + if (TYPE_RANK_BOARD.equals(type)){ + RxBusHelper.post(JUMP_RANK_BOARD_STRING); + }else if (TYPE_SHOP.equals(type)){ + long uid = AuthModel.get().getCurrentUid(); + if (uid > 0) { + DecorationStoreActivity.start(context, uid); + } + }else{ + Logger.e("未知app原生页面 跳转类型..."); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/helper/LoadPageDataHelper.java b/app/src/main/java/com/yizhuan/erban/home/helper/LoadPageDataHelper.java new file mode 100644 index 000000000..327a9fbbb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/helper/LoadPageDataHelper.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.home.helper; + +import com.yizhuan.xchat_android_core.Constants; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; +import io.reactivex.functions.Consumer; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public class LoadPageDataHelper { + private int curPage = Constants.PAGE_START; + private boolean loading = false; + private LoadData loadData; + + public LoadPageDataHelper(LoadData loadData) { + this.loadData = loadData; + } + + public Single refreshData() { + this.curPage = Constants.PAGE_START; + return internalLoadData(this.curPage); + } + + public Single loadMoreData() { + return internalLoadData(this.curPage); + } + + private Single internalLoadData(int targetPage) { + if (loading) { + return Single.error(new Throwable("正在加载中...")); + } + loading = true; + return loadData.loadData(targetPage) + .observeOn(AndroidSchedulers.mainThread()) + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + curPage++; + loading = false; + } + }); + } + + public interface LoadData { + Single loadData(int curPage); + } + + public void setCurPage(int newPage) { + this.curPage = newPage; + } + + public boolean isLoading() { + return loading; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/model/AllGameVm.java b/app/src/main/java/com/yizhuan/erban/home/model/AllGameVm.java new file mode 100644 index 000000000..f1c4056d5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/model/AllGameVm.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.home.model; + +import com.yizhuan.erban.base.BaseListViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; + +import java.util.Iterator; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.Consumer; + +public class AllGameVm extends BaseListViewModel { + @Override + public Single>> getSingle() { + return GameModel.get().getApi().getHomeGameList(AuthModel.get().getCurrentUid(), page, pageSize) + .compose(RxHelper.handleSchedulers()) + .doOnSuccess(listServiceResult -> { + Iterator iterator = listServiceResult.getData().iterator(); + while (iterator.hasNext()) { + GameInfo gameInfo = iterator.next(); + if (!"all".equals(gameInfo.getPlatform()) && !"android".equals(gameInfo.getPlatform())) { + iterator.remove(); + } + } + if (!isLode.get()) { + listServiceResult.getData().add(0, new GameInfo()); + } + + }) + ; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/model/UserMatchVm.java b/app/src/main/java/com/yizhuan/erban/home/model/UserMatchVm.java new file mode 100644 index 000000000..1fc52ac5f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/model/UserMatchVm.java @@ -0,0 +1,156 @@ +package com.yizhuan.erban.home.model; + +import android.databinding.Observable; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.databinding.ObservableInt; +import android.view.View; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.game.MatchActivity; +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.room.game.GameMatchInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.net.rxnet.RxNet; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import lombok.Setter; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.POST; + +public class UserMatchVm extends BaseViewModel { + public static final String SVGA_START = "https://img.tutuyuyin.com/start_match.svga"; + public static final String SVGA_MATCHING = "https://img.tutuyuyin.com/matching.svga"; + + public static final int START = 1;//默认页面 + public static final int MATCHING = 2;//匹配中 + public static final int END = 3;//匹配成功 + + public static final int BOY = 1; + public static final int GIRL = 2; + public static final int NO_LIMIT = 3; + private Disposable subscribe; + + private Api api; + //页面状态,对应上面code + public ObservableInt pageType = new ObservableInt(START); + public ObservableField selfInfo = new ObservableField(); + public ObservableField rightInfo = new ObservableField(); + private Observer observer; + private int findType; + @Setter + private Consumer matchConsumer; + + public void setFindType(int findType) { + this.findType = findType; + } + + public int getFindType() { + return findType; + } + + public UserMatchVm() { + api = RxNet.create(Api.class); + selfInfo.set(UserModel.get().getCacheLoginUserInfo()); + findType = DemoCache.readFilTrateType(); + + observer = (Observer) message -> { + // 在这里处理自定义通知。 + if (message != null) { + try { + LogUtil.e("系统消息" + message.getContent()); + pageType.set(END); + JSONObject object = JSON.parseObject(message.getContent()); + GameMatchInfo matchInfo = new Gson().fromJson(object.toJSONString(), GameMatchInfo.class); + if (matchInfo == null || matchInfo.getData() == null) return; + if (matchInfo.getData().getPlayer1().getUid() != AuthModel.get().getCurrentUid()) { + rightInfo.set(matchInfo.getData().getPlayer1()); + } else if (matchInfo.getData().getPlayer2().getUid() != AuthModel.get().getCurrentUid()) { + rightInfo.set(matchInfo.getData().getPlayer2()); + } + subscribe = Single.just(rightInfo.get()).subscribe(matchConsumer); + } catch (Exception e) { + } + } + }; + + } + + public void destroy() { + if (subscribe != null) { + subscribe.dispose(); + } + removePlayer().subscribe(); + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + } + + public void changePageType(Consumer consumer) { + if (pageType.get() == START) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_player_beginmatch, "开始匹配"); + + addPlayer() + .doOnError(consumer) + .subscribe(); + + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, true); + } + if (pageType.get() == MATCHING) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_player_finishmatch, "停止匹配"); + removePlayer().subscribe(); + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(observer, false); + } + if (pageType.get() != END) { + pageType.set(pageType.get() == START ? MATCHING : START); + } + } + + public Single addPlayer() { + return api.addPlayer(AuthModel.get().getCurrentUid(), findType) + .compose(RxHelper.handleRoomPmLimit()) + .compose(RxHelper.handleCommon(() -> "")); + } + + public Single removePlayer() { + return api.removePlayer(AuthModel.get().getCurrentUid(), findType) + .compose(RxHelper.singleMainResult()); + } + + interface Api { + /** + * @param uid + * @param findType 1-男 | 2-女 |3-无限制 + * @return + */ + @FormUrlEncoded + @POST("game/v4/match/addPlayer") + Single> addPlayer(@Field("uid") long uid, @Field("findType") int findType); + + @FormUrlEncoded + @POST("game/v4/match/removePlayer") + Single> removePlayer(@Field("uid") long uid, @Field("findType") int findType); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/CommunityNoticePresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/CommunityNoticePresenter.java new file mode 100644 index 000000000..3e7c97a5e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/CommunityNoticePresenter.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.home.presenter; + +import android.annotation.SuppressLint; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.ICommunityNoticeAct; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.community.bean.CommunityNoticeInfo; +import com.yizhuan.xchat_android_core.home.model.CommunityNoticeModel; + +import java.util.List; + +import io.reactivex.functions.BiConsumer; + +public class CommunityNoticePresenter extends BaseMvpPresenter { + private int page = 0; + private int pageSize = Constants.PAGE_SIZE; + private Long lastId; + + public void refresh(long uid) { + page = 1; + getMsgList(uid, null); + } + + public void loadMore(long uid) { + page++; + getMsgList(uid, lastId); + } + + @SuppressLint("CheckResult") + private void getMsgList(long uid, Long id) { + CommunityNoticeModel.get().getMsg(uid, id, pageSize) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List communityNoticeInfos, Throwable throwable) throws Exception { + + if (throwable == null) { + if (communityNoticeInfos != null && communityNoticeInfos.size() > 0) { + lastId = communityNoticeInfos.get(communityNoticeInfos.size() - 1).getMsgId(); + + if (mMvpView != null) { + mMvpView.getMsgListSuccess(communityNoticeInfos); + } + } else { + if (mMvpView != null) { + mMvpView.getMsgListFail("无数据"); + } + } + + } else { + page--; + if (mMvpView != null) { + mMvpView.getMsgListFail(throwable.getMessage()); + } + } + + } + }); + + } + + @SuppressLint("CheckResult") + public void delete(long uid) { + CommunityNoticeModel.get().delete(uid).compose(bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + + if (throwable == null) { + if (mMvpView != null) { + mMvpView.clearSuccess(); + } + + } else { + if (mMvpView != null) { + mMvpView.clearFail(throwable.getMessage()); + } + + } + + } + }); + } + + public int getPage() { + return page; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/FamilyFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/FamilyFragmentPresenter.java new file mode 100644 index 000000000..f6b85f36b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/FamilyFragmentPresenter.java @@ -0,0 +1,150 @@ +package com.yizhuan.erban.home.presenter; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IFamilyFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.family.bean.CustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyCustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.FindBannerInfo; +import com.yizhuan.xchat_android_core.family.bean.response.RankingFamilyInfo; +import com.yizhuan.xchat_android_core.family.bean.response.RespFamilyRankList; +import com.yizhuan.xchat_android_core.family.event.FamilyUpdateEvent; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public class FamilyFragmentPresenter extends BaseMvpPresenter { + private CompositeDisposable compositeDisposable; + private FamilyInfo myFamily = null; + + public FamilyFragmentPresenter() { + + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + compositeDisposable = new CompositeDisposable(); + addRxEvent(); + } + + @Override + public void onResumePresenter() { + super.onResumePresenter(); + Logger.e("onResumePresenter ~~~"); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (compositeDisposable != null) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + } + + private void addRxEvent() { + /** + * 家族更新事件 + */ + RxBusHelper.doOnMainThread(FamilyUpdateEvent.class, compositeDisposable, new Consumer() { + @Override + public void accept(FamilyUpdateEvent familyUpdateEvent) throws Exception { + checkMyFamilyInfo(); + } + }); + } + + + public FamilyInfo getMyFamily() { + return myFamily; + } + + /** + * 检查我的家族信息 + */ + public void checkMyFamilyInfo() { + myFamily = FamilyModel.Instance().getMyFamily(); + getMvpView().showMyFamilyInfo(myFamily); + } + + public Single> loadWeeklyStarList() { + return FamilyModel.Instance().loadFamilyRankingList( + RespFamilyRankList.TYPE_LAST_WEEK, + String.valueOf(Constants.PAGE_START), + String.valueOf(6) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(RespFamilyRankList response) throws Exception { + return Single.just(response.getFamilys()); + } + }); + } + + /** + * 联系客服 + */ + public Single contactCustomerService() { + //去聊 + FamilyCustomServiceInfo serviceInfo = FamilyModel.Instance().getCustomServiceInfo(); + if (null == serviceInfo) { + return Single.error(new Throwable("没找到客服")); + } + String account = ""; + for (int i = 0; i < serviceInfo.getServices().size(); i++) { + if (serviceInfo.getServices().get(i).getType() == CustomServiceInfo.TYPE_ONLINE) { + account = serviceInfo.getServices().get(i).getUid(); + } + } + if (TextUtils.isEmpty(account)) { + return Single.error(new Throwable("没找到对应的联系方式")); + } + + return Single.just(account); + + } + + /** + * 获取家族广场banner数据 + * + * @return + */ + public Single> loadBannerDate() { + return FamilyModel.Instance().loadFamilyBanner() + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + + } + + /** + * 显示客服信息 + * + * @return + */ + public Single showCustomerServiceInfo() { + return FamilyModel.Instance().loadFamilyCustomServiceInfo() + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/FindFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/FindFragmentPresenter.java new file mode 100644 index 000000000..787fd9912 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/FindFragmentPresenter.java @@ -0,0 +1,135 @@ +package com.yizhuan.erban.home.presenter; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IFindFragmentView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.home.bean.FindInfo; +import com.yizhuan.xchat_android_core.home.bean.TopMessage; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessage; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessageInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/5/22 + */ + +public class FindFragmentPresenter extends BaseMvpPresenter { + + private FindInfo findInfo; + + public FindInfo getFindInfo() { + return findInfo; + } + + public FindFragmentPresenter() { + + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + } + + public void loadData() { + long uid = AuthModel.get().getCurrentUid(); + if (uid <= 0) { + onLoadFindPageDataFail("没找到uid"); + return; + } + HomeModel.get().loadFindPageV2(String.valueOf(uid)) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FindInfo findInfo) { + onLoadFindPageData(findInfo); + } + + @Override + public void onError(Throwable e) { + onLoadFindPageDataFail(e.getMessage()); + } + }); + + } + + + private void onLoadFindPageData(FindInfo findInfo) { + this.findInfo = findInfo; + if (getMvpView() != null) { + getMvpView().onLoadData(findInfo); + } + } + + + private void onLoadFindPageDataFail(String error) { + if (getMvpView() != null) { + getMvpView().onLoadDataFail(error); + } + } + +// @SuppressLint("CheckResult") +// public void loadNewerList() { +// HomeModel.get().loadNewUserList("1", "3") +// .compose(bindUntilEvent(PresenterEvent.DESTROY)) +// .subscribe((userInfoList, throwable) -> { +// if (throwable == null) { +// getMvpView().onLoadNewUserList(userInfoList); +// } else { +// getMvpView().onLoadDataFail(throwable.getMessage()); +// } +// }); +// } + + /** + * 把服务器返回的model 数据转换成 需要显示的 ViewModel + * + * @return + */ + public VMTopMessageInfo transformHomeData2TopMessageInfos(List topMessages) { + if (ListUtils.isListEmpty(topMessages)) { + return null; + } + VMTopMessageInfo topMessageInfo = new VMTopMessageInfo(); + topMessageInfo.setTitle("轻寻头条"); + List vmTopMessageList = new ArrayList<>(); + //组装成2个2个一组 + final int groupSize = 2; + VMTopMessage vmTopMessage = null; + final int maxSize = topMessages.size() <= 6 ? topMessages.size() : 6; + for (int i = 0; i < maxSize; i++) { + if ((i % groupSize) == 0) { + vmTopMessage = new VMTopMessage(); + vmTopMessage.setTopMessageList(new ArrayList<>()); + vmTopMessageList.add(vmTopMessage); + } + if (vmTopMessage != null) { + vmTopMessage.getTopMessageList().add(topMessages.get(i)); + } + } + topMessageInfo.setVmTopMessageList(vmTopMessageList); + return topMessageInfo; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/FindTabFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/FindTabFragmentPresenter.java new file mode 100644 index 000000000..e920571e9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/FindTabFragmentPresenter.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IFindTabFragmentView; + +public class FindTabFragmentPresenter extends BaseMvpPresenter { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/HottestKTVRoomFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/HottestKTVRoomFragmentPresenter.java new file mode 100644 index 000000000..7e18e9e0d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/HottestKTVRoomFragmentPresenter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.home.view.IHottestKTVRoomFragmentView; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; +import com.yizhuan.xchat_android_core.home.model.HomeModel; + +import java.util.List; + +import io.reactivex.Single; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public class HottestKTVRoomFragmentPresenter extends BaseMvpPresenter + implements LoadPageDataHelper.LoadData> { + + LoadPageDataHelper> loadPageDataHelper; + + public HottestKTVRoomFragmentPresenter() { + loadPageDataHelper = new LoadPageDataHelper<>(this); + } + + + @Override + public Single> loadData(int curPage) { + return HomeModel.get().loadKTVList(String.valueOf(curPage), String.valueOf(10), String.valueOf(2)) + .compose(bindToLifecycle()); + } + + public Single> refreshData() { + return loadPageDataHelper.refreshData(); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/KTVFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/KTVFragmentPresenter.java new file mode 100644 index 000000000..2ca5fc0f0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/KTVFragmentPresenter.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IKTVFragmentView; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public class KTVFragmentPresenter extends BaseMvpPresenter { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/MainFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/MainFragmentPresenter.java new file mode 100644 index 000000000..f4f2aefc1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/MainFragmentPresenter.java @@ -0,0 +1,340 @@ +package com.yizhuan.erban.home.presenter; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IMainFragmentView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.family.bean.HomeBannerInfo; +import com.yizhuan.xchat_android_core.home.bean.TagListInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.market_verify.event.MarketVerifyUpdateEvent; +import com.yizhuan.xchat_android_core.miniworld.model.MiniWorldModel; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomResult; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; + +/** + * @author jiajie + * @Description + * @Date 2018/4/13 + */ + +public class MainFragmentPresenter extends BaseMvpPresenter { + + + private final static String TAG = MainFragmentPresenter.class.getSimpleName(); + + public static final int OPEN_ROOM_SUCCESS = 1; + public static final int OPEN_ROOM_FAIL_TYPE_IN_ROOM = 2; + public static final int OPEN_ROOM_FAIL = 3; + public static final int OPEN_ROOM_FAIL_ALREADY_OPENED_ROOM = 4; + /** + * 青少年限制时长的报错 + */ + public static final int OPEN_ROOM_FAIL_PM_LIMIT_TIME = 5; + + private int roomType = RoomInfo.ROOMTYPE_HOME_PARTY; + + private CompositeDisposable mCompositeDisposable; + + private final AvRoomModel avRoomModel; + + private Disposable mDisposable; + + public MainFragmentPresenter() { + avRoomModel = AvRoomModel.get(); + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + if (mCompositeDisposable == null) { + mCompositeDisposable = new CompositeDisposable(); + } + EventBus.getDefault().register(this); + } + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + EventBus.getDefault().unregister(this); + } + + + /** + * 开启房间 + */ + public void requestOpenRoom(int type) { + roomType = type; + AvRoomModel.get().requestRoomInfoV2(String.valueOf(AuthModel.get().getCurrentUid()), 0) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(RoomInfo roomInfo, Throwable throwable) { + super.acceptThrowable(roomInfo, throwable); + if (roomInfo != null) { + onGetRoomInfo(roomInfo); + } else { + if (throwable instanceof PmRoomLimitException) { + if (getMvpView() != null) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL_PM_LIMIT_TIME, + throwable.getMessage()); + } + } else if (!TextUtils.isEmpty(throwable.getMessage())) { + if (getMvpView() != null) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL, + throwable.getMessage()); + } + } + } + } + }); + + } + + /** + * 请求退出房间 + */ + public void requestExitRoom(int type) { + if (roomType != type) { + requestCloseRoom(type); + return; + } + roomType = type; + avRoomModel.exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + openRoom(); + } + + @Override + public void onFail(int code, String error) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL, error); + } + }); + + } + + /** + * 请求关闭房间 + */ + private void requestCloseRoom(int type) { + roomType = type; + AvRoomModel.get() + .quitRoomForOurService(new CallBack() { + @Override + public void onSuccess(String data) { + onCloseRoomInfo(); + } + + @Override + public void onFail(int code, String error) { + onCloseRoomInfoFail(error); + } + }); + } + + @SuppressLint("CheckResult") + private void openRoom() { + AvRoomModel.get().openRoom( + AuthModel.get().getCurrentUid(), roomType, null, null, null, null) + .compose(bindToLifecycle()) + .subscribe((roomResult, throwable) -> { + if (throwable != null) { + onOpenRoomFail(throwable.getMessage()); + } else if (roomResult != null && roomResult.isSuccess()) { + onOpenRoom(roomResult.getData()); + } else if (roomResult != null && !roomResult.isSuccess()) { + if (roomResult.getCode() == 1500) { + onAlreadyOpenedRoom(roomResult.getData()); + } else { + onOpenRoomFail(roomResult.getError()); + } + } else { + onOpenRoomFail("未知错误"); + } + }); + } + + private void onGetRoomInfo(RoomInfo roomInfo) { + if (roomInfo != null) { + if (roomInfo.isValid()) { + if (roomInfo.getType() != roomType) { + requestCloseRoom(roomType); + } else { + getMvpView().requestOpenRoomResult(OPEN_ROOM_SUCCESS, roomInfo); + } + } else { + openRoom(); + } + + } else { + openRoom(); + } + } + + @Override + public IMainFragmentView getMvpView() { + if (super.getMvpView() == null) { + return new IMainFragmentView.FakeIMainFragmentView(); + } else { + return super.getMvpView(); + } + } + + private void onCloseRoomInfoFail(String error) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL, error); + } + + private void onCloseRoomInfo() { + openRoom(); + } + + private void onOpenRoom(RoomInfo roomInfo) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_SUCCESS, roomInfo); + } + + private void onOpenRoomFail(String error) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL, error); + } + + private void onAlreadyOpenedRoom(RoomInfo roomInfo) { + getMvpView().requestOpenRoomResult(OPEN_ROOM_FAIL_ALREADY_OPENED_ROOM, roomInfo); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMarketVerifyUpdateEvent(MarketVerifyUpdateEvent event) { + getMvpView().showByMarketCheckingStatus(new ArrayList<>()); + } + + public void tagList() { + HomeModel.get().tagList(AuthModel.get().getCurrentUid()) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List tagListInfoList) { + IMainFragmentView iMainFragmentView = getMvpView(); + if (iMainFragmentView != null) + iMainFragmentView.titleListSuccess(tagListInfoList); + + } + + @Override + public void onError(Throwable e) { + IMainFragmentView iMainFragmentView = getMvpView(); + if (iMainFragmentView != null) + iMainFragmentView.titleListFail(e.getMessage()); + + } + }); + } + + public Single> getAttentionList() { + return AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + 1, + 100) + .flatMap(attentionInfos -> { + if (attentionInfos != null) { + Iterator iterator = attentionInfos.iterator(); + while (iterator.hasNext()) { + if (iterator.next().getUserInRoom() == null) { + iterator.remove(); + } + } + if (attentionInfos.size() > 20) { + attentionInfos = attentionInfos.subList(0, 20); + attentionInfos.add(new AttentionInfo()); + } + } + return Single.just(attentionInfos); + }); + } + + /** + * 获取首页banner和tab + */ + public void getHomeBannerInfo() { + if (mDisposable != null && !mDisposable.isDisposed()) { + return; + } + mDisposable = HomeModel.get() + .getQxBannerInfo() + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new BiConsumer() { + @Override + public void accept(HomeBannerInfo homeBannerInfo, Throwable throwable) throws Exception { + if (throwable == null) { + getMvpView().onGetFirstPageBannerSucceeded(homeBannerInfo); + } else { + getMvpView().onGetFirstPageBannerFailed(throwable.getMessage()); + } + } + }); + mCompositeDisposable.add(mDisposable); + } + + public void uploadAddress(long uid, String address, int adcode, double longitude, double latitude) { + Disposable disposable = HomeModel.get().uploadAddress(uid, address, adcode, longitude, latitude).compose(bindUntilEvent(PresenterEvent.DESTROY)).subscribe(new BiConsumer() { + + @Override + public void accept(Object o, Throwable throwable) throws Exception { + + } + }); + } + + public void roomWorldModeClose(long roomUid) { + MiniWorldModel.getInstance().roomWorldModeClose(roomUid).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.roomWorldModeCloseFail(error); + + } + + @Override + public void onSuccess(String s) { + if (mMvpView != null) + mMvpView.roomWorldModeCloseSuccess(); + + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/MainPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/MainPresenter.java new file mode 100644 index 000000000..2fe95c235 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/MainPresenter.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IMainView; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +/** + *

+ * + * @author jiahui + * @date 2017/12/12 + */ +public class MainPresenter extends BaseMvpPresenter { + private final AvRoomModel mAvRoomMode; + + public MainPresenter() { + mAvRoomMode = AvRoomModel.get(); + } + + public void exitRoom() { + mAvRoomMode.exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + if (getMvpView() != null) { + getMvpView().exitRoom(data); + } + } + + @Override + public void onFail(int code, String error) { + + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/NewUserListPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/NewUserListPresenter.java new file mode 100644 index 000000000..0fc7843a9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/NewUserListPresenter.java @@ -0,0 +1,55 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.home.view.INewUserListActivityView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.base.PresenterEvent; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleEmitter; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public class NewUserListPresenter extends BaseMvpPresenter + implements LoadPageDataHelper.LoadData> { + + LoadPageDataHelper> loadPageDataHelper; + + public NewUserListPresenter() { + loadPageDataHelper = new LoadPageDataHelper<>(this); + } + + + @Override + public Single> loadData(int curPage) { + return HomeModel.get().loadNewUserList( + String.valueOf(curPage), + String.valueOf(Constants.PAGE_SIZE) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + + public Single> refreshData() { + return loadPageDataHelper.refreshData() + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData() + .compose(bindUntilEvent(PresenterEvent.DESTROY)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/NewestKTVRoomFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/NewestKTVRoomFragmentPresenter.java new file mode 100644 index 000000000..0b79eb55e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/NewestKTVRoomFragmentPresenter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.home.view.INewestKTVRoomFragmentView; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; +import com.yizhuan.xchat_android_core.home.model.HomeModel; + +import java.util.List; + +import io.reactivex.Single; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public class NewestKTVRoomFragmentPresenter extends BaseMvpPresenter + implements LoadPageDataHelper.LoadData> { + + LoadPageDataHelper> loadPageDataHelper; + + public NewestKTVRoomFragmentPresenter() { + loadPageDataHelper = new LoadPageDataHelper<>(this); + } + + + @Override + public Single> loadData(int curPage) { + return HomeModel.get().loadKTVList(String.valueOf(curPage), String.valueOf(10), String.valueOf(1)) + .compose(bindToLifecycle()); + } + + public Single> refreshData() { + return loadPageDataHelper.refreshData(); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/RecommendFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/RecommendFragmentPresenter.java new file mode 100644 index 000000000..94c142f19 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/RecommendFragmentPresenter.java @@ -0,0 +1,764 @@ +package com.yizhuan.erban.home.presenter; + +import android.os.Bundle; +import android.os.Parcelable; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IRecommendFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeImpDataType; +import com.yizhuan.xchat_android_core.home.bean.HomeInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.KTVRoom; +import com.yizhuan.xchat_android_core.home.bean.KTVRoomInfo; +import com.yizhuan.xchat_android_core.home.bean.MakeFriendsInfo; +import com.yizhuan.xchat_android_core.home.bean.RecommendInfo; +import com.yizhuan.xchat_android_core.home.bean.TopBannerInfo; +import com.yizhuan.xchat_android_core.home.bean.TopMessage; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessage; +import com.yizhuan.xchat_android_core.home.bean.VMTopMessageInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GameRespondAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; +import com.yizhuan.xchat_android_core.level.UserLevelResourceType; +import com.yizhuan.xchat_android_core.market_verify.event.MarketVerifyUpdateEvent; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterProtocol; +import com.yizhuan.xchat_android_core.monsterhunting.model.MonsterHuntingModel; +import com.yizhuan.xchat_android_core.monsterhunting.rxevent.MonsterUpdateEvent; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public class RecommendFragmentPresenter extends BaseMvpPresenter { + + private final static String TAG = RecommendFragmentPresenter.class.getSimpleName(); + + private List mHomeItemList; + /** + * 用于保存热门推荐的房间 + */ + private List hotList = new ArrayList<>(); + + /** + * 热门标签 + */ + private HomeItem hotTitleItem = new HomeItem<>(HomeItem.TYPE_BLOCK_TITLE); + + private List homeInfos; + private int mPage = Constants.PAGE_START; + private CompositeDisposable mCompositeDisposable; + + public RecommendFragmentPresenter() { + + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + LogUtil.d(TAG, "onSaveInstanceState~~"); + if (!ListUtils.isListEmpty(mHomeItemList)) { + outState.putParcelableArrayList(Constants.KEY_HOME_LIST, (ArrayList) mHomeItemList); + } + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + LogUtil.d(TAG, "onCreatePresenter~~"); + if (saveState != null) { + mHomeItemList = saveState.getParcelableArrayList(Constants.KEY_HOME_LIST); + } + if (mCompositeDisposable == null) { + mCompositeDisposable = new CompositeDisposable(); + } + addRxBusEvent(); + EventBus.getDefault().register(this); + } + + /** + * 添加RXBus 事件 + */ + private void addRxBusEvent() { + RxBusHelper.doOnMainThread(MonsterUpdateEvent.class, mCompositeDisposable, new Consumer() { + @Override + public void accept(MonsterUpdateEvent monsterUpdateEvent) throws Exception { + syncMonsterData(monsterUpdateEvent.getMonsterList()); + } + }); + } + + + @Override + public void onDestroyPresenter() { + super.onDestroyPresenter(); + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + EventBus.getDefault().unregister(this); + } + + + /** + * 获取首页数据 + */ + public void loadHomeData() { + String ticket = AuthModel.get().getTicket(); + if (TextUtils.isEmpty(ticket)) { + return; + } + HomeModel.get().loadHomeListV4( + String.valueOf(AuthModel.get().getCurrentUid()) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver>>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(ServiceResult> listServiceResult) { + if (listServiceResult.isSuccess()) { + onGetHomeDataSuccess(listServiceResult.getData()); + } else { + onGetHomeDataFail(listServiceResult.getError()); + } + } + + @Override + public void onError(Throwable e) { + onGetHomeDataFail(e.getMessage()); + } + + }); + } + + /** + * 获取首页分页数据 + */ + public void loadMoreHomeData() { + String ticket = AuthModel.get().getTicket(); + if (TextUtils.isEmpty(ticket)) { + return; + } + HomeModel.get().loadMoreHomeData(mPage, 15) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + getMvpView().addHomeDataFail(error); + } + + @Override + public void onSuccess(List list) { + if (list.size() == 0) { + getMvpView().onNoMoreHomeData(); + return; + } + + //兼容后台首页热门数据不够3个,但是翻页加载第二页却有数据 + //据说是后台缓存导致 + if (mHomeItemList == null) { + return; + } + //将热门项移除先 + List notHotList = new ArrayList<>(); + for (HomeItem index : mHomeItemList) { + if (!index.isHotItem()) { + notHotList.add(index); + } + } + mHomeItemList.clear(); + mHomeItemList.addAll(notHotList); + + //先移除热门项的虚位以待 + List notRemoveList = new ArrayList<>(); + for(HomeItem item : hotList) { + if (item.getItemType() != HomeItem.TYPE_SQUARE_EMPTY) { + notRemoveList.add(item); + } + } + hotList.clear(); + hotList.addAll(notRemoveList); + + //把加载到的数据添加hotlist + for(HomeRoom item : list) { + HomeItem homeItem; + if (hotList.size() < 3) { + homeItem = new HomeItem<>( + HomeItem.TYPE_SQUARE_PIC, item, true); + } else { + homeItem = new HomeItem<>( + HomeItem.TYPE_LINEAR_LITTLE_PIC, item, true); + } + hotList.add(homeItem); + } + //计算要添加的虚位以待 + if (hotList.size() >= 1 && hotList.size() < 3) { + int emptyNum = 3 - hotList.size(); + for (int i = 0; i < emptyNum; i++) { + HomeItem emptyItem = new HomeItem<>( + HomeItem.TYPE_SQUARE_EMPTY, new HomeRoom(), true); + hotList.add(emptyItem); + } + } + for (int i = 0; i < hotList.size(); i++) { + if (i < 3) { + hotList.get(i).setDividerDesc(i); + } else if (i == hotList.size() - 1) { + hotList.get(i).setDividerDesc(-2); + } else { + hotList.get(i).setDividerDesc(-1); + } + } + + if (!mHomeItemList.contains(hotTitleItem)) { + mHomeItemList.add(hotTitleItem); + } + mHomeItemList.addAll(hotList); + getMvpView().addHomeDataSuccess(hotList); + mPage++; + } + }); + } + + /** + * 首页数据成功 + * + * @param homeInfoList + */ + private void onGetHomeDataSuccess(List homeInfoList) { + if (!ListUtils.isListEmpty(homeInfoList)) { + if (!ListUtils.isListEmpty(mHomeItemList)) { + mHomeItemList.clear(); + } + if (mHomeItemList == null) { + mHomeItemList = new ArrayList<>(); + } + hotList.clear(); + transformHomeData(homeInfoList); + getMvpView().loadHomeDataSuccess(mHomeItemList); + //3.1.2之后推荐页不显示怪兽 + //MonsterHuntingModel.get().getMonsterList("", AuthModel.get().getTicket()); + } else { + getMvpView().onNoHomeData(); + } + } + + /** + * 刷新交友的房间列表 + */ + public void refreshMakeFriendList() { + HomeModel.get().loadMakeFriendList() + .compose(RxHelper.handleBeanData()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List roomList) { + setToHomeItemList(roomList); + } + + @Override + public void onError(Throwable e) { + getMvpView().onRefreshMakeFriendListFail(e.getMessage()); + } + }); + + } + + private void setToHomeItemList(List roomList) { + HomeItem makeFriendsInfoHomeItem = findHomeItemByType(HomeItem.TYPE_MAKE_FRIENDS); + if (makeFriendsInfoHomeItem == null) { + return; + } + MakeFriendsInfo makeFriendsInfo = (MakeFriendsInfo) makeFriendsInfoHomeItem.getData(); + if (makeFriendsInfo == null) { + return; + } + makeFriendsInfo.setVmIsLoading(false); + makeFriendsInfo.setRoomList(roomList); + int position = mHomeItemList.indexOf(makeFriendsInfoHomeItem); + + getMvpView().notifyDataSetChanged(IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, position, null); + + } + + @Nullable + private HomeItem findHomeItemByType(int type) { + for (HomeItem homeItem : this.mHomeItemList) { + if (homeItem.getItemType() == type) { + return homeItem; + } + } + return null; + } + + private void removeEmptyHomeItem() { + Iterator iterator = this.mHomeItemList.iterator(); + while (iterator.hasNext()) { + HomeItem homeItem = iterator.next(); + if (null == homeItem.getData() + && homeItem.getItemType() != HomeItem.TYPE_DIV_1 + && homeItem.getItemType() != HomeItem.TYPE_DIV_2) { + iterator.remove(); + } + } + + } + + /** + * 转换成我们的viewModel + * + * @param homeInfoList + */ + private void transformHomeData(List homeInfoList) { + + if (null == this.mHomeItemList) { + return; + } + if (null == homeInfoList) { + return; + } + //banner + mHomeItemList.add(new HomeItem>(HomeItem.TYPE_BANNER)); + //因为可配置模块不止1个,并且位置一定要在墙裂推荐和热门推荐之间 + //所以可配置模块独立获取 + List configList = new ArrayList<>(); + //热门推荐 + hotList.clear(); + this.homeInfos = homeInfoList; + for (HomeInfo homeInfo : homeInfoList) { + if (null == homeInfo) continue; + if (homeInfo.getType() == HomeItem.TYPE_BANNER) { + //top Banner + HomeItem> topBannerInfoHomeItem = findHomeItemByType(HomeItem.TYPE_BANNER); + ArrayList topBannerInfoList = new Gson().fromJson(homeInfo.getData(), + new TypeToken>() { + }.getType()); + if (!ListUtils.isListEmpty(topBannerInfoList)) { + topBannerInfoHomeItem.setData(topBannerInfoList); + } + + } else if (homeInfo.getType() == HomeItem.TYPE_TOP_MESSAGE) { + //轻寻头条数据 + //3.1.2开始不处理 + } else if (homeInfo.getType() == HomeItem.TYPE_RECOMMEND || + homeInfo.getType() == HomeItem.TYPE_CONFIG) { + //此版本推荐和可配置模块,数据和ui都一样,所以一起处理 + HomeItem titleItem = new HomeItem<>(HomeItem.TYPE_BLOCK_TITLE, + homeInfo.getTitle()); + List tmpList = handleSubListToMainList(homeInfo, -1, false); + + if (!ListUtils.isListEmpty(tmpList)) { + + // 推荐位第三个位置展示半小时榜图标 + if (homeInfo.getType() == HomeItem.TYPE_RECOMMEND && tmpList.size() >= 3) { + tmpList.get(2).setShowRankHalfIcon(true); + } + + configList.add(titleItem); + configList.addAll(tmpList); + } + } else if (homeInfo.getType() == HomeItem.TYPE_KTV) { + //KTV 房间列表 + //3.1.2开始不处理 + } else if (homeInfo.getType() == HomeItem.TYPE_HALL) { + //交友的大厅 + + } else if (homeInfo.getType() == HomeItem.TYPE_MAKE_FRIENDS) { + //佛系交友大厅 + //3.1.2开始不处理 + } else if (homeInfo.getType() == HomeImpDataType.HOT) { + hotTitleItem.setData(homeInfo.getTitle()); + hotList.addAll(handleSubListToMainList(homeInfo, 3, true)); + } + + } + + + /**************************************************************************/ + + //移除没内容的块 + removeEmptyHomeItem(); + + //添加可配置模块 + mHomeItemList.addAll(configList); + + //添加热门 + //为了兼容后台,热门第一页没数据,第二页居然有数据的骚操作 + //客户端进行兼容 + if (hotList.size() > 0) { + //添加标题 + if (TextUtils.isEmpty(hotTitleItem.getData())) { + hotTitleItem.setData("热门推荐"); + } + mHomeItemList.add(hotTitleItem); + mHomeItemList.addAll(hotList); + } + } + + + /** + * 由于接口的数据是分模块返回的, + * 所以将模块的数据处理后,合成一条list + */ + private List handleSubListToMainList(HomeInfo homeInfo, int customSquareNum, boolean isHot) { + List resultList = new ArrayList<>(); + if (null != homeInfo.getData() && homeInfo.getData().isJsonArray() + && homeInfo.getData().getAsJsonArray().size() > 0) { + //判断不为空 + List homeRoomList = new Gson().fromJson(homeInfo.getData(), + new TypeToken>() { + }.getType()); + if (homeRoomList == null) { + homeRoomList = new ArrayList<>(); + + } + int maxNum; + //表示方格子的个数,如果不足3的倍数,则补足3的倍数 + //处理热门数据,前三个为格子,其他为普通布局,如果不足三个,则补虚位以待 + if (customSquareNum >= 0) { + maxNum = customSquareNum; + } else { + maxNum = homeInfo.getMaxNum(); + } + List squareList = new ArrayList<>(); + List linearList = new ArrayList<>(); + + for (int i = 0; i < homeRoomList.size(); i++) { + HomeItem item; + HomeRoom room = homeRoomList.get(i); + if (i < maxNum) { + item = new HomeItem<>(HomeItem.TYPE_SQUARE_PIC, room, isHot); + squareList.add(item); + } else { + item = new HomeItem<>(HomeItem.TYPE_LINEAR_LITTLE_PIC, room, isHot); + linearList.add(item); + } + } + //添加虚位以待 + int needEmptySize; + if (squareList.size() == 0) { + //如果方形推荐位为空,添加3个虚位以待 + //如果方块列表为空,maxnum = 0,不配置虚位以待 + needEmptySize = 0; + } else if (squareList.size() % 3 == 0) { + //如果刚好是3的倍数,则不需要添加 + needEmptySize = 0; + } else { + //其余情况补足 + needEmptySize = 3 - squareList.size() % 3; + } + //添加虚位以待 + if (needEmptySize > 0) { + for (int i = 0; i < needEmptySize; i++) { + HomeItem item = new HomeItem<>(HomeItem.TYPE_SQUARE_EMPTY, new HomeRoom(), isHot); + squareList.add(item); + } + } + //加个防错机制,保证方形是3的倍数 + while (squareList.size() % 3 != 0) { + if (squareList.size() > 0) { + squareList.remove(squareList.size() - 1); + } + } + //添加分割线 + for (int i = 0; i < squareList.size(); i++) { + squareList.get(i).setDividerDesc(i % 3); + } + //分割线 + for (int i = 0; i < linearList.size(); i++) { + if (i == linearList.size() - 1) { + linearList.get(i).setDividerDesc(-2); + } else { + linearList.get(i).setDividerDesc(-1); + } + } + resultList.addAll(squareList); + resultList.addAll(linearList); + } + return resultList; + } + + /** + * 整理推荐数据 + * + * @param homeRoomList + */ + private void handleErbanRoomList(List homeRoomList) { + if (ListUtils.isListEmpty(homeRoomList)) { + return; + } + //做下简单的数据处理,对前3项特别处理 + for (int i = 0; i < homeRoomList.size(); i++) { + if (i < 3) { + homeRoomList.get(i).setItemStarType(HomeRoom.TYPE_GIRD); + } else { + homeRoomList.get(i).setItemStarType(HomeRoom.TYPE_LINEAR); + } + } + //不足三项的情况下,添加虚位以待的格子 + if (homeRoomList.size() > 0 && homeRoomList.size() < 3) { + List emptyList = new ArrayList<>(); + for (int i = 0; i < (3 - homeRoomList.size()); i++) { + HomeRoom homeRoom = new HomeRoom(); + homeRoom.setItemStarType(HomeRoom.TYPE_GIRD_EMPTY); + emptyList.add(homeRoom); + } + homeRoomList.addAll(emptyList); + } + } + + /** + * 把服务器返回的model 数据转换成 需要显示的 ViewModel + * + * @param homeInfo + * @return + */ + private VMTopMessageInfo transformHomeData2TopMessageInfos(HomeInfo homeInfo) { + List topMessages = new Gson().fromJson(homeInfo.getData(), new TypeToken>() { + }.getType()); + VMTopMessageInfo topMessageInfo = new VMTopMessageInfo(); + topMessageInfo.setTitle(homeInfo.getTitle()); + List vmTopMessageList = new ArrayList<>(); + //组装成2个2个一组 + final int groupSize = 2; + VMTopMessage vmTopMessage = null; + final int maxSize = topMessages.size() <= 6 ? topMessages.size() : 6; + for (int i = 0; i < maxSize; i++) { + if ((i % groupSize) == 0) { + vmTopMessage = new VMTopMessage(); + vmTopMessage.setTopMessageList(new ArrayList<>()); + vmTopMessageList.add(vmTopMessage); + } + if (vmTopMessage != null) { + vmTopMessage.getTopMessageList().add(topMessages.get(i)); + } + } + topMessageInfo.setVmTopMessageList(vmTopMessageList); + return topMessageInfo; + } + + /** + * 获取首页数据失败 + * + * @param error + */ + private void onGetHomeDataFail(String error) { + getMvpView().loadHomeDataFail(error); + } + + + public int getPage() { + return this.mPage; + } + + public void setPage(int page) { + this.mPage = page; + } + + public List getmHomeItemList() { + return mHomeItemList; + } + + + @Override + public IRecommendFragmentView getMvpView() { + if (super.getMvpView() == null) { + return new IRecommendFragmentView.FakeIMainFragmentView(); + } else { + return super.getMvpView(); + } + } + + + /** + * 同步怪兽数据 + * + * @param monsterList + */ + private void syncMonsterData(List monsterList) { + //查找更新怪兽,没有的话添加怪兽 + for (int i = 0; i < monsterList.size(); i++) { + MonsterProtocol.DataBean monsterSource = monsterList.get(i); + boolean isFindMonster = false; + for (int j = 0; j < mHomeItemList.size(); j++) { + HomeItem homeItem = mHomeItemList.get(j); + if (homeItem.getItemType() == HomeItem.TYPE_MONSTER) { + MonsterProtocol.DataBean monsterTarget = (MonsterProtocol.DataBean) homeItem.getData(); + if (monsterTarget.getMonsterId() == monsterSource.getMonsterId()) { + isFindMonster = true; + homeItem.setData(monsterSource); + break; + } + } + } + if (!isFindMonster) { + HomeItem homeItem = new HomeItem<>(HomeItem.TYPE_MONSTER); + homeItem.setData(monsterSource); + mHomeItemList.add(1, homeItem); + } + } + + //当前列表存在怪兽列表不存在的怪兽,移除该怪兽 + Iterator itemIterator = mHomeItemList.iterator(); + while (itemIterator.hasNext()) { + HomeItem homeItem = itemIterator.next(); + if (homeItem.getItemType() == HomeItem.TYPE_MONSTER) { + MonsterProtocol.DataBean monsterSource = (MonsterProtocol.DataBean) homeItem.getData(); + boolean isNeedRemove = true; + for (int i = 0; i < monsterList.size(); i++) { + MonsterProtocol.DataBean monsterTarget = monsterList.get(i); + if (monsterTarget.getMonsterId() == monsterSource.getMonsterId()) { + isNeedRemove = false; + break; + } + } + int position = mHomeItemList.indexOf(homeItem); + if (isNeedRemove) { + itemIterator.remove(); + getMvpView().notifyDataSetChanged(IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, IRecommendFragmentView.NOTIFY_DATA_SET_REMOVE, position); + } else { + getMvpView().notifyDataSetChanged(IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, position); + } + + + } + } + + + } + + + /** + * 列表中存在这个怪兽 + * + * @param data + * @return + */ + private boolean findMonster(MonsterProtocol.DataBean data) { + for (HomeItem homeItem : mHomeItemList) { + if (HomeItem.TYPE_MONSTER == homeItem.getItemType()) { + MonsterProtocol.DataBean monsterInfos = (MonsterProtocol.DataBean) homeItem.getData(); + if (monsterInfos.getMonsterId() == data.getMonsterId()) { + return true; + } + } + } + return false; + } + + /** + * 刷新头条消息,全部全服广播到来时候刷新 + */ + public void refreshTopMessageList() { + HomeModel.get().loadHomeListV4( + String.valueOf(AuthModel.get().getCurrentUid()) + ) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver>>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(ServiceResult> listServiceResult) { + if (listServiceResult.isSuccess()) { + updateTopMessages(listServiceResult.getData()); + } + } + + @Override + public void onError(Throwable e) { + } + + }); + } + + /** + * 更新头条信息 + * + * @param data + */ + private void updateTopMessages(List data) { + //新获取到首页排序与旧的不一致,直接刷新首页 + if (homeInfos == null || homeInfos.size() != data.size()) { + loadHomeData(); + return; + } + for (int i = 0; i < homeInfos.size(); i++) { + if (homeInfos.get(i).getType() != data.get(i).getType()) { + loadHomeData(); + return; + } + } + + //新获取到首页排序与旧的一致,更新头条数据 + VMTopMessageInfo vmTopMessageInfo = null; + for (HomeInfo datum : data) { + if (datum.getType() == HomeItem.TYPE_TOP_MESSAGE) { + vmTopMessageInfo = transformHomeData2TopMessageInfos(datum); + break; + } + } + if (null != vmTopMessageInfo) { + for (int i = 0; i < mHomeItemList.size(); i++) { + HomeItem homeItem = mHomeItemList.get(i); + if (homeItem.getItemType() == HomeItem.TYPE_TOP_MESSAGE) { + homeItem.setData(vmTopMessageInfo); + getMvpView().notifyDataSetChanged(IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, IRecommendFragmentView.NOTIFY_DATA_SET_CHANGED, i); + break; + } + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMarketVerifyUpdateEvent(MarketVerifyUpdateEvent event) { + getMvpView().showByMarketCheckingStatus(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/RoomCategoryFragmentPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomCategoryFragmentPresenter.java new file mode 100644 index 000000000..eafdd1694 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomCategoryFragmentPresenter.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.home.presenter; + +import android.os.Bundle; +import android.os.Parcelable; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.view.IRoomCategoryFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public class RoomCategoryFragmentPresenter extends BaseMvpPresenter { + private static final String TAG = RoomCategoryFragmentPresenter.class.getSimpleName(); + + private List mTabInfoList; + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + if (saveState != null) { + mTabInfoList = saveState.getParcelableArrayList(Constants.KEY_MAIN_TAB_LIST); + }else{ + mTabInfoList = HomeModel.get().getmTabInfoList(); + + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (!ListUtils.isListEmpty(mTabInfoList)) { + outState.putParcelableArrayList(Constants.KEY_MAIN_TAB_LIST, (ArrayList) mTabInfoList); + } + } + + public List getTabInfoList() { + return this.mTabInfoList; + } + + /** + * 从服务器获取房间分类列表 + */ + public void loadTabInfoList() { + HomeModel.get().getMainTabData() + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List tabInfos) { + mTabInfoList = tabInfos; + getMvpView().initiate(); + } + + @Override + public void onError(Throwable e) { + //获取不到 + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/RoomListPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomListPresenter.java new file mode 100644 index 000000000..cf3ef7a0d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomListPresenter.java @@ -0,0 +1,87 @@ +package com.yizhuan.erban.home.presenter; + +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.home.view.IRoomListFragmentView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.ClassifiedRoomInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +/** + * @author jack + * @Description + * @Date 2018/11/2 + */ +public class RoomListPresenter extends BaseMvpPresenter + implements LoadPageDataHelper.LoadData> { + + private LoadPageDataHelper> loadPageDataHelper; + + private TabInfo tabInfo; + + public RoomListPresenter() { + loadPageDataHelper = new LoadPageDataHelper<>(this); + } + + public void setTabInfo(TabInfo tabInfo) { + this.tabInfo = tabInfo; + } + + @Override + public Single> loadData(int curPage) { + if (tabInfo == null) { + return Single.error(new Throwable("没找到房间类型")); + } + return HomeModel.get().getMainDataByTab(tabInfo.getId(), curPage, Constants.PAGE_SIZE) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(ClassifiedRoomInfo classifiedRoomInfo) throws Exception { + List list = new ArrayList<>(); + List homeRooms = classifiedRoomInfo.getRooms(); + + if (!ListUtils.isListEmpty(homeRooms)) { + for (HomeRoom homeRoom : homeRooms) { + list.add(new HomeRoomItem<>(HomeRoomItem.TYPE_HOME_ROOM, homeRoom)); + } + } + if (!ListUtils.isListEmpty(classifiedRoomInfo.getBanners()) && curPage == Constants.PAGE_START) { + if (list.size() <= 4) { + list.add(new HomeRoomItem<>(HomeRoomItem.TYPE_BANNER, classifiedRoomInfo.getBanners())); + } else { + list.add(4, new HomeRoomItem<>(HomeRoomItem.TYPE_BANNER, classifiedRoomInfo.getBanners())); + } + } + + if (ListUtils.isListEmpty(list)) { + return Single.just(new ArrayList<>()); + } else { + return Single.just(list); + } + } + }); + } + + public Single> refreshData() { + return loadPageDataHelper.refreshData(); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/presenter/RoomTabPresenter.java b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomTabPresenter.java new file mode 100644 index 000000000..edd180795 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/presenter/RoomTabPresenter.java @@ -0,0 +1,106 @@ +package com.yizhuan.erban.home.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.helper.LoadPageDataHelper; +import com.yizhuan.erban.home.view.IRoomTabView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.HomeRoomItem; +import com.yizhuan.xchat_android_core.home.bean.TitleIndexInfo; +import com.yizhuan.xchat_android_core.home.model.HomeModel; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +public class RoomTabPresenter extends BaseMvpPresenter implements LoadPageDataHelper.LoadData> { + + private LoadPageDataHelper> loadPageDataHelper; + + private long mTitleId = -1; + + public RoomTabPresenter() { + loadPageDataHelper = new LoadPageDataHelper<>(this); + } + + public void setmTitleId(long titleId) { + this.mTitleId = titleId; + } + + @Override + public Single> loadData(int curPage) { + if (mTitleId < 0) { + return Single.error(new Throwable("没找到房间类型")); + } + + return HomeModel.get().titleIndex(mTitleId, curPage, Constants.PAGE_SIZE) + .compose(bindToLifecycle()) + .flatMap(new Function>>() { + @Override + public SingleSource> apply(TitleIndexInfo classifiedRoomInfo) throws Exception { + List list = new ArrayList<>(); + List homeRooms = classifiedRoomInfo.getRooms(); + + if (!ListUtils.isListEmpty(homeRooms)) { + + if (curPage == Constants.PAGE_START) { + + // 空白占位 + list.add(new HomeRoomItem<>(HomeRoomItem.TYPE_TOP_EMPTY, null)); + + int topThree = 0; + ArrayList roomList = new ArrayList<>(); + while (homeRooms.size() > 0 && topThree < 3) { + HomeRoom homeRoom = homeRooms.remove(0); + homeRoom.setItemStarType(HomeRoom.TYPE_GIRD); + roomList.add(homeRoom); + topThree++; + } + + while (roomList.size() < 3) { + HomeRoom homeRoom = new HomeRoom(); + homeRoom.setItemStarType(HomeRoom.TYPE_GIRD_EMPTY); + roomList.add(homeRoom); + } + + list.add(new HomeRoomItem<>(HomeRoomItem.TYPE_TOP_THREE, roomList)); + + } + + for (HomeRoom homeRoom : homeRooms) { + list.add(new HomeRoomItem<>(HomeRoomItem.TYPE_HOME_ROOM, homeRoom)); + } + } + + if (!ListUtils.isListEmpty(classifiedRoomInfo.getBanner()) && curPage == Constants.PAGE_START) { + HomeRoomItem bannerItems = new HomeRoomItem<>(HomeRoomItem.TYPE_BANNER, classifiedRoomInfo.getBanner()); + if (list.size() <= 5) { + if (list.size() == 0) + bannerItems.setBannerInTop(true); + list.add(bannerItems); + } else { + list.add(5, bannerItems); + } + } + + if (ListUtils.isListEmpty(list)) { + return Single.just(new ArrayList<>()); + } else { + return Single.just(list); + } + } + }); + } + + public Single> refreshData() { + return loadPageDataHelper.refreshData(); + } + + public Single> loadMoreData() { + return loadPageDataHelper.loadMoreData(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameBase.java b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameBase.java new file mode 100644 index 000000000..32b763e7d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameBase.java @@ -0,0 +1,249 @@ +package com.yizhuan.erban.home.refresh; + +import android.content.Context; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +import com.scwang.smartrefresh.layout.api.RefreshContent; +import com.scwang.smartrefresh.layout.api.RefreshHeader; +import com.scwang.smartrefresh.layout.api.RefreshKernel; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.constant.RefreshState; +import com.scwang.smartrefresh.layout.constant.SpinnerStyle; + +import static android.view.MotionEvent.ACTION_MASK; + +/** + * 游戏 header + * Created by SCWANG on 2017/6/17. + */ + +public class FunGameBase extends FrameLayout implements RefreshHeader { + + // + protected int mOffset; + protected int mHeaderHeight; + protected int mScreenHeightPixels; + protected float mTouchY; + protected boolean mIsFinish; + protected boolean mLastFinish; + protected boolean mManualOperation; + protected RefreshState mState; + protected RefreshKernel mRefreshKernel; + protected RefreshContent mRefreshContent; + // + + // + public FunGameBase(Context context) { + super(context); + initView(context); + } + + public FunGameBase(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public FunGameBase(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + public FunGameBase(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initView(context); + } + + private void initView(Context context) { + mScreenHeightPixels = context.getResources().getDisplayMetrics().heightPixels; + } + + @Override + public void setTranslationY(float translationY) { + if (!isInEditMode()) { + super.setTranslationY(translationY); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return mState == RefreshState.Refreshing || super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mState == RefreshState.Refreshing || mState == RefreshState.RefreshFinish) { + if (!mManualOperation) { + onManualOperationStart(); + } + switch (event.getAction() & ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mTouchY = event.getRawY(); + mRefreshKernel.moveSpinner(0, true); + break; + case MotionEvent.ACTION_MOVE: + float dy = event.getRawY() - mTouchY; + if (dy >= 0) { + final double M = mHeaderHeight * 2; + final double H = mScreenHeightPixels * 2 / 3; + final double x = Math.max(0, dy * 0.5); + final double y = Math.min(M * (1 - Math.pow(100, -x / H)), x);// 公式 y = M(1-40^(-x/H)) + mRefreshKernel.moveSpinner((int) y, false); + } else { + final double M = mHeaderHeight * 2; + final double H = mScreenHeightPixels * 2 / 3; + final double x = -Math.min(0, dy * 0.5); + final double y = -Math.min(M * (1 - Math.pow(100, -x / H)), x);// 公式 y = M(1-40^(-x/H)) + mRefreshKernel.moveSpinner((int) y, false); + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + onManualOperationRelease(); + mTouchY = -1; + if (mIsFinish) { + mRefreshKernel.moveSpinner(mHeaderHeight, true); + } + break; + } + return true; + } + return super.onTouchEvent(event); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mRefreshKernel = null; + mRefreshContent = null; + } + + // + + // + boolean enableLoadmore; + + protected void onManualOperationStart() { + if (!mManualOperation) { + mManualOperation = true; + mRefreshContent = mRefreshKernel.getRefreshContent(); + enableLoadmore = mRefreshKernel.getRefreshLayout().isEnableLoadmore(); + mRefreshKernel.getRefreshLayout().setEnableLoadmore(false); + View contentView = mRefreshContent.getView(); + MarginLayoutParams params = (MarginLayoutParams) contentView.getLayoutParams(); + params.topMargin += mHeaderHeight; + contentView.setLayoutParams(params); + } + } + + protected void onManualOperationMove(float percent, int offset, int headHeight, int extendHeight) { + + } + + protected void onManualOperationRelease() { + if (mIsFinish) { + mManualOperation = false; + mRefreshKernel.getRefreshLayout().setEnableLoadmore(enableLoadmore); + if (mTouchY != -1) {//还没松手 + onFinish(mRefreshKernel.getRefreshLayout(), mLastFinish); + mRefreshKernel.setStateRefresingFinish(); + mRefreshKernel.animSpinner(0); +// mRefreshKernel.getRefreshLayout().finishRefresh(0); + } else { + mRefreshKernel.moveSpinner(mHeaderHeight, true); + } + View contentView = mRefreshContent.getView(); + MarginLayoutParams params = (MarginLayoutParams) contentView.getLayoutParams(); + params.topMargin -= mHeaderHeight; + contentView.setLayoutParams(params); + } else { + mRefreshKernel.moveSpinner(0, true); + } + } + // + + // + + @Override + public boolean isSupportHorizontalDrag() { + return false; + } + + @Override + public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) { + } + + @Override + public void onPullingDown(float percent, int offset, int headHeight, int extendHeight) { + if (mManualOperation) onManualOperationMove(percent, offset, headHeight, extendHeight); + else { + mOffset = offset; + setTranslationY(mOffset - mHeaderHeight); + } + } + + @Override + public void onReleasing(float percent, int offset, int headHeight, int extendHeight) { + onPullingDown(percent, offset, headHeight, extendHeight); + } + + @Override + public void onStartAnimator(RefreshLayout layout, int headHeight, int extendHeight) { + mIsFinish = false; + } + + @Override + public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) { + mState = newState; + } + + @Override + public void onInitialized(RefreshKernel kernel, int height, int extendHeight) { + mRefreshKernel = kernel; + mHeaderHeight = height; + setTranslationY(mOffset - mHeaderHeight); + kernel.requestHeaderNeedTouchEventWhenRefreshing(true); + } + + @Override + public int onFinish(RefreshLayout layout, boolean success) { + mLastFinish = success; + if (!mIsFinish) { + mIsFinish = true; + if (mManualOperation) { + if (mTouchY == -1) {//已经放手 + onManualOperationRelease(); + onFinish(layout, success); + return 0; + } + return Integer.MAX_VALUE; + } + } + return 0; + } + + @Override + @Deprecated + public void setPrimaryColors(@ColorInt int... colors) { + } + + @NonNull + @Override + public View getView() { + return this; + } + + @Override + public SpinnerStyle getSpinnerStyle() { + return SpinnerStyle.MatchLayout; + } + // +} diff --git a/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHeader.java b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHeader.java new file mode 100644 index 000000000..feedb4bea --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHeader.java @@ -0,0 +1,234 @@ +package com.yizhuan.erban.home.refresh; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.scwang.smartrefresh.header.R; +import com.scwang.smartrefresh.layout.api.RefreshHeader; +import com.scwang.smartrefresh.layout.api.RefreshKernel; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.util.ColorUtils; +import com.scwang.smartrefresh.layout.util.DensityUtil; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +/** + * 游戏 header + * Created by SCWANG on 2017/6/17. + */ + +public class FunGameHeader extends FunGameBase implements RefreshHeader { + + // + /** + * 分割线默认宽度大小 + */ + protected float DIVIDING_LINE_SIZE = 1.f; + + private RelativeLayout curtainReLayout, maskReLayout; + + private TextView topMaskView, bottomMaskView; + + private int halfHitBlockHeight; + + private boolean isStart = false; + + private String topMaskViewText = "下拉即将展开";//"Pull To Break Out!"; + private String bottomMaskViewText = "更多惊喜来临";//"Scrooll to move handle"; + + private int topMaskTextSize; + + private int bottomMaskTextSize; + + // + + // + public FunGameHeader(Context context) { + super(context); + this.initView(context, null); + } + + public FunGameHeader(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.initView(context, attrs); + } + + public FunGameHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.initView(context, attrs); + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + public FunGameHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + this.initView(context, attrs); + } + + private void initView(Context context, AttributeSet attrs) { + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FunGameHeader); + + if (ta.hasValue(R.styleable.FunGameHeader_fgvMaskTopText)) { + topMaskViewText = ta.getString(R.styleable.FunGameHeader_fgvMaskTopText); + } + if (ta.hasValue(R.styleable.FunGameHeader_fgvMaskBottomText)) { + bottomMaskViewText = ta.getString(R.styleable.FunGameHeader_fgvMaskBottomText); + } + + topMaskTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()); + bottomMaskTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()); + + topMaskTextSize = ta.getDimensionPixelSize(R.styleable.FunGameHeader_fgvBottomTextSize, topMaskTextSize); + bottomMaskTextSize = ta.getDimensionPixelSize(R.styleable.FunGameHeader_fgvBottomTextSize, bottomMaskTextSize); + + ta.recycle(); + + curtainReLayout = new RelativeLayout(context); + maskReLayout = new RelativeLayout(context); + maskReLayout.setBackgroundColor(Color.parseColor("#ffb606")); + + topMaskView = createMaskTextView(context, topMaskViewText, topMaskTextSize, Gravity.BOTTOM); + bottomMaskView = createMaskTextView(context, bottomMaskViewText, bottomMaskTextSize, Gravity.TOP); + + DIVIDING_LINE_SIZE = Math.max(1, DensityUtil.dp2px(0.5f)); + } + + + private TextView createMaskTextView(Context context, String text, int textSize, int gravity) { + TextView maskTextView = new TextView(context); + maskTextView.setTextColor(Color.parseColor("#999999")); + maskTextView.setBackgroundColor(Color.WHITE); + maskTextView.setGravity(gravity | Gravity.CENTER_HORIZONTAL); + maskTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + maskTextView.setText(text); + return maskTextView; + } + + private void coverMaskView() { + if (getChildCount() < 2 && !isInEditMode()) { + LayoutParams maskLp = new LayoutParams(MATCH_PARENT, mHeaderHeight); +// maskLp.topMargin = (int) FunGameView.DIVIDING_LINE_SIZE; +// maskLp.bottomMargin = (int) FunGameView.DIVIDING_LINE_SIZE; + + addView(maskReLayout, maskLp); + addView(curtainReLayout, maskLp); + + halfHitBlockHeight = (int) ((mHeaderHeight/* - 2 * DIVIDING_LINE_SIZE*/) * .5f); + RelativeLayout.LayoutParams topRelayLayoutParams = new RelativeLayout.LayoutParams(MATCH_PARENT, halfHitBlockHeight); + RelativeLayout.LayoutParams bottomRelayLayoutParams = new RelativeLayout.LayoutParams(MATCH_PARENT, halfHitBlockHeight); + bottomRelayLayoutParams.topMargin = mHeaderHeight - halfHitBlockHeight; + curtainReLayout.addView(topMaskView, topRelayLayoutParams); + curtainReLayout.addView(bottomMaskView, bottomRelayLayoutParams); + } + } + + private void doStart(long delay) { + ObjectAnimator topMaskAnimator = ObjectAnimator.ofFloat(topMaskView, "translationY", topMaskView.getTranslationY(), -halfHitBlockHeight); + ObjectAnimator bottomMaskAnimator = ObjectAnimator.ofFloat(bottomMaskView, "translationY", bottomMaskView.getTranslationY(), halfHitBlockHeight); + ObjectAnimator maskShadowAnimator = ObjectAnimator.ofFloat(maskReLayout, "alpha", maskReLayout.getAlpha(), 0); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(topMaskAnimator).with(bottomMaskAnimator).with(maskShadowAnimator); + animatorSet.setDuration(800); + animatorSet.setStartDelay(delay); + animatorSet.start(); + + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + topMaskView.setVisibility(View.GONE); + bottomMaskView.setVisibility(View.GONE); + maskReLayout.setVisibility(View.GONE); + onGameStart(); + } + }); + } + + protected void onGameStart() { + + } + + public void postStart() { + if (!isStart) { + doStart(200); + isStart = true; + } + } + + public void postEnd() { + isStart = false; + + topMaskView.setTranslationY(topMaskView.getTranslationY() + halfHitBlockHeight); + bottomMaskView.setTranslationY(bottomMaskView.getTranslationY() - halfHitBlockHeight); + maskReLayout.setAlpha(1.f); + + topMaskView.setVisibility(View.VISIBLE); + bottomMaskView.setVisibility(View.VISIBLE); + maskReLayout.setVisibility(View.VISIBLE); + } + + public void setTopMaskViewText(String topMaskViewText) { + this.topMaskViewText = topMaskViewText; + topMaskView.setText(topMaskViewText); + } + + public void setBottomMaskViewText(String bottomMaskViewText) { + this.bottomMaskViewText = bottomMaskViewText; + bottomMaskView.setText(bottomMaskViewText); + } + + // + + + @Override + @Deprecated + public void setPrimaryColors(@ColorInt int... colors) { + super.setPrimaryColors(colors); + if (colors.length > 0) { + // topMaskView.setTextColor(colors[0]); + // bottomMaskView.setTextColor(colors[0]); + if (colors.length > 1) { + maskReLayout.setBackgroundColor(ColorUtils.setAlphaComponent(colors[1], 200)); + topMaskView.setBackgroundColor(ColorUtils.setAlphaComponent(colors[1], 200)); + bottomMaskView.setBackgroundColor(ColorUtils.setAlphaComponent(colors[1], 200)); + } + } + } + + @Override + public void onInitialized(RefreshKernel kernel, int height, int extendHeight) { + super.onInitialized(kernel, height, extendHeight); + coverMaskView(); + } + + @Override + public void onStartAnimator(RefreshLayout layout, int headHeight, int extendHeight) { + super.onStartAnimator(layout, headHeight, extendHeight); + postStart(); + } + + @Override + public int onFinish(RefreshLayout layout, boolean success) { + if (!mManualOperation) { + postEnd(); + } + return super.onFinish(layout, success); + } + + // +} diff --git a/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHitBlockHeader.java b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHitBlockHeader.java new file mode 100644 index 000000000..dc786da69 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameHitBlockHeader.java @@ -0,0 +1,302 @@ +package com.yizhuan.erban.home.refresh; + + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Point; +import android.os.Build; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.util.AttributeSet; + +import com.scwang.smartrefresh.layout.util.ColorUtils; +import com.scwang.smartrefresh.layout.util.DensityUtil; +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Hitomis on 2016/2/29. + * email:196425254@qq.com + */ +public class FunGameHitBlockHeader extends FunGameView { + + /** + * 默认矩形块竖向排列的数目 + */ + private static final int BLOCK_VERTICAL_NUM = 5; + + /** + * 默认矩形块横向排列的数目 + */ + private static final int BLOCK_HORIZONTAL_NUM = 3; + + /** + * 矩形块的宽度占屏幕宽度比率 + */ + private static final float BLOCK_WIDTH_RATIO = .01806f; + + /** + * 挡板所在位置占屏幕宽度的比率 + */ + private static final float RACKET_POSITION_RATIO = .8f; + + /** + * 矩形块所在位置占屏幕宽度的比率 + */ + private static final float BLOCK_POSITION_RATIO = .08f; + + /** + * 小球默认其实弹射角度 + */ + private static final int DEFAULT_ANGLE = 30; + + /** + * 分割线默认宽度大小 + */ + static final float DIVIDING_LINE_SIZE = 1.f; + + /** + * 小球移动速度 + */ + private static final int SPEED = 3; + + /** + * 矩形砖块的高度、宽度 + */ + private float blockHeight, blockWidth; + + /** + * 小球半径 + */ + private float BALL_RADIUS; + + private Paint blockPaint; + + private float blockLeft, racketLeft; + + private float cx, cy; + + private List pointList; + + private boolean isleft; + + private int angle; + + private int blockHorizontalNum; + + private int speed; + + public FunGameHitBlockHeader(Context context) { + super(context); + initView(context, null); + } + + public FunGameHitBlockHeader(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context, attrs); + } + + public FunGameHitBlockHeader(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(context, attrs); + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + public FunGameHitBlockHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initView(context, attrs); + } + + private void initView(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FunGameHitBlockHeader); + blockHorizontalNum = typedArray.getInt(R.styleable.FunGameHitBlockHeader_fgvBlockHorizontalNum, BLOCK_HORIZONTAL_NUM); + speed = typedArray.getInt(R.styleable.FunGameHitBlockHeader_fgvBallSpeed, DensityUtil.dp2px(SPEED)); + typedArray.recycle(); + + blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + blockPaint.setStyle(Paint.Style.FILL); + BALL_RADIUS = DensityUtil.dp2px(4); + } + + @Override + protected void initConcreteView() { + + final int measuredWidth = getMeasuredWidth(); + controllerSize = (int) (blockHeight * 1.6f); + blockHeight = mHeaderHeight / BLOCK_VERTICAL_NUM - DIVIDING_LINE_SIZE; + blockWidth = measuredWidth * BLOCK_WIDTH_RATIO; + + blockLeft = measuredWidth * BLOCK_POSITION_RATIO; + racketLeft = measuredWidth * RACKET_POSITION_RATIO; + + controllerSize = (int) (blockHeight * 1.6f); + } + + @Override + protected void drawGame(Canvas canvas, int width, int height) { + drawColorBlock(canvas); + drawRacket(canvas); + if (status == STATUS_GAME_PLAY + || status == STATUS_GAME_FINISHED + || status == STATUS_GAME_FAIL + || isInEditMode()) { + makeBallPath(canvas, width); + } + } + + @Override + protected void resetConfigParams() { + cx = racketLeft - 3 * BALL_RADIUS; + cy = (int) (mHeaderHeight * .5f); + + controllerPosition = DIVIDING_LINE_SIZE; + + angle = DEFAULT_ANGLE; + + isleft = true; + + if (pointList == null) { + pointList = new ArrayList<>(); + } else { + pointList.clear(); + } + } + + /** + * 绘制挡板 + * + * @param canvas 默认画布 + */ + private void drawRacket(Canvas canvas) { + mPaint.setColor(rModelColor); + canvas.drawRect(racketLeft, controllerPosition, racketLeft + blockWidth, controllerPosition + controllerSize, mPaint); + } + + /** + * 绘制并处理小球运动的轨迹 + * + * @param canvas 默认画布 + * @param width 视图宽度 + */ + private void makeBallPath(Canvas canvas, int width) { + mPaint.setColor(mModelColor); + + if (cx <= blockLeft + blockHorizontalNum * blockWidth + (blockHorizontalNum - 1) * DIVIDING_LINE_SIZE + BALL_RADIUS) { // 小球进入到色块区域 + if (checkTouchBlock(cx, cy)) { // 反弹回来 + isleft = false; + } + } + if (cx <= blockLeft + BALL_RADIUS) { // 小球穿过色块区域 + isleft = false; + } + + if (cx + BALL_RADIUS >= racketLeft && cx - BALL_RADIUS < racketLeft + blockWidth) { //小球当前坐标X值在挡板X值区域范围内 + if (checkTouchRacket(cy)) { // 小球与挡板接触 + if (pointList.size() == blockHorizontalNum * BLOCK_VERTICAL_NUM) { // 矩形块全部被消灭,游戏结束 + status = STATUS_GAME_OVER; + return; + } + isleft = true; + } + } else if (cx > width) { // 小球超出挡板区域 + status = STATUS_GAME_OVER; + } + + if (cy <= BALL_RADIUS + DIVIDING_LINE_SIZE) { // 小球撞到上边界 + angle = 180 - DEFAULT_ANGLE; + } else if (cy >= mHeaderHeight - BALL_RADIUS - DIVIDING_LINE_SIZE) { // 小球撞到下边界 + angle = 180 + DEFAULT_ANGLE; + } + + if (isleft) { + cx -= speed; + } else { + cx += speed; + } + cy -= (float) Math.tan(Math.toRadians(angle)) * speed; + + canvas.drawCircle(cx, cy, BALL_RADIUS, mPaint); + + invalidate(); + + } + + /** + * 检查小球是否撞击到挡板 + * + * @param y 小球当前坐标Y值 + * @return 小球位于挡板Y值区域范围内:true,反之:false + */ + private boolean checkTouchRacket(float y) { + boolean flag = false; + float diffVal = y - controllerPosition; + if (diffVal >= 0 && diffVal <= controllerSize) { // 小球位于挡板Y值区域范围内 + flag = true; + } + return flag; + } + + /** + * 检查小球是否撞击到矩形块 + * + * @param x 小球坐标X值 + * @param y 小球坐标Y值 + * @return 撞击到:true,反之:false + */ + private boolean checkTouchBlock(float x, float y) { + int columnX = (int) ((x - blockLeft - BALL_RADIUS - speed) / blockWidth); + columnX = columnX == blockHorizontalNum ? columnX - 1 : columnX; + int rowY = (int) (y / blockHeight); + rowY = rowY == BLOCK_VERTICAL_NUM ? rowY - 1 : rowY; + Point p = new Point(); + p.set(columnX, rowY); + + boolean flag = false; + for (Point point : pointList) { + if (point.equals(p.x, p.y)) { + flag = true; + break; + } + } + + if (!flag) { + pointList.add(p); + } + return !flag; + } + + /** + * 绘制矩形色块 + * + * @param canvas 默认画布 + */ + private void drawColorBlock(Canvas canvas) { + float left, top; + int column, row; + for (int i = 0; i < blockHorizontalNum * BLOCK_VERTICAL_NUM; i++) { + row = i / blockHorizontalNum; + column = i % blockHorizontalNum; + + boolean flag = false; + for (Point point : pointList) { + if (point.equals(column, row)) { + flag = true; + break; + } + } + if (flag) { + continue; + } + + blockPaint.setColor(ColorUtils.setAlphaComponent(lModelColor, 255 / (column + 1))); + + left = blockLeft + column * (blockWidth + DIVIDING_LINE_SIZE); + top = DIVIDING_LINE_SIZE + row * (blockHeight + DIVIDING_LINE_SIZE); + canvas.drawRect(left, top, left + blockWidth, top + blockHeight, blockPaint); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameView.java b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameView.java new file mode 100644 index 000000000..0be00ed7b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/refresh/FunGameView.java @@ -0,0 +1,323 @@ +package com.yizhuan.erban.home.refresh; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.scwang.smartrefresh.header.R; +import com.scwang.smartrefresh.layout.api.RefreshKernel; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.util.ColorUtils; +import com.scwang.smartrefresh.layout.util.DensityUtil; + + +/** + * Created by Hitomis on 2016/3/9. + * email:196425254@qq.com + */ +public abstract class FunGameView extends FunGameHeader { + + // + protected static final int STATUS_GAME_PREPAR = 0; + + protected static final int STATUS_GAME_PLAY = 1; + + protected static final int STATUS_GAME_OVER = 2; + + protected static final int STATUS_GAME_FINISHED = 3; + + protected static final int STATUS_GAME_FAIL = 4; + + /** + * 控件高度占屏幕高度比率 + */ + protected static final float VIEW_HEIGHT_RATIO = .161f; + + public static String textGameOver = "游戏结束"; + public static String textLoading = "和我们一起玩"; + public static String textLoadingFinished = "刷新完成"; + public static String textLoadingFail = "刷新失败"; +// private String loadingText = "Loading..."; +// private String loadingFinishedText = "Loading Finished"; +// private String gameOverText = "Game Over"; + + protected Paint mPaint; + + protected TextPaint textPaint; + + protected float controllerPosition; + + protected int controllerSize; + + protected int status = STATUS_GAME_PREPAR; + + protected int lModelColor, rModelColor, mModelColor; + protected int mBackColor, mBoundaryColor = 0xff606060; + // + + public FunGameView(Context context) { + super(context); + this.initView(context, null); + } + + public FunGameView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.initView(context, attrs); + } + + public FunGameView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.initView(context, attrs); + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + public FunGameView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + this.initView(context, attrs); + } + + private void initView(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FunGameView); + mBackColor = ta.getColor(R.styleable.FunGameView_fgvBackColor, 0); + lModelColor = ta.getColor(R.styleable.FunGameView_fgvLeftColor, Color.rgb(0, 0, 0)); + mModelColor = ta.getColor(R.styleable.FunGameView_fgvMiddleColor, Color.BLACK); + rModelColor = ta.getColor(R.styleable.FunGameView_fgvRightColor, Color.parseColor("#A5A5A5")); + if (ta.hasValue(R.styleable.FunGameView_fgvTextGameOver)) { + textGameOver = ta.getString(R.styleable.FunGameView_fgvTextGameOver); + } + if (ta.hasValue(R.styleable.FunGameView_fgvTextGameOver)) { + textLoading = ta.getString(R.styleable.FunGameView_fgvTextLoading); + } + if (ta.hasValue(R.styleable.FunGameView_fgvTextGameOver)) { + textLoadingFinished = ta.getString(R.styleable.FunGameView_fgvTextLoadingFinished); + } + ta.recycle(); + + initBaseTools(); + initBaseConfigParams(); + initConcreteView(); + } + + protected void initBaseTools() { + textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(Color.parseColor("#C1C2C2")); + + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStrokeWidth(DIVIDING_LINE_SIZE); + } + + protected void initBaseConfigParams() { + controllerPosition = DIVIDING_LINE_SIZE; + } + + protected abstract void initConcreteView(); + + protected abstract void drawGame(Canvas canvas, int width, int height); + + protected abstract void resetConfigParams(); + + /** + * 绘制分割线 + * + * @param canvas 默认画布 + */ + private void drawBoundary(Canvas canvas, int width, int height) { + mPaint.setColor(mBackColor); + canvas.drawRect(0, 0, width, height, mPaint); + mPaint.setColor(mBoundaryColor); + canvas.drawLine(0, 0, width, 0, mPaint); + canvas.drawLine(0, height - DIVIDING_LINE_SIZE, + width, height - DIVIDING_LINE_SIZE, + mPaint); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + final int width = getWidth(); + final int height = mHeaderHeight; + drawBoundary(canvas, width, height); + drawText(canvas, width, height); + drawGame(canvas, width, height); + super.dispatchDraw(canvas); + } + + /** + * 绘制文字内容 + * + * @param canvas 默认画布 + */ + private void drawText(Canvas canvas, int width, int height) { + switch (status) { + case STATUS_GAME_PREPAR: + case STATUS_GAME_PLAY: + textPaint.setTextSize(DensityUtil.dp2px(21)); + promptText(canvas, textLoading, width, height); + break; + case STATUS_GAME_FINISHED: + textPaint.setTextSize(DensityUtil.dp2px(20)); + promptText(canvas, textLoadingFinished, width, height); + break; + case STATUS_GAME_FAIL: + textPaint.setTextSize(DensityUtil.dp2px(20)); + promptText(canvas, textLoadingFail, width, height); + break; + case STATUS_GAME_OVER: + textPaint.setTextSize(DensityUtil.dp2px(21)); + promptText(canvas, textGameOver, width, height); + break; + } + } + + /** + * 提示文字信息 + * + * @param canvas 默认画布 + * @param text 相关文字字符串 + */ + private void promptText(Canvas canvas, String text, int width, int height) { + float textX = (width - textPaint.measureText(text)) * .5f; + float textY = height * .5f - (textPaint.ascent() + textPaint.descent()) * .5f; + canvas.drawText(text, textX, textY, textPaint); + } + + + /** + * 获取当前控件状态 + */ + public int getCurrStatus() { + return status; + } + + public String getTextGameOver() { + return textGameOver; + } + + public void setTextGameOver(String textGameOver) { + this.textGameOver = textGameOver; + } + + public String getTextLoading() { + return textLoading; + } + + public void setTextLoading(String textLoading) { + this.textLoading = textLoading; + } + + public String getTextLoadingFinished() { + return textLoadingFinished; + } + + public void setTextLoadingFinished(String textLoadingFinished) { + this.textLoadingFinished = textLoadingFinished; + } + + /** + * 获取屏幕尺寸 + * + * @param context context + * @return 手机屏幕尺寸 + */ + private DisplayMetrics getScreenMetrics(Context context) { + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(dm); + return dm; + } + + + // + + + @Override + protected void onGameStart() { + postStatus(FunGameView.STATUS_GAME_PLAY); + } + + @Override + protected void onManualOperationMove(float percent, int offset, int headHeight, int extendHeight) { + moveController(Math.max(offset, 0)); + } + + /** + * 移动控制器(控制器对象为具体控件中的右边图像模型) + * + * @param distance 移动的距离 + */ + public void moveController(float distance) { + float maxDistance = (mHeaderHeight - 2 * DIVIDING_LINE_SIZE - controllerSize); + + if (distance > maxDistance) { + distance = maxDistance; + } + + controllerPosition = distance; + postInvalidate(); + } + + /** + * 更新当前控件状态 + * + * @param status 状态码 + */ + public void postStatus(int status) { + this.status = status; + + if (status == STATUS_GAME_PREPAR) { + resetConfigParams(); + } + + postInvalidate(); + } + // + + // + @Override + public void onInitialized(RefreshKernel kernel, int height, int extendHeight) { + super.onInitialized(kernel, height, extendHeight); + initConcreteView(); + postStatus(STATUS_GAME_PREPAR); + } + + @Override + public int onFinish(RefreshLayout layout, boolean success) { + if (mManualOperation) { + postStatus(success ? FunGameView.STATUS_GAME_FINISHED : FunGameView.STATUS_GAME_FAIL); + } else { + postStatus(FunGameView.STATUS_GAME_PREPAR); + } + return super.onFinish(layout, success); + } + + @Override + @Deprecated + public void setPrimaryColors(@ColorInt int... colors) { + super.setPrimaryColors(colors); + if (colors.length > 0) { + mBoundaryColor = mBackColor = colors[0]; + if (mBackColor == 0 || mBackColor == 0xffffffff) { + mBoundaryColor = 0xff606060; + } + if (colors.length > 1) { + mModelColor = colors[1]; + lModelColor = ColorUtils.setAlphaComponent(colors[1], 225); + rModelColor = ColorUtils.setAlphaComponent(colors[1], 200); + textPaint.setColor(ColorUtils.setAlphaComponent(colors[1], 150)); + } + } + } + + // + + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/Home3PlusNDecoration.java b/app/src/main/java/com/yizhuan/erban/home/view/Home3PlusNDecoration.java new file mode 100644 index 000000000..6e9892e5f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/Home3PlusNDecoration.java @@ -0,0 +1,99 @@ +package com.yizhuan.erban.home.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.home.adapter.HomeFragmentAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * 首页3+n的边框划线 + * Created by lvzebiao on 2019/2/20. + */ + +public class Home3PlusNDecoration extends RecyclerView.ItemDecoration { + + private int gridDividerPx; + + private HomeFragmentAdapter adapter; + + private Drawable lineDrawable; + + private int lineLeftPaddingPx; + + private int lineHeightPx = 1; + + public Home3PlusNDecoration(Context context, HomeFragmentAdapter adapter) { + gridDividerPx = UIUtil.dip2px(context, 15); + lineLeftPaddingPx = UIUtil.dip2px(context, 86); + this.adapter = adapter; + lineDrawable = new ColorDrawable(context.getResources().getColor(R.color.line_color)); + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + if (!(parent.getLayoutManager() instanceof GridLayoutManager)) { + return; + } + GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager(); + int position = parent.getChildAdapterPosition(view); + if (position >= adapter.getData().size()) { + outRect.set(0, 0, 0, 0); + return; + } + int dividerDesc = adapter.getData().get(position).getDividerDesc(); + int left, right; + if (dividerDesc == -3) { + left = 0; + right = 0; + } else if (dividerDesc >= 0) { + left = gridDividerPx - gridDividerPx * dividerDesc / manager.getSpanCount(); + right = gridDividerPx * (dividerDesc + 1) / manager.getSpanCount(); + } else { + left = gridDividerPx; + right = gridDividerPx; + } + int bottom = 0; + //首页去除画线 +// if (dividerDesc == -3) { +// bottom = 0; +// } else if (dividerDesc == -1) { +// bottom = lineHeightPx; +// } else { +// bottom = 0; +// } + outRect.set(left, 0, right, bottom); + } + //首页去除画线 +// @Override +// public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { +// super.onDraw(c, parent, state); +// int left = lineLeftPaddingPx; +// int right = parent.getWidth() - gridDividerPx; +// for (int i = 0; i < parent.getChildCount(); i++) { +// View childView = parent.getChildAt(i); +// RecyclerView.LayoutParams childViewParams = (RecyclerView.LayoutParams) childView.getLayoutParams(); +// int position = childViewParams.getViewAdapterPosition(); +// if (position < adapter.getData().size()) { +// int dividerDesc = adapter.getData().get(position).getDividerDesc(); +// if (dividerDesc == -1) { +// //int traX = (int)(ViewCompat.getTranslationX(childView)); 偏移值,暂时没用到 +// //int traY = (int)(ViewCompat.getTranslationY(childView)); +// final int top = childView.getTop() + childView.getHeight(); +// final int bottom = top + lineHeightPx; +// //drawable.setBounds(left + traX, top + traY, right + traX, bottom + traY); +// lineDrawable.setBounds(left, top, right, bottom); +// lineDrawable.draw(c); +// } +// } +// } +// } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/HomeConfigModule.java b/app/src/main/java/com/yizhuan/erban/home/view/HomeConfigModule.java new file mode 100644 index 000000000..dd7e24428 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/HomeConfigModule.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.home.view; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.home.adapter.ErbanRecommendAdapter; +import com.yizhuan.erban.home.adapter.RecommendThreeNModelDecoration; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.home.bean.HomeInfo; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.home.bean.RecommendInfo; +import com.yizhuan.xchat_android_library.widget.ShapeConstrainLayout; + +import java.util.List; + +/** + * 可配置模块,3N+M布局封装 + * Created by lvzebiao on 2019/2/19. + */ + +public class HomeConfigModule extends ShapeConstrainLayout { + + private TextView tvTitle; + + private RecyclerView recyclerView; + + public HomeConfigModule(Context context) { + this(context, null); + } + + public HomeConfigModule(Context context, AttributeSet attrs) { + super(context, attrs); + inflate(context, R.layout.home_module_title_recycler_view, this); + tvTitle = findViewById(R.id.tv_title); + recyclerView = findViewById(R.id.rv_list); + } + + public void setData(RecommendInfo info) { + if (info == null) { + return; + } + tvTitle.setText(info.getTitle()); + List roomList = info.getRoomList(); + recyclerView.setItemAnimator(null); + recyclerView.setFocusable(false); + Context context = getContext(); + GridLayoutManager manager = new GridLayoutManager(context, 3); + recyclerView.setLayoutManager(manager); + if (recyclerView.getItemDecorationCount() == 0) { + int px = UIUtil.dip2px(context, 15); + recyclerView.addItemDecoration(new RecommendThreeNModelDecoration(px)); + } + ErbanRecommendAdapter erbanRecommendAdapter = new ErbanRecommendAdapter(context, roomList); + recyclerView.setAdapter(erbanRecommendAdapter); + erbanRecommendAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + if (position < 3) { + return 1; + } + return manager.getSpanCount(); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/ICommunityNoticeAct.java b/app/src/main/java/com/yizhuan/erban/home/view/ICommunityNoticeAct.java new file mode 100644 index 000000000..b64a90e18 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/ICommunityNoticeAct.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.community.bean.CommunityNoticeInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +public interface ICommunityNoticeAct extends IMvpBaseView { + void getMsgListSuccess(List list); + void getMsgListFail(String error); + + void clearSuccess(); + void clearFail(String error); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IFamilyFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IFamilyFragmentView.java new file mode 100644 index 000000000..91c3e5f09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IFamilyFragmentView.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.family.bean.FamilyCustomServiceInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public interface IFamilyFragmentView extends IMvpBaseView { + void showMyFamilyInfo(FamilyInfo familyInfo); + + void onCustomServiceInfo(FamilyCustomServiceInfo customServiceInfo); + + void onCustomServiceFail(String reason); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IFamilyHomeActivityView.java b/app/src/main/java/com/yizhuan/erban/home/view/IFamilyHomeActivityView.java new file mode 100644 index 000000000..3ac95c3c8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IFamilyHomeActivityView.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; + +/** + * @author jack + * @Description + * @Date 2018/5/23 + */ + +public interface IFamilyHomeActivityView extends IMvpBaseView { + + void onLoadData(FamilyInfo data); + + void showErrorView(String message); + + void reloadMyFamilyInfo(String familyId); + + void close(); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IFindFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IFindFragmentView.java new file mode 100644 index 000000000..3954bc50b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IFindFragmentView.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.home.bean.FindInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/5/22 + */ + +public interface IFindFragmentView extends IMvpBaseView { + + public void onLoadData(FindInfo findInfo); + + void onLoadDataFail(String error); + +// void onLoadNewUserList(List userInfoList); + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IFindTabFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IFindTabFragmentView.java new file mode 100644 index 000000000..0c4b2744e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IFindTabFragmentView.java @@ -0,0 +1,6 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IFindTabFragmentView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IHottestKTVRoomFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IHottestKTVRoomFragmentView.java new file mode 100644 index 000000000..cf5f8cf8e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IHottestKTVRoomFragmentView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public interface IHottestKTVRoomFragmentView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IKTVFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IKTVFragmentView.java new file mode 100644 index 000000000..a2d0c8270 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IKTVFragmentView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public interface IKTVFragmentView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentTabBg.java b/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentTabBg.java new file mode 100644 index 000000000..73e5dd829 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentTabBg.java @@ -0,0 +1,5 @@ +package com.yizhuan.erban.home.view; + +public interface IMainFragmentTabBg { + void isBannerTop(boolean isBannerTop); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentView.java new file mode 100644 index 000000000..46f714c35 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IMainFragmentView.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.family.bean.HomeBannerInfo; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_core.home.bean.TagListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_core.home.bean.HomeItem; + +import java.util.List; + +/** + * @author jiajie + * @Description + * @Date 2018/4/13 + */ + +public interface IMainFragmentView extends IMvpBaseView { + + + /** + * 请求打开房间结果 + * @param openRoomFailType + * @param arg + */ + void requestOpenRoomResult(int openRoomFailType, Object... arg); + + void showByMarketCheckingStatus(List tagListInfoList); + + + /** + * 假实现,用于在View销毁后 调用View方法导致空指针问题,的一种解决方案 + */ + class FakeIMainFragmentView implements IMainFragmentView{ + + @Override + public void requestOpenRoomResult(int openRoomFailType, Object... arg) { + + } + + @Override + public void showByMarketCheckingStatus(List tagListInfoList) { + + } + + @Override + public void titleListSuccess(List tagListInfoList) { + + } + + @Override + public void titleListFail(String msg) { + + } + + @Override + public void onGetFirstPageBannerSucceeded(HomeBannerInfo homeBannerInfo) { + + } + + @Override + public void onGetFirstPageBannerFailed(String message) { + + } + + @Override + public void roomWorldModeCloseSuccess() { + + } + + @Override + public void roomWorldModeCloseFail(String error) { + + } + } + + void titleListSuccess(List tagListInfoList); + void titleListFail(String msg); + + /** + * 获取首页banner成功 + * @param homeBannerInfo + */ + void onGetFirstPageBannerSucceeded(HomeBannerInfo homeBannerInfo); + + /** + * 获取首页banner失败 + * @param message + */ + void onGetFirstPageBannerFailed(String message); + + void roomWorldModeCloseSuccess(); + void roomWorldModeCloseFail(String error); + +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IMainView.java b/app/src/main/java/com/yizhuan/erban/home/view/IMainView.java new file mode 100644 index 000000000..25affdb3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IMainView.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + *

+ * + * @author jiahui + * @date 2017/12/12 + */ +public interface IMainView extends IMvpBaseView { + /** + * 退出房间 + */ + void exitRoom(RoomInfo roomInfo); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/INewUserListActivityView.java b/app/src/main/java/com/yizhuan/erban/home/view/INewUserListActivityView.java new file mode 100644 index 000000000..8e428cf9b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/INewUserListActivityView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/11/1 + */ +public interface INewUserListActivityView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/INewestKTVRoomFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/INewestKTVRoomFragmentView.java new file mode 100644 index 000000000..9ad488e73 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/INewestKTVRoomFragmentView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public interface INewestKTVRoomFragmentView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IRecommendFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IRecommendFragmentView.java new file mode 100644 index 000000000..6c72767be --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IRecommendFragmentView.java @@ -0,0 +1,124 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_core.home.bean.HomeItem; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public interface IRecommendFragmentView extends IMvpBaseView { + public static int NOTIFY_DATA_SET_CHANGED = 1; + public static int NOTIFY_DATA_SET_REMOVE = 2; + + /** + * 设置首页数据 + * + * @param data 首页数据 + */ + void loadHomeDataSuccess(List data); + + /** + * 没有首页数据 + */ + void onNoHomeData(); + + /** + * 获取首页数据失败 + * + * @param error + */ + void loadHomeDataFail(String error); + + /** + * 加载第二页数据 + * + * @param data 首页数据 + */ + void addHomeDataSuccess(List data); + + /** + * 没有更多房间数据了 + */ + void onNoMoreHomeData(); + + /** + * 加载第二页数据失败 + * + * @param error + */ + void addHomeDataFail(String error); + + + void setEnableLoadMore(boolean b); + + void setRefreshing(boolean b); + + void notifyDataSetChanged(int type, int position, Object payloads); + + void showByMarketCheckingStatus(); + + void onRefreshMakeFriendListFail(String message); + + + public class FakeIMainFragmentView implements IRecommendFragmentView { + @Override + public void loadHomeDataSuccess(List data) { + + } + + @Override + public void onNoHomeData() { + + } + + @Override + public void loadHomeDataFail(String error) { + + } + + @Override + public void addHomeDataSuccess(List data) { + + } + + @Override + public void onNoMoreHomeData() { + + } + + @Override + public void addHomeDataFail(String error) { + + } + + @Override + public void setEnableLoadMore(boolean b) { + + } + + @Override + public void setRefreshing(boolean b) { + + } + + @Override + public void notifyDataSetChanged(int type, int position, Object payloads) { + + } + + + @Override + public void showByMarketCheckingStatus() { + + } + + @Override + public void onRefreshMakeFriendListFail(String message) { + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IRoomCategoryFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IRoomCategoryFragmentView.java new file mode 100644 index 000000000..5c7229b4d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IRoomCategoryFragmentView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/10/29 + */ +public interface IRoomCategoryFragmentView extends IMvpBaseView { + public void initiate(); +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IRoomListFragmentView.java b/app/src/main/java/com/yizhuan/erban/home/view/IRoomListFragmentView.java new file mode 100644 index 000000000..f51c3ae7f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IRoomListFragmentView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * @author jack + * @Description + * @Date 2018/11/2 + */ +public interface IRoomListFragmentView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/view/IRoomTabView.java b/app/src/main/java/com/yizhuan/erban/home/view/IRoomTabView.java new file mode 100644 index 000000000..6cb75874e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/view/IRoomTabView.java @@ -0,0 +1,6 @@ +package com.yizhuan.erban.home.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IRoomTabView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/home/widget/ListViewAdaptWidth.java b/app/src/main/java/com/yizhuan/erban/home/widget/ListViewAdaptWidth.java new file mode 100644 index 000000000..8cc552833 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/home/widget/ListViewAdaptWidth.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.home.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ListView; + +public class ListViewAdaptWidth extends ListView { + + public ListViewAdaptWidth(Context context) { + super(context); + } + + public ListViewAdaptWidth(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ListViewAdaptWidth(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + //计算listview的宽度 + int width = getMaxWidthOfChildren() + getPaddingLeft() + getPaddingRight(); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), heightMeasureSpec);//设置listview的宽高 + + } + + /** + * 计算item的最大宽度 + * + * @return + */ + private int getMaxWidthOfChildren() { + int maxWidth = 0; + View view = null; + int count = getAdapter().getCount(); + for (int i = 0; i < count; i++) { + view = getAdapter().getView(i, view, this); + view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + if (view.getMeasuredWidth() > maxWidth) + maxWidth = view.getMeasuredWidth(); + } + return maxWidth; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/location/LocationManager.java b/app/src/main/java/com/yizhuan/erban/location/LocationManager.java new file mode 100644 index 000000000..cc407e790 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/location/LocationManager.java @@ -0,0 +1,50 @@ +package com.yizhuan.erban.location; + +import android.content.Context; + +import com.yizhuan.erban.guide.GuideActivity; +import com.yizhuan.erban.other.activity.SplashActivity; +import com.yizhuan.erban.ui.login.LoginActivity; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.utils.UIUtils; + +import org.greenrobot.eventbus.EventBus; + +import java.util.Calendar; +import java.util.Date; + +public class LocationManager { + private static final String LOCATE_TIME = "locate_time"; + + public static void uploadLocation(Context context) { + + if (UIUtils.isTopActivity(context, SplashActivity.class.getName()) + || UIUtils.isTopActivity(context, LoginActivity.class.getName()) + || UIUtils.isTopActivity(context, GuideActivity.class.getName())) { + return; + } + + Long lastLocateTime = (Long) SharedPreferenceUtils.get(LOCATE_TIME, 0L); + if (lastLocateTime != null) { + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.set(Calendar.HOUR, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + + long currentTime = calendar.getTimeInMillis(); + + if (lastLocateTime < currentTime) { + EventBus.getDefault().post(new LocationUploadEvent()); + } + + } + + } + + public static void saveUploadTime() { + SharedPreferenceUtils.put(LOCATE_TIME, System.currentTimeMillis()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/location/LocationUploadEvent.java b/app/src/main/java/com/yizhuan/erban/location/LocationUploadEvent.java new file mode 100644 index 000000000..ed724a54e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/location/LocationUploadEvent.java @@ -0,0 +1,4 @@ +package com.yizhuan.erban.location; + +public class LocationUploadEvent { +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/adapter/LuckyMoneyMemberListAdapter.java b/app/src/main/java/com/yizhuan/erban/luckymoney/adapter/LuckyMoneyMemberListAdapter.java new file mode 100644 index 000000000..a75b9dc2d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/adapter/LuckyMoneyMemberListAdapter.java @@ -0,0 +1,57 @@ +package com.yizhuan.erban.luckymoney.adapter; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.common.ui.imageview.HeadImageView; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyUserInfo; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by MadisonRong on 05/06/2018. + */ + +public class LuckyMoneyMemberListAdapter extends BaseAdapter { + + private Context context; + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); + + public LuckyMoneyMemberListAdapter(Context context) { + this(R.layout.item_lucky_money_member_list, BR.memberInfo, context); + } + + public LuckyMoneyMemberListAdapter(int layoutResId, int brid, Context context) { + super(layoutResId, brid); + this.context = context; + } + + @Override + protected void convert(BindingViewHolder helper, LuckyMoneyUserInfo item) { + HeadImageView ivAvatar = helper.getView(R.id.iv_avatar); + TextView tvName = helper.getView(R.id.tv_name); + TextView timestamp = helper.getView(R.id.tv_timestamp); + TextView amount = helper.getView(R.id.tv_member_amount); + + + ImageLoadUtils.loadAvatar(context, item.getAvatar(), ivAvatar, true); + tvName.setText(item.getNick()); + timestamp.setText(simpleDateFormat.format(new Date(item.getCreateTime()))); + helper.setVisible(R.id.tv_luckiest, item.isLuckiest()); + amount.setText(String.valueOf(item.getAmount())); + helper.setText(R.id.tv_coin_name, FamilyModel.Instance().getMyFamily().getMoneyName()); + + if (this.mData != null && this.mData.size() > 0 && + this.mData.indexOf(item) == this.mData.size() - 1) { + helper.getView(R.id.diver).setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyComfirmToPayDialog.java b/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyComfirmToPayDialog.java new file mode 100644 index 000000000..a73d1054e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyComfirmToPayDialog.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.luckymoney.dialog; + +import android.content.Context; +import android.support.v7.app.AppCompatDialog; +import android.view.View; + +/** + * Created by MadisonRong on 17/07/2018. + */ + +public class LuckyMoneyComfirmToPayDialog extends AppCompatDialog implements View.OnClickListener { + + public LuckyMoneyComfirmToPayDialog(Context context) { + super(context); + } + + @Override + public void onClick(View v) { + // + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyDialog.java b/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyDialog.java new file mode 100644 index 000000000..b410133f3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/dialog/LuckyMoneyDialog.java @@ -0,0 +1,234 @@ +package com.yizhuan.erban.luckymoney.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatDialog; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.erban.luckymoney.view.LuckyMoneyDetailActivity; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.team.bean.TeamEvent; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import io.reactivex.disposables.Disposable; + +/** + * Created by MadisonRong on 31/05/2018. + */ + +public class LuckyMoneyDialog extends AppCompatDialog implements View.OnClickListener { + + private static final String TAG = "LuckyMoneyDialog"; + + private LuckyMoneyInfo luckyMoneyInfo; + private TeamViewModel teamViewModel; + private FamilyInfo myFamilyInfo; + private String uuid; + private Disposable disposable; + + public LuckyMoneyDialog(@NonNull Context context, LuckyMoneyInfo luckyMoneyInfo, String uuid) { + super(context); + this.luckyMoneyInfo = luckyMoneyInfo; + this.uuid = uuid; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + Window window = getWindow(); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams params = window.getAttributes(); + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + window.setWindowAnimations(R.style.ErbanCommonWindowAnimationStyle); + super.onCreate(savedInstanceState); + teamViewModel = new TeamViewModel(); + myFamilyInfo = FamilyModel.Instance().getMyFamily(); +// dialogManager = new DialogManager(getContext()); + setCancelable(true); + setDialogContentView(luckyMoneyInfo); + } + + private void setDialogContentView(LuckyMoneyInfo luckyMoneyInfo) { + if (luckyMoneyInfo == null) return; + + switch (luckyMoneyInfo.getClaimStatus()) { + // 红包待开 + default: + case LuckyMoneyInfo.STATE_NOT_OPEN: + setContentView(R.layout.dialog_lucky_money); + findViewById(R.id.iv_close).setOnClickListener(this); + findViewById(R.id.rl_lucky_money_dialog_background).setOnClickListener(this); + break; + + // 打开红包 + case LuckyMoneyInfo.STATE_DID_OPEN: + setContentView(R.layout.dialog_lucky_money_draw); + findViewById(R.id.tv_other_operation).setOnClickListener(this); + findViewById(R.id.iv_close).setOnClickListener(this); + // 显示发送者的头像和名字 + setupAvatarAndNick(luckyMoneyInfo); + TextView amount = findViewById(R.id.tv_amount); + amount.setText(luckyMoneyInfo.getAmount() + myFamilyInfo.getMoneyName()); + break; + + // 红包已领完 + case LuckyMoneyInfo.STATE_OUT_BONUS: + setContentView(R.layout.dialog_lucky_money_out_bonus); + findViewById(R.id.iv_close).setOnClickListener(this); + findViewById(R.id.tv_other_operation).setOnClickListener(this); + // 显示发送者的头像和名字 + setupAvatarAndNick(luckyMoneyInfo); + break; + + // 红包已过期 + case LuckyMoneyInfo.STATE_OUT_DATE: + setContentView(R.layout.dialog_lucky_money_out_date); + findViewById(R.id.iv_close).setOnClickListener(this); + // 显示发送者的头像和名字 + setupAvatarAndNick(luckyMoneyInfo); + break; + } + } + + private void setupAvatarAndNick(LuckyMoneyInfo luckyMoneyInfo) { + ImageView userAvatar = findViewById(R.id.iv_avatar); + ImageLoadUtils.loadAvatar(getContext(), luckyMoneyInfo.getAvatar(), userAvatar, true); + TextView userName = findViewById(R.id.tv_user_name); + userName.setText(luckyMoneyInfo.getNick()); + } + + private void init(View view) { + // + } + + @Override + protected void onStop() { + super.onStop(); + if (disposable != null && !disposable.isDisposed()) { + disposable.dispose(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.rl_lucky_money_dialog_background: + // 请求服务器 API 进行开红包 + if (luckyMoneyInfo.getClaimStatus() == LuckyMoneyInfo.STATE_NOT_OPEN) { + disposable = teamViewModel.receiveLuckyMoney(String.valueOf(luckyMoneyInfo.getId())) + .subscribe((luckyMoneyInfoServiceResult, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + if (luckyMoneyInfoServiceResult.isSuccess()) { + LuckyMoneyInfo respLuckyMoneyInfo = luckyMoneyInfoServiceResult.getData(); + luckyMoneyInfo.setClaimStatus(respLuckyMoneyInfo.getClaimStatus()); + switch (respLuckyMoneyInfo.getClaimStatus()) { + case LuckyMoneyInfo.STATE_DID_OPEN: + if (respLuckyMoneyInfo.getAmount() != 0) { + String uid = String.valueOf(AuthModel.get().getCurrentUid()); + UserInfo cacheLoginUserInfo = UserModel.get().getCacheLoginUserInfo(); + String nick = cacheLoginUserInfo != null ? cacheLoginUserInfo.getNick() : ""; + luckyMoneyInfo.setAmount(respLuckyMoneyInfo.getAmount()); + luckyMoneyInfo.setClaimStatus(LuckyMoneyInfo.STATE_DID_OPEN); + respLuckyMoneyInfo.setReceiveNick(nick); + respLuckyMoneyInfo.setReceiveUid(uid); + respLuckyMoneyInfo.setUid(Integer.parseInt(uid)); + respLuckyMoneyInfo.setSenderUid(luckyMoneyInfo.getSenderUid()); + respLuckyMoneyInfo.setNick(luckyMoneyInfo.getNick()); + respLuckyMoneyInfo.setClaimStatus(LuckyMoneyInfo.STATE_DID_OPEN); + respLuckyMoneyInfo.setAvatar(luckyMoneyInfo.getAvatar()); + respLuckyMoneyInfo.setTId(luckyMoneyInfo.getTId()); + IMNetEaseManager.get().receiveLuckyMoneyMessage(SessionType.TEAM, + TeamModel.get().getCurrentTeamInfo().getTid(), uid, respLuckyMoneyInfo); + setDialogContentView(luckyMoneyInfo); + } else { + dismiss(); + openLuckyMoneyDetail(); + return; + } + break; + + case LuckyMoneyInfo.STATE_OUT_BONUS: + break; + + case LuckyMoneyInfo.STATE_OUT_DATE: + break; + } + updateLuckyMoneyInfo(respLuckyMoneyInfo.getClaimStatus()); + IMNetEaseManager.get().updateLuckyMoneyMessage(uuid, luckyMoneyInfo); + // 刷新界面 + RxBus.get().post(new TeamEvent().setOperation(TeamEvent.OP_UPDATE_MSG).setMsgUuid(uuid)); + } else { + switch (luckyMoneyInfoServiceResult.getCode()) { + case LuckyMoneyInfo.LUCKY_MONEY_HAS_EXPIRED: + updateLuckyMoneyInfo(LuckyMoneyInfo.STATE_OUT_DATE); + break; + + case LuckyMoneyInfo.LUCKY_MONEY_HAS_GONE: + updateLuckyMoneyInfo(LuckyMoneyInfo.STATE_OUT_BONUS); + break; + + case LuckyMoneyInfo.LUCKY_MONEY_HAS_TOKEN: + openLuckyMoneyDetail(); + break; + + case LuckyMoneyInfo.LUCKY_MONEY_NOT_EXIST: + break; + default: + SingleToastUtil.showToast(luckyMoneyInfoServiceResult.getMessage()); + break; + } + } + } + }); + } + break; + + case R.id.iv_close: + dismiss(); + break; + + case R.id.tv_other_operation: + openLuckyMoneyDetail(); + break; + } + } + + private void updateLuckyMoneyInfo(int stateOutBonus) { + luckyMoneyInfo.setClaimStatus(stateOutBonus); + setDialogContentView(luckyMoneyInfo); + } + + private void openLuckyMoneyDetail() { + dismiss(); + LuckyMoneyDetailActivity.start(getContext(), luckyMoneyInfo.getId()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyCreationActivity.java b/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyCreationActivity.java new file mode 100644 index 000000000..4cf7ef9a8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyCreationActivity.java @@ -0,0 +1,307 @@ +package com.yizhuan.erban.luckymoney.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; + +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityLuckyMoneyCreationBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BalanceNotEnoughExeption; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.trello.rxlifecycle2.android.ActivityEvent; + +import java.util.Objects; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 05/06/2018. + */ +@ActLayoutRes(R.layout.activity_lucky_money_creation) +public class LuckyMoneyCreationActivity extends BaseBindingActivity + implements View.OnClickListener, TextWatcher { + + private static final int DECIMAL_DIGITS = 2; + private FamilyInfo myFamilyInfo; + private TeamInfo teamInfo; + private TeamViewModel teamViewModel; + private double redPacketRate; + + public static void start(Context context) { + Intent intent = new Intent(context, LuckyMoneyCreationActivity.class); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.title_lucky_money_creation)); + + myFamilyInfo = FamilyModel.Instance().getMyFamily(); + teamViewModel = new TeamViewModel(); + teamInfo = TeamModel.get().getCurrentTeamInfo(); + + redPacketRate = myFamilyInfo.getRedPacketRate() * 100; + mBinding.tvCoinName.setText(myFamilyInfo.getMoneyName()); + mBinding.tvDisplayCoinName.setText(myFamilyInfo.getMoneyName()); + mBinding.tvFamilyMemberCount.setText(getString(R.string.text_total_family_member, + String.valueOf(teamInfo.getMemberCount()))); + updateRemainCoin(); + mBinding.tvLuckyMoneyRate.setText( + getString(R.string.tips_lucky_money_service_interest_rate, redPacketRate + "%")); + resetLuckyMoneyAmountAndFee(); + mBinding.tvLuckyMoneyReturnBack.setText(getString(R.string.tips_lucky_money_return_back, myFamilyInfo.getMoneyName())); + mBinding.etLuckyMoneyAmount.addTextChangedListener(this); + mBinding.etLuckyMoneyCount.addTextChangedListener(this); + mBinding.setClick(this); + + requestFamilyInfo(); + refreshFamilyCurrencyAmount(String.valueOf(AuthModel.get().getCurrentUid())); + } + + /** + * 这里获取家族信息,决定是否能使用家族币 + */ + private void requestFamilyInfo() { + if (FamilyModel.Instance().getMyFamily() == null) { + return; + } + FamilyModel.Instance().loadFamilySimpleInfo( + FamilyModel.Instance().getMyFamily().getFamilyId() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + if (!familyInfo.isOpenMoney()) { + toast("已关闭家族币."); + finish(); + } + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setBackgroundColor(ContextCompat.getColor(this, R.color.color_ff5454)); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.drawable.icon_nav_back); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + EditText editText = mBinding.etLuckyMoneyAmount; + if (editText.isFocused()) { + // 限制红包金额最多只能输入一个小数点以及两个小数 + if (s.toString().contains(".")) { + if (s.length() - 1 - s.toString().indexOf(".") > DECIMAL_DIGITS) { + s = s.toString().subSequence(0, + s.toString().indexOf(".") + DECIMAL_DIGITS + 1); + editText.setText(s); + editText.setSelection(s.length()); + } + } + if (s.toString().trim().substring(0).equals(".")) { + s = "0" + s; + editText.setText(s); + editText.setSelection(2); + } + if (s.toString().startsWith("0") + && s.toString().trim().length() > 1) { + if (!s.toString().substring(1, 2).equals(".")) { + editText.setText(s.subSequence(0, 1)); + editText.setSelection(1); + return; + } + } + } + } + + @Override + public void afterTextChanged(Editable s) { + if (mBinding.etLuckyMoneyAmount.isFocused()) { + String amountInput = mBinding.etLuckyMoneyAmount.getText().toString(); + if (Objects.equals(amountInput, "")) { + resetLuckyMoneyAmountAndFee(); + } else { + double amountInputValue = JavaUtil.str2double(amountInput); + setLuckyMoneyAmountAndFee(amountInput, amountInputValue); + } + } + if (mBinding.etLuckyMoneyCount.isFocused()) { + String countInput = mBinding.etLuckyMoneyCount.getText().toString(); + mBinding.tvOverMemberCountTips.setVisibility(JavaUtil.str2int(countInput) > 500 ? View.VISIBLE : View.INVISIBLE); + } + } + + private void setLuckyMoneyAmountAndFee(String amountInput, double amountInputValue) { + mBinding.tvDisplayLuckyMoneyAmount.setText(amountInput); + mBinding.tvLuckyMoneyServiceFee.setText(getString(R.string.text_lucky_money_service_fee, + JavaUtil.formatDecimal(amountInputValue * myFamilyInfo.getRedPacketRate()) + myFamilyInfo.getMoneyName())); + } + + private void resetLuckyMoneyAmountAndFee() { + mBinding.tvDisplayLuckyMoneyAmount.setText(getString(R.string.hint_lucky_money_amount)); + mBinding.tvLuckyMoneyServiceFee.setText(getString(R.string.text_lucky_money_service_fee, getString(R.string.hint_lucky_money_amount) + myFamilyInfo.getMoneyName())); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_ready_to_send: + String tempAmountString = mBinding.etLuckyMoneyAmount.getText().toString(); + String tempCountString = mBinding.etLuckyMoneyCount.getText().toString(); + double amountDoubleValue = JavaUtil.str2double(tempAmountString); + double countDoubleValue = JavaUtil.str2double(tempCountString); + if (countDoubleValue <= 0 || countDoubleValue > 500) { + toast(getString(R.string.tips_lucky_money_count)); + return; + } + if (amountDoubleValue < 1) { + toast(getString(R.string.tips_lucky_money_amount) + myFamilyInfo.getMoneyName()); + return; + } + String tempFee = String.valueOf(JavaUtil.str2double(tempAmountString) + * myFamilyInfo.getRedPacketRate()); + String fee = JavaUtil.formatDecimal(JavaUtil.str2double(tempFee)); + double feeValue = JavaUtil.str2double(tempFee); + String tempRealAmountString = JavaUtil.str2double2len(String.valueOf(amountDoubleValue - feeValue)); + double amountValue = JavaUtil.str2double(tempRealAmountString); + double averageAmount = amountValue / countDoubleValue; + if (averageAmount < 0.01) { + toast(getString(R.string.tips_lucky_money_average_amount)); + return; + } + if (!Objects.equals(tempAmountString, "") && + !Objects.equals(tempCountString, "")) { + hideIME(); + getDialogManager().showLuckyMoneyConfirmToPayDialog(tempAmountString, + fee, + myFamilyInfo.getMoneyName(), + v1 -> { + getDialogManager().showProgressDialog(getApplicationContext(), "发送中", false); + sendLuckyMoney(); + }); + } + break; + } + } + + private void sendLuckyMoney() { + Team team = NIMClient.getService(TeamService.class).queryTeamBlock(teamInfo.getTid()); + String uid = String.valueOf(AuthModel.get().getCurrentUid()); + TeamMember teamMember = NIMClient.getService(TeamService.class).queryTeamMemberBlock(teamInfo.getTid(), uid); + if (!team.isMyTeam()) { + getDialogManager().dismissDialog(); + toast("你已不在群内"); + return; + } + if (teamMember.isMute()) { + getDialogManager().dismissDialog(); + toast("你已被禁言,不能发红包"); + return; + } + String message = mBinding.etLuckyMoneyGreetings.getEditableText().toString(); + if (Objects.equals(message, "")) { + message = getString(R.string.hint_lucky_money_greetings); + } + teamViewModel.sendLuckyMoney(teamInfo.getTid(), + Double.parseDouble(mBinding.etLuckyMoneyAmount.getText().toString()), + Integer.parseInt(mBinding.etLuckyMoneyCount.getText().toString()), + message) + .compose(bindToLifecycle()) + .subscribe((luckyMoneyInfo, throwable) -> { + getDialogManager().dismissDialog(); + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + if (throwable instanceof BalanceNotEnoughExeption) { + getDialogManager().showOkCancelDialog("余额不足,请充值", + true, new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + ChargeActivity.start(LuckyMoneyCreationActivity.this); + } + }); + + } + } else { + luckyMoneyInfo.setUid(Integer.parseInt(uid)); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + luckyMoneyInfo.setAvatar(userInfo.getAvatar()); + luckyMoneyInfo.setNick(userInfo.getNick()); + } + IMNetEaseManager.get().sendLuckyMoneyMessage(SessionType.TEAM, teamInfo.getTid(), uid, luckyMoneyInfo); + finish(); + } + }); + } + + private void refreshFamilyCurrencyAmount(String uid) { + FamilyModel.Instance().refreshFamilyCurrencyAmount() + .compose(bindToLifecycle()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((familyInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + FamilyModel.Instance().getMyFamily().setFamilyMoney(familyInfo.getFamilyMoney()); + updateRemainCoin(); + } + }); + } + + private void updateRemainCoin() { + mBinding.tvRemainCoin.setText(myFamilyInfo.getMoneyName() + getString(R.string.text_lucky_money_remain_coin, + String.valueOf(myFamilyInfo.getFamilyMoney()))); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyDetailActivity.java b/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyDetailActivity.java new file mode 100644 index 000000000..2695d6af7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/view/LuckyMoneyDetailActivity.java @@ -0,0 +1,131 @@ +package com.yizhuan.erban.luckymoney.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.ActivityLuckyMoneyDetailBinding; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.luckymoney.adapter.LuckyMoneyMemberListAdapter; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyUserInfo; +import com.yizhuan.xchat_android_core.user.IUserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + + +import java.util.List; +import java.util.Objects; + +/** + * Created by MadisonRong on 05/06/2018. + */ +@ActLayoutRes(R.layout.activity_lucky_money_detail) +public class LuckyMoneyDetailActivity extends BaseBindingActivity { + + public static final String EXTRA_LUCKY_MONEY_ID = "EXTRA_LUCKY_MONEY_ID"; + + private LuckyMoneyMemberListAdapter adapter; + private TeamViewModel teamViewModel; + private FamilyInfo myFamilyInfo; + private int luckyMoneyId; + + public static void start(Context context, int luckyMoneyId) { + Intent intent = new Intent(context, LuckyMoneyDetailActivity.class); + intent.putExtra(EXTRA_LUCKY_MONEY_ID, luckyMoneyId); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.action_red_packet)); + + teamViewModel = new TeamViewModel(); + myFamilyInfo = FamilyModel.Instance().getMyFamily(); + luckyMoneyId = getIntent().getIntExtra(EXTRA_LUCKY_MONEY_ID, -1); + + adapter = new LuckyMoneyMemberListAdapter(this); + mBinding.recyclerView.setAdapter(adapter); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + + showLoading(); + } + + @Override + protected void onResume() { + super.onResume(); + teamViewModel.receiveLuckyMoneyRecords(String.valueOf(luckyMoneyId)) + .compose(bindToLifecycle()) + .subscribe((luckyMoneyRecordsInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + boolean result = false; + LuckyMoneyUserInfo myself = null; + UserInfo cacheLoginUserInfo = UserModel.get().getCacheLoginUserInfo(); + LuckyMoneyInfo luckyMoneyInfo = luckyMoneyRecordsInfo.getRedPacket(); + mBinding.tvLuckyMoneyGreeting.setText(luckyMoneyInfo.getMessage()); + List records = luckyMoneyRecordsInfo.getRecords(); + if (cacheLoginUserInfo != null) { + for (LuckyMoneyUserInfo record : records) { + if (Objects.equals(record.getUid(), String.valueOf(cacheLoginUserInfo.getUid()))) { + result = true; + myself = record; + break; + } + } + mBinding.llAmount.setVisibility(result ? View.VISIBLE : View.GONE); + mBinding.tvLuckyMoneyTips.setVisibility(result ? View.GONE : View.VISIBLE); + if (result) { + mBinding.tvLuckyMoneyAmount.setText(String.valueOf(myself.getAmount())); + mBinding.tvCoinName.setText(myFamilyInfo.getMoneyName()); + } + ImageLoadUtils.loadAvatar(this, cacheLoginUserInfo.getAvatar(), mBinding.ivAvatar, true); + mBinding.tvName.setText(cacheLoginUserInfo.getNick()); + } + + //这里保留两位精度,需要计算到第三位 + int amount = (int) (luckyMoneyInfo.getAmount() * 1000); + int claimedAmount = (int) (luckyMoneyInfo.getClaimedAmount() * 1000); + int fee = (int) (luckyMoneyInfo.getFee() * 1000); + double resTemp = (amount - claimedAmount - fee) / 1000.0f; + String restAmount = FormatUtils.formatBigDecimal(resTemp); + mBinding.tvSubTitleLuckyMoneyDetail.setText(String.format(getString(R.string.text_lucky_money_sub_title_detail), + String.valueOf(luckyMoneyInfo.getClaimedNum()), + String.valueOf(luckyMoneyInfo.getNum()), + restAmount + myFamilyInfo.getMoneyName())); + if (!ListUtils.isListEmpty(records)) { + hideStatus(); + adapter.setNewData(records); + adapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + }); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setBackgroundColor(ContextCompat.getColor(this, R.color.color_ff5454)); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.drawable.icon_nav_back); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyMsgViewHolder.java b/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyMsgViewHolder.java new file mode 100644 index 000000000..0a359bb37 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyMsgViewHolder.java @@ -0,0 +1,125 @@ +package com.yizhuan.erban.luckymoney.viewholder; + +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.model.Team; +import com.yizhuan.erban.R; +import com.yizhuan.erban.luckymoney.dialog.LuckyMoneyDialog; +import com.yizhuan.erban.luckymoney.view.LuckyMoneyDetailActivity; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyAttachment; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.Objects; + +/** + * Created by MadisonRong on 31/05/2018. + */ + +public class LuckyMoneyMsgViewHolder extends MsgViewHolderBase implements View.OnClickListener { + + private static final String TAG = "LuckyMoneyMsgViewHolder"; + + private View layout; + private TextView greetingView; + private LuckyMoneyInfo luckyMoneyInfo; + + public LuckyMoneyMsgViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + public void onClick(View v) { + TeamInfo teamInfo = TeamModel.get().getCurrentTeamInfo(); + if (teamInfo == null) { + return; + } + Team team = NIMClient.getService(TeamService.class) + .queryTeamBlock(TeamModel.get().getCurrentTeamInfo().getTid()); + if (team != null && team.isMyTeam()) { + if (luckyMoneyInfo.getClaimStatus() == LuckyMoneyInfo.STATE_DID_OPEN) { + LuckyMoneyDetailActivity.start(context, luckyMoneyInfo.getId()); + } else { + // 打开群红包弹窗 + new LuckyMoneyDialog(context, luckyMoneyInfo, message.getUuid()).show(); + } + } else { + SingleToastUtil.showToast("你已不在群内"); + } + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_lucky_money; + } + + @Override + protected void inflateContentView() { + layout = findViewById(R.id.rl_lucky_money_msg_view_holder); + greetingView = findViewById(R.id.tv_lucky_money_greeting); + IMMessage luckyMoneyMessage = IMNetEaseManager.get().queryMessageByUuid(message.getUuid()); + Log.e(TAG, "inflateContentView: lucky money message: " + luckyMoneyMessage); + LuckyMoneyAttachment luckyMoneyAttachment; + if (luckyMoneyMessage == null) { + luckyMoneyAttachment = (LuckyMoneyAttachment) message.getAttachment(); + IMNetEaseManager.get().saveMessageToLocal(message); + luckyMoneyInfo = luckyMoneyAttachment.getLuckyMoneyInfo(); + if (luckyMoneyInfo.getClaimStatus() == 0) { + luckyMoneyInfo.setClaimStatus(luckyMoneyInfo.getStatus()); + } + message.setLocalExtension(LuckyMoneyInfo.convertToMap(luckyMoneyInfo)); + IMNetEaseManager.get().updateLuckyMoneyMessage(message.getUuid(), luckyMoneyInfo); + } else { + luckyMoneyAttachment = (LuckyMoneyAttachment) luckyMoneyMessage.getAttachment(); + if (luckyMoneyMessage.getLocalExtension() == null) { + luckyMoneyInfo = luckyMoneyAttachment.getLuckyMoneyInfo(); + } else { + luckyMoneyInfo = LuckyMoneyInfo.convertMapToObject(luckyMoneyMessage.getLocalExtension()); + } + if (luckyMoneyInfo.getClaimStatus() == 0) { + luckyMoneyInfo.setClaimStatus(luckyMoneyInfo.getStatus()); + } + luckyMoneyMessage.setLocalExtension(LuckyMoneyInfo.convertToMap(luckyMoneyInfo)); + IMNetEaseManager.get().updateLuckyMoneyMessage(luckyMoneyMessage.getUuid(), luckyMoneyInfo); + } + Log.e(TAG, "inflateContentView: message: " + message.getUuid()); + Log.e(TAG, "inflateContentView: attachment:" + luckyMoneyInfo); + if (luckyMoneyInfo.getMessage() != null && !Objects.equals("", luckyMoneyInfo.getMessage())) { + greetingView.setText(luckyMoneyInfo.getMessage()); + } + layout.setOnClickListener(this); + } + + @Override + protected void bindContentView() { + Log.e(TAG, "bindContentView: "); + } + + @Override + protected int leftBackground() { + if (luckyMoneyInfo.getClaimStatus() == LuckyMoneyInfo.STATE_NOT_OPEN) { + return R.drawable.lucky_money_msg_undraw; + } else { + return R.drawable.lucky_money_msg_draw; + } + } + + @Override + protected int rightBackground() { + if (luckyMoneyInfo.getClaimStatus() == LuckyMoneyInfo.STATE_NOT_OPEN) { + return R.drawable.lucky_money_msg_undraw; + } else { + return R.drawable.lucky_money_msg_draw; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyTipsViewHolder.java b/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyTipsViewHolder.java new file mode 100644 index 000000000..7f5f09724 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/viewholder/LuckyMoneyTipsViewHolder.java @@ -0,0 +1,87 @@ +package com.yizhuan.erban.luckymoney.viewholder; + +import android.support.v4.content.ContextCompat; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.util.Log; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyTipsAttachment; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; + +import java.util.Objects; + +/** + * Created by MadisonRong on 02/07/2018. + */ + +public class LuckyMoneyTipsViewHolder extends MsgViewHolderBase { + + private static final String TAG = "LuckyMoneyTipsViewHolde"; + + public LuckyMoneyTipsViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected boolean isShowHeadImage() { + return false; + } + + @Override + protected boolean isMiddleItem() { + return true; + } + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_lucky_money_receive; + } + + @Override + protected void inflateContentView() { + TextView tipsView = findViewById(R.id.tv_lucky_money_tips); + LuckyMoneyTipsAttachment luckyMoneyAttachment = (LuckyMoneyTipsAttachment) message.getAttachment(); + LuckyMoneyInfo luckyMoneyInfo = luckyMoneyAttachment.getLuckyMoneyInfo(); + String uid = String.valueOf(AuthModel.get().getCurrentUid()); + Log.e(TAG, "inflateContentView: -----------------"); + Log.e(TAG, "inflateContentView: currentUid: " + uid); + Log.e(TAG, "inflateContentView: senderUid: " + luckyMoneyInfo.getSenderUid()); + Log.e(TAG, "inflateContentView: receiveUid: " + luckyMoneyInfo.getReceiveUid()); + Log.e(TAG, "inflateContentView: -----------------"); + if (Objects.equals(uid, String.valueOf(luckyMoneyInfo.getReceiveUid()))) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + String content = String.format("你领取了%s的红包", luckyMoneyInfo.getNick()); + builder.append(content); + builder.setSpan(new ForegroundColorSpan( + ContextCompat.getColor(context, R.color.color_fe555a)), + content.length() - 2, content.length(), + Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + tipsView.setText(builder); + } else if (Objects.equals(uid, String.valueOf(luckyMoneyInfo.getSenderUid()))) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + String content = String.format("%s领取了你的红包", luckyMoneyInfo.getReceiveNick()); + builder.append(content); + builder.setSpan(new ForegroundColorSpan( + ContextCompat.getColor(context, R.color.color_fe555a)), + content.length() - 2, content.length(), + Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + tipsView.setText(builder); + } + } + + @Override + protected void bindContentView() { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/luckymoney/viewmodel/LuckyMoneyViewModel.java b/app/src/main/java/com/yizhuan/erban/luckymoney/viewmodel/LuckyMoneyViewModel.java new file mode 100644 index 000000000..374ee9b25 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/luckymoney/viewmodel/LuckyMoneyViewModel.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.luckymoney.viewmodel; + +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by MadisonRong on 05/06/2018. + */ + +public class LuckyMoneyViewModel extends BaseViewModel { + + private static final String TAG = "LuckyMoneyViewModel"; + + public Single> getLuckyMoneyMemberList() { + return Single.create(e -> { + ArrayList memberInfoList = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + TeamMemberInfo memberInfo = new TeamMemberInfo(); + memberInfo.setUid(i); + memberInfo.setNick("家族成员名字要限制在十个字以内" + i); + memberInfoList.add(memberInfo); + } + e.onSuccess(memberInfoList); + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/module/Extras.java b/app/src/main/java/com/yizhuan/erban/module/Extras.java new file mode 100644 index 000000000..b170626f4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/module/Extras.java @@ -0,0 +1,16 @@ +package com.yizhuan.erban.module; + +public interface Extras { + + String EXTRA_JUMP_P2P = "EXTRA_JUMP_P2P"; + + String EXTRA_DATA = "data"; + + String EXTRA_FROM = "from"; + + String EXTRA_FROM_NOTIFICATION = "from_notification"; + + // 参数 + String EXTRA_ACCOUNT = "account"; + +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/ImpactValueLayout.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/ImpactValueLayout.java new file mode 100644 index 000000000..edb32ee46 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/ImpactValueLayout.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.monsterhunting; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.animator.AbstractPathAnimator; +import com.yizhuan.xchat_android_library.animator.PathAnimator; +import com.yizhuan.erban.ui.gift.widget.StrokeTextView; + +public class ImpactValueLayout extends RelativeLayout { + + private AbstractPathAnimator mAnimator; + + public ImpactValueLayout(Context context) { + super(context); + init(null, 0); + } + + public ImpactValueLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs, 0); + } + + public ImpactValueLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs, defStyleAttr); + } + + private void init(AttributeSet attrs, int defStyleAttr) { + + final TypedArray a = getContext().obtainStyledAttributes( + attrs, R.styleable.HeartLayout, defStyleAttr, 0); + + mAnimator = new PathAnimator(AbstractPathAnimator.Config.fromTypeArray(a)); + + a.recycle(); + } + + public AbstractPathAnimator getAnimator() { + return mAnimator; + } + + public void setAnimator(AbstractPathAnimator animator) { + clearAnimation(); + mAnimator = animator; + } + + public void clearAnimation() { + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).clearAnimation(); + } + removeAllViews(); + } + + public void addImpact(int impactValue) { + View view = LayoutInflater.from(getContext()).inflate(R.layout.monster_impact_value_view, null); + StrokeTextView impactValueView = view.findViewById(R.id.room_monster_impact_value); + LayoutParams layoutParams= new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); + layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE); + impactValueView.setLayoutParams(layoutParams); + impactValueView.setText("-" + String.valueOf(impactValue)); + mAnimator.start(impactValueView, this); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterEscapeDialog.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterEscapeDialog.java new file mode 100644 index 000000000..67e8ae0af --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterEscapeDialog.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.monsterhunting; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.manager.MonsterDataManager; + +/** + * Created by MadisonRong on 03/04/2018. + */ + +public class MonsterEscapeDialog extends DialogFragment implements View.OnClickListener { + + private static final String TAG = "MonsterEscapeDialog"; + + private ImageView monsterImageView; + private TextView confirmView; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + Window window = getDialog().getWindow(); + // setup window and width + View view = inflater.inflate(R.layout.dialog_monster_escape, window.findViewById(android.R.id.content), false); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); +// window.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtil.dip2px(getContext(), 327)); + setCancelable(false); + init(view); + return view; + } + + private void init(View view) { + monsterImageView = view.findViewById(R.id.iv_monster_image); + confirmView = view.findViewById(R.id.tv_operation_ok); + confirmView.setOnClickListener(this); + + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + ImageLoadUtils.loadImage(getContext(), monsterInfo.getMonsterImg(), monsterImageView); + } + + public void show(FragmentManager fragmentManager) { + this.show(fragmentManager, TAG); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_operation_ok: + dismissAllowingStateLoss(); + if (getActivity() != null) { + getActivity().finish(); + } + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingActivity.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingActivity.java new file mode 100644 index 000000000..8335fbfb8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingActivity.java @@ -0,0 +1,701 @@ +package com.yizhuan.erban.monsterhunting; + +import android.content.Context; +import android.content.Intent; +import android.os.CountDownTimer; +import android.support.v7.widget.LinearLayoutManager; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.widget.GiftV2View; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityMonsterHuntingBinding; +import com.yizhuan.erban.monsterhunting.bean.UpdateMyGoldInfo; +import com.yizhuan.erban.monsterhunting.bean.AttackMonsterResultInfo; +import com.yizhuan.erban.monsterhunting.viewmodel.MonsterHuntingViewModel; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.widget.MagicAdapter; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.KickOutEvent; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterAttackInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterEvent; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingResult; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterProtocol; +import com.yizhuan.xchat_android_core.monsterhunting.manager.MonsterDataManager; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.statistic.LogFactory; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.LogProtocol; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_NOTI_SUB_GAME_END; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_NOTI_SUB_GAME_RESULT; + + +/** + * Created by MadisonRong on 29/03/2018. + */ + +@ActLayoutRes(R.layout.activity_monster_hunting) +public class MonsterHuntingActivity extends BaseBindingActivity { + + private static final String TAG = "MonsterHuntingActivity"; + + private MonsterHuntingViewModel viewModel; + private double mGoldNum; + private GiftV2View giftView; + private MagicAdapter mMagicAdapter; + private volatile int monsterTotalBlood = 10; + private volatile int monsterRemainBlood = 10; + private CountDownTimer countDownTimer; + private volatile int sequence; + private volatile int currentMonsterStatus = MonsterInfo.MONSTER_STATUS_DID_APPEAR; + private volatile MonsterHuntingRewardDialog monsterHuntingRewardDialog; + private volatile MonsterEscapeDialog monsterEscapeDialog; + private volatile long beforeDisappearSeconds = 0; + + private List infoList; + private Disposable subscribe; + + public static void start(Context context) { + context.startActivity(new Intent(context, MonsterHuntingActivity.class)); + } + + + @Override + protected void init() { + initial(); + IMNetEaseManager.get().getChatRoomEventObservable() + .compose(bindToLifecycle()) + .subscribe(this::onReceiveRoomEvent); + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .compose(bindToLifecycle()) + .subscribe(this::onReceiveMonsterEvent); + + EventBus.getDefault().register(this); + } + + @Override + protected void onResume() { + super.onResume(); + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + if (monsterInfo.getMonsterStatus() != MonsterInfo.MONSTER_STATUS_DID_APPEAR) { + finish(); + } + if (beforeDisappearSeconds == 0){ + finish(); + } + intervalAttack(); + sequence = 0; + // 自动打怪代码,需要的时候就打开注释运行程序 +// Observable.interval(250, TimeUnit.MILLISECONDS) +// .compose(bindToLifecycle()) +// .observeOn(AndroidSchedulers.mainThread()) +// .subscribe(integer -> { +// if (magicLayout.getVisibility() == View.VISIBLE) { +// magicRecyclerView.smoothScrollToPosition(new Random().nextInt(mMagicAdapter.getItemCount())); +// magicRecyclerView.getChildAt(new Random().nextInt(magicRecyclerView.getChildCount())).performClick(); +// tvSendMagic.performClick(); +// } +// }); + } + + private void intervalAttack() { + subscribe = Observable.interval(200, TimeUnit.MILLISECONDS) + .compose(bindToLifecycle()) + .observeOn(AndroidSchedulers.mainThread()) + .filter(aLong -> infoList != null && infoList.size() > 0) + .flatMap(aLong -> { + return Observable.just(infoList.get(0)); + }).subscribe(monsterAttackInfo -> { + if (monsterAttackInfo != null) { + giftView.onReceiveMonsterAttackMsg(monsterAttackInfo, mBinding.rlMonsterLayout); + infoList.remove(0); + } + }, throwable -> { + intervalAttack(); + }); + } + + private void onReceiveMonsterEvent(MonsterEvent monsterEvent) { + if (monsterEvent == null) return; + switch (monsterEvent.getEvent()) { + case MonsterEvent.ANIMATION_LOADED: + // 资源加载完毕,关掉 loading + getDialogManager().dismissDialog(); + // 开始 MonsterLayout 的进场动画 + MonsterHuntingAnimationManager.get().monsterLayoutShowIn(this, mBinding.rlMonsterLayout); + break; + + case MonsterEvent.MONSTER_APPEAR_ANIMATION_FINISHED: + case MonsterEvent.MONSTER_ATTACK_ANIMATION_FINISHED: + MonsterHuntingSvgaManager.get().displayNormalAnimation(); + // monsterLayout 的进场动画结束,开始 monsterInfoLayout 的进场动画 + MonsterHuntingAnimationManager.get().monsterInfoLayoutShowIn(this, mBinding.rlMonsterInfo); + break; + + case MonsterEvent.MONSTER_DEFAT_ANIMATION_START: + // 结束倒计时 + if (infoList != null) { + infoList.clear(); + } + if (subscribe != null) { + subscribe.dispose(); + } + cancelTimer(); + // 收起其他控件 + MonsterHuntingAnimationManager.get().monsterInfoLayoutShowOut(this, mBinding.rlMonsterInfo); + MonsterHuntingAnimationManager.get().magicLayoutShowOut(this, mBinding.rlDialogBottomMagic); + MonsterHuntingAnimationManager.get().countDownTimerShowOut(this, mBinding.tvCountdown); + MonsterHuntingAnimationManager.get().closeImgShowOut(this, mBinding.ivMonsterHuntingExit); + MonsterHuntingSvgaManager.get().displayDefeatAnimation(); + break; + + case MonsterEvent.MONSTER_DEFEAT_ANIMATION_FINISHED: + // 怪兽被打爆后,展示抽奖动画 + MonsterHuntingSvgaManager.get().displayDrawAnimation(); + break; + + case MonsterEvent.MONSTER_LOTTERY_ANIMATION_FINISHED: + // 结束倒计时 + cancelTimer(); + // 收起其他控件 + MonsterHuntingAnimationManager.get().monsterLayoutShowOut(this, mBinding.rlMonsterLayout); + // 展示抽奖结果 + if (monsterHuntingRewardDialog == null) { + monsterHuntingRewardDialog = new MonsterHuntingRewardDialog(); + monsterHuntingRewardDialog.show(getSupportFragmentManager()); + currentMonsterStatus = MonsterInfo.MONSTER_RESULT_SHOWN; + } + break; + + case MonsterEvent.MONSTER_HUNTING_TIME_OUT: + // 结束倒计时 + cancelTimer(); + // 收起其他控件 + MonsterHuntingAnimationManager.get().monsterLayoutShowOut(this, mBinding.rlMonsterLayout); + MonsterHuntingAnimationManager.get().monsterInfoLayoutShowOut(this, mBinding.rlMonsterInfo); + MonsterHuntingAnimationManager.get().magicLayoutShowOut(this, mBinding.rlDialogBottomMagic); + MonsterHuntingAnimationManager.get().countDownTimerShowOut(this, mBinding.tvCountdown); + MonsterHuntingAnimationManager.get().closeImgShowOut(this, mBinding.ivMonsterHuntingExit); + // 怪兽逃跑了 + if (monsterEscapeDialog == null) { + monsterEscapeDialog = new MonsterEscapeDialog(); + monsterEscapeDialog.show(getSupportFragmentManager()); + } + break; + + case MonsterEvent.MONSTER_LAYOUT_SHOW_IN_ANIMATION_START: + mBinding.rlMonsterLayout.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_LAYOUT_SHOW_OUT_ANIMATION_FINISHED: + mBinding.rlMonsterLayout.setVisibility(View.INVISIBLE); + break; + + case MonsterEvent.MONSTER_LAYOUT_SHOW_IN_ANIMATION_FINISHED: + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + if (monsterInfo.getAppearTime() + 5 * 1000 > monsterInfo.getServerTime()) { + // 如果打怪兽刚开始,则播放进场动画 + // 同时开始怪兽的进场动画 + MonsterHuntingSvgaManager.get().displayAppearAnimation(); + } else { + // 否则直接显示怪兽 + MonsterHuntingSvgaManager.get().displayNormalAnimation(); + // monsterLayout 的进场动画结束,开始 monsterInfoLayout 的进场动画 + MonsterHuntingAnimationManager.get().monsterInfoLayoutShowIn(this, mBinding.rlMonsterInfo); + } + break; + + case MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_IN_ANIMATION_START: + mBinding.rlMonsterInfo.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_OUT_ANIMATION_FINISHED: + mBinding.rlMonsterInfo.setVisibility(View.INVISIBLE); + break; + + case MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_IN_ANIMATION_FINISHED: + // monsterInfoLayout 的进场动画结束, + // 开始 magicLayout, countDownTimer 和 closeImg 的进场动画 + MonsterHuntingAnimationManager.get().magicLayoutShowIn(this, mBinding.rlDialogBottomMagic); + MonsterHuntingAnimationManager.get().countDownTimerShowIn(this, mBinding.tvCountdown); + MonsterHuntingAnimationManager.get().closeImgShowIn(this, mBinding.ivMonsterHuntingExit); + break; + + case MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_IN_ANIMATION_START: + mBinding.rlDialogBottomMagic.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_OUT_ANIMATION_FINISHED: + mBinding.rlDialogBottomMagic.setVisibility(View.INVISIBLE); + break; + + case MonsterEvent.MONSTER_COUNT_DOWN_SHOW_IN_ANIMATION_START: + mBinding.tvCountdown.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_COUNT_DOWN_SHOW_OUT_ANIMATION_FINISHED: + mBinding.tvCountdown.setVisibility(View.INVISIBLE); + break; + + case MonsterEvent.MONSTER_CLOSE_SHOW_IN_ANIMATION_START: + mBinding.ivMonsterHuntingExit.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_CLOSE_SHOW_OUT_ANIMATION_FINISHED: + mBinding.ivMonsterHuntingExit.setVisibility(View.INVISIBLE); + break; + + case MonsterEvent.MONSTER_IMPACT_SHOW_OUT_ANIMATION_START: +// impactValueView.setVisibility(View.VISIBLE); + break; + + case MonsterEvent.MONSTER_IMPACT_SHOW_OUT_ANIMATION_FINISHED: +// impactValueView.setVisibility(View.INVISIBLE); + break; + + } + } + + private void cancelTimer() { + if (countDownTimer != null) { + countDownTimer.cancel(); + } + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + if (roomEvent == null) return; + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.MONSTER_HUNTING: + if (mBinding.rlMonsterLayout.getVisibility() == View.VISIBLE) { + // 当怪兽显示时才出现发魔法的动画 + onReceiveMagicMsg(roomEvent.getMonsterAttackReceiveInfo()); + + //每次攻击怪兽打log到阿里云 + MonsterAttackInfo monsterAttackInfo = roomEvent.getMonsterAttackReceiveInfo(); + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_VERBOSE, + LogProtocol.Topic.TOPIC_BUSINESS_LOG, + LogProtocol.Event.EVENT_MONSTER_ONGOING_MONSTER + ).append(LogProtocol.CommonKey.KEY_UID.getName(), String.valueOf(AuthModel.get().getCurrentUid())) + .append("monsterId", String.valueOf(monsterAttackInfo.getMonsterId())) + .append("remainBlood", String.valueOf(monsterAttackInfo.getMonsterRemainBlood())) + .append("beforeDisappearSeconds", String.valueOf(JavaUtil.str2long(monsterAttackInfo.getRemainMills()) / 1000.0f))); + } + + break; + + case RoomEvent.MONSTER_HUNTING_ANIMATION_FINISHED: + // onReceiveMagicAnimationFinishedMsg(roomEvent.getMonsterAttackReceiveInfo()); + displayImpactAnimation(roomEvent.getMonsterAttackReceiveInfo().getImpactValue()); + break; + + case RoomEvent.WALLET_UPDATE: + break; + + case RoomEvent.MONSTER_STATUS_CHANGED: + MonsterProtocol.DataBean dataBean = roomEvent.getMonsterStatusAttachment().getDataBean(); + Log.e(TAG, "onResume room event: " + dataBean); + // 判断是否为当前房间的怪兽消息 + if (Objects.equals(MonsterDataManager.get().getCurrentRoomMonsterInfo().getAppearRoomUid(), + dataBean.getAppearRoomUid())) { + switch (dataBean.getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_DID_DEAD: + switch (roomEvent.getMonsterStatusAttachment().getSecond()) { + case CUSTOM_NOTI_SUB_GAME_END: + if (currentMonsterStatus == MonsterInfo.MONSTER_STATUS_DID_APPEAR) { + manualShowDefeatAnimation(); + } + break; + } + break; + + case MonsterInfo.MONSTER_STATUS_DID_LEAVE: + if (currentMonsterStatus == MonsterInfo.MONSTER_STATUS_DID_APPEAR) { + manualShowEscapeAnimation(); + } + break; + } + } + break; + + case RoomEvent.MONSTER_HUNTING_RESULT: + MonsterHuntingResult result = roomEvent.getMonsterHuntingResultAttachment().getResult(); + Log.e(TAG, "onResume: room event monster result: " + result); + // 判断是否为当前房间的怪兽消息 + if (Objects.equals(MonsterDataManager.get().getCurrentRoomMonsterInfo().getAppearRoomUid(), + result.getMonster().getAppearRoomUid())) { + switch (result.getMonster().getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_DID_DEAD: + switch (roomEvent.getMonsterHuntingResultAttachment().getSecond()) { + case CUSTOM_NOTI_SUB_GAME_RESULT: + if (currentMonsterStatus == MonsterInfo.MONSTER_STATUS_DID_DEAD) { + + //怪兽结果 打log 到 阿里云 + StatisticManager.Instance().sendAliyunLog(LogFactory.create( + LogProtocol.LogLevel.LEVEL_VERBOSE, + LogProtocol.Topic.TOPIC_BUSINESS_LOG, + LogProtocol.Event.EVENT_MONSTER_GAME_RESULT + ).append(LogProtocol.CommonKey.KEY_UID.getName(), String.valueOf(AuthModel.get().getCurrentUid())) + .append("monsterId", String.valueOf(MonsterDataManager.get().getCurrentRoomMonsterInfo().getMonsterId())) + .append("monsterStatus", String.valueOf(result.getMonster().getMonsterStatus())) + .append("luckMan_erbanNo", String.valueOf(result.getLuckyDog().getErbanNo()))); + + // 奖励结果出来了 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_LOTTERY_ANIMATION_FINISHED)); + } + break; + } + break; + } + } + break; + + case RoomEvent.KICK_OUT_ROOM: + finish(); + break; + + case RoomEvent.ADD_BLACK_LIST: + String account = roomEvent.getAccount(); + if (Objects.equals(account, + String.valueOf(AuthModel.get().getCurrentUid()))) { + finish(); + } + break; + } + } + + private void manualShowDefeatAnimation() { + currentMonsterStatus = MonsterInfo.MONSTER_STATUS_DID_DEAD; + // 怪兽已经挂了 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_DEFAT_ANIMATION_START)); + } + + private void manualShowEscapeAnimation() { + currentMonsterStatus = MonsterInfo.MONSTER_STATUS_DID_LEAVE; + // 怪兽逃跑了 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_HUNTING_TIME_OUT) + .setType(MonsterEvent.TYPE_BROADCAST)); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + cancelTimer(); + // 释放 SvgaManager,避免内存泄露 + MonsterHuntingSvgaManager.get().release(); + + EventBus.getDefault().unregister(this); + } + + private void initial() { + viewModel = new MonsterHuntingViewModel(); + viewModel.attackMonsterResultInfo.addOnPropertyChangedCallback(new android.databinding.Observable.OnPropertyChangedCallback() { + @Override + public void onPropertyChanged(android.databinding.Observable sender, int propertyId) { + AttackMonsterResultInfo resultInfo = (AttackMonsterResultInfo) sender; + switch (resultInfo.getStatus()){ + case 1: + if (resultInfo.getMonsterAttackInfo() != null) + attackMonsterSuccess(resultInfo.getMonsterAttackInfo()); + break; + case 2: + attackMonsterFail(resultInfo.getCode(), resultInfo.getErrorMessage()); + break; + case 3: + attackMonsterFail(-1, resultInfo.getErrorMessage()); + break; + default: + break; + } + } + }); + viewModel.updateMyGoldInfo.addOnPropertyChangedCallback(new android.databinding.Observable.OnPropertyChangedCallback() { + @Override + public void onPropertyChanged(android.databinding.Observable sender, int propertyId) { + UpdateMyGoldInfo updateInfo = (UpdateMyGoldInfo) sender; + if (updateInfo.isSucceed()) { + updateMyGoldInternal(updateInfo.getWalletInfo()); + } else { + updateMyGoldInternalFail(); + } + } + }); + + mBinding.rlMonsterImpactValue.getAnimator().getmConfig().initX = mBinding.roomMonsterSvga.getWidth() / 2; + mBinding.rlMonsterImpactValue.getAnimator().getmConfig().initY = mBinding.roomMonsterSvga.getHeight() / 2; + + mBinding.ivMonsterHuntingExit.setOnClickListener(this); + mBinding.tvCharge.setOnClickListener(this); + mBinding.tvSend.setOnClickListener(this); + mBinding.ivMonsterHuntingIntroduction.setOnClickListener(this); + + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + beforeDisappearSeconds = monsterInfo.getBeforeDisappearSeconds(); + if (monsterInfo != null) { + switch (monsterInfo.getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_DID_APPEAR: + if (monsterInfo.getBeforeDisappearSeconds() > 0) { + // 初始化 SVGA parser + MonsterHuntingSvgaManager.get().initParser(this, mBinding.roomMonsterSvga); + // 预加载 SVGA 资源 + MonsterHuntingSvgaManager.get().preLoadMonsterAnimation( + monsterInfo.getAppearSvg(), + monsterInfo.getNormalSvg(), + monsterInfo.getAttackSvg(), + monsterInfo.getDefeatSvg()); + + // 更新自己的金币 + viewModel.updateMyGold(); + // 更新魔法礼物列表 + updateMagicList(); + // 根据怪兽状态显示 UI + updateMonsterInfo(monsterInfo); + } else { + finish(); + } + break; + + case MonsterInfo.MONSTER_STATUS_DID_DEAD: + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_DEFAT_ANIMATION_START) + .setType(MonsterEvent.TYPE_ALREADY_FINISHED)); + break; + + case MonsterInfo.MONSTER_STATUS_DID_LEAVE: + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_HUNTING_TIME_OUT) + .setType(MonsterEvent.TYPE_ALREADY_FINISHED)); + break; + } + } + + getDialogManager().showProgressDialog(this, "怪兽加载中", + false, true, null, dialog -> finish()); + } + + private void updateMagicList() { + MagicModel.get().getRemoteMagicList().subscribe((magicInfos, throwable) -> { + if (!ListUtils.isListEmpty(magicInfos)) { + for (MagicInfo magicInfo : magicInfos) { + magicInfo.setMagicType(MagicInfo.MONSTER_MAGIC); + } + mMagicAdapter = new MagicAdapter(this, magicInfos); + mBinding.recyclerViewMagic.setAdapter(mMagicAdapter); + mBinding.recyclerViewMagic.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + } else if (throwable != null) { +// Toast.makeText(this, "获取魔法列表失败,请重试!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("获取魔法列表失败,请重试!"); + } + }); + } + + + private void updateMyGoldInternal(WalletInfo walletInfo) { + mGoldNum = walletInfo.getGoldNum(); + mBinding.tvGold.setText(this.getResources().getString(R.string.gold_num_text, mGoldNum)); + } + + private void updateMyGoldInternalFail() { +// Toast.makeText(this, "获取金币失败,请重试!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("获取金币失败,请重试!"); + } + + private void updateMonsterInfo(MonsterInfo monsterInfo) { + mBinding.tvMonsterName.setText(monsterInfo.getMonsterName()); + monsterTotalBlood = monsterInfo.getTotalBlood(); + mBinding.tvMonsterTotalHp.setText(String.valueOf(monsterTotalBlood)); + monsterRemainBlood = monsterInfo.getRemainBlood(); + mBinding.tvMonsterHp.setText(String.valueOf(monsterRemainBlood)); + mBinding.pbMonsterHp.setMax(monsterTotalBlood); + mBinding.pbMonsterHp.setProgress(monsterRemainBlood); + long timeLeft = monsterInfo.getBeforeDisappearSeconds(); + countDownTimer = new CountDownTimer( + timeLeft * 1000, + 1000) { + @Override + public void onTick(long millisUntilFinished) { + beforeDisappearSeconds--; + mBinding.tvCountdown.setText(TimeUtils.ms2MS(millisUntilFinished)); + } + + @Override + public void onFinish() { + beforeDisappearSeconds = 0; + mBinding.tvCountdown.setText("00:00"); + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_HUNTING_TIME_OUT)); + } + }; + countDownTimer.start(); + } + + @Override + public void onBackPressed() { + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + switch (monsterInfo.getMonsterStatus()) { + case MonsterInfo.MONSTER_STATUS_DID_DEAD: + case MonsterInfo.MONSTER_STATUS_DID_LEAVE: + super.onBackPressed(); + Log.e(TAG, "onBackPressed: "); + break; + + case MonsterInfo.MONSTER_STATUS_DID_APPEAR: + new QuitConfirmDialog().show(getSupportFragmentManager()); + break; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_monster_hunting_exit: + new QuitConfirmDialog().show(getSupportFragmentManager()); + break; + + case R.id.iv_monster_hunting_introduction: + new MonsterHuntingIntroductionDialog().show(getSupportFragmentManager()); + break; + + case R.id.tv_charge: + ChargeActivity.start(this); + break; + + case R.id.tv_send: + if (mMagicAdapter != null && mMagicAdapter.getItemCount() > 0 && + monsterRemainBlood > 0) { + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + attackMonster(monsterInfo); + } + break; + } + } + + private void attackMonster(MonsterInfo monsterInfo) { + viewModel.attackMonster(String.valueOf(monsterInfo.getMonsterId()), + String.valueOf(monsterInfo.getAppearRoomUid()), + String.valueOf(mMagicAdapter.getCurrentMagicInfo().getMagicId())); + } + + private void attackMonsterSuccess(MonsterAttackInfo monsterAttackInfo) { + // 设置魔法底图,动画时候显示使用 + monsterAttackInfo.setMagicIcon(mMagicAdapter.getCurrentMagicInfo().getIcon()); + } + + private void attackMonsterFail(int code, String errorMsg) { + switch (code) { + case 6502: + toast(errorMsg); + monsterRemainBlood = 0; + displayImpactAnimation(mBinding.pbMonsterHp.getProgress()); + mBinding.pbMonsterHp.incrementProgressBy(monsterRemainBlood - mBinding.pbMonsterHp.getProgress()); + mBinding.tvMonsterHp.setText(String.valueOf(monsterRemainBlood)); + // 怪兽已被打败,清空缓存队列 + infoList.clear(); + if (subscribe != null) { + subscribe.dispose(); + } + manualShowDefeatAnimation(); + break; + + case 6503: + toast(errorMsg); + cancelTimer(); + manualShowEscapeAnimation(); + break; + + default: + toast(errorMsg); + } + } + + public void onReceiveMagicMsg(MonsterAttackInfo monsterAttackReceiveInfo) { + if (monsterAttackReceiveInfo == null || currentMonsterStatus != MonsterInfo.MONSTER_STATUS_DID_APPEAR) + return; + if (giftView == null) { + giftView = (GiftV2View) mBinding.vsMagicView.getViewStub().inflate(); + } + if (infoList == null) { + infoList = new ArrayList<>(); + } + if (infoList.size() > 200) { + Iterator iterator = infoList.iterator(); + for (int i = 0; i < 50; i++) { + if (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + } + if (monsterAttackReceiveInfo.getUid().equals(AuthModel.get().getCurrentUid() + "")) { + giftView.onReceiveMonsterAttackMsg(monsterAttackReceiveInfo, mBinding.rlMonsterLayout); + } else { + infoList.add(monsterAttackReceiveInfo); + } + onReceiveMagicAnimationFinishedMsg(monsterAttackReceiveInfo); + } + + public void onReceiveMagicAnimationFinishedMsg(MonsterAttackInfo monsterAttackReceiveInfo) { + updateRemainBlood(monsterAttackReceiveInfo); + } + + private void updateRemainBlood(MonsterAttackInfo monsterAttackReceiveInfo) { + if (sequence <= monsterAttackReceiveInfo.getSequence()) { + sequence = monsterAttackReceiveInfo.getSequence(); + monsterRemainBlood = Integer.parseInt(monsterAttackReceiveInfo.getMonsterRemainBlood()); + Log.e(TAG, String.format(Locale.getDefault(), "attackMonsterSuccess: monsterTotalBlood: %s, monsterRemainBlood: %s", + monsterTotalBlood, monsterRemainBlood)); + mBinding.pbMonsterHp.incrementProgressBy(monsterRemainBlood - mBinding.pbMonsterHp.getProgress()); + mBinding.tvMonsterHp.setText(String.valueOf(monsterRemainBlood)); + if (monsterRemainBlood == 0) { + manualShowDefeatAnimation(); + } + } + } + + private void displayImpactAnimation(int impactValue) { + mBinding.rlMonsterImpactValue.addImpact(impactValue); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onKickedOutEvent(KickOutEvent event) { + // 被踢下线,直接退出该页面 + finish(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingAnimationManager.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingAnimationManager.java new file mode 100644 index 000000000..afa4d574a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingAnimationManager.java @@ -0,0 +1,259 @@ +package com.yizhuan.erban.monsterhunting; + +import android.content.Context; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterEvent; +import com.yizhuan.xchat_android_core.monsterhunting.SimpleAnimationListener; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.processors.PublishProcessor; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 03/04/2018. + */ + +public class MonsterHuntingAnimationManager { + + private PublishProcessor monsterEventPublishProcessor; + + private static class MonsterHuntingAnimationManagerHolder { + private static final MonsterHuntingAnimationManager instance = new MonsterHuntingAnimationManager(); + } + + public static MonsterHuntingAnimationManager get() { + return MonsterHuntingAnimationManagerHolder.instance; + } + + public PublishProcessor getMonsterEventObservable() { + if (monsterEventPublishProcessor == null) { + synchronized (IMNetEaseManager.class) { + if (monsterEventPublishProcessor == null) { + monsterEventPublishProcessor = PublishProcessor.create(); + monsterEventPublishProcessor.subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()); + } + } + } + return monsterEventPublishProcessor; + } + + public void monsterLayoutShowIn(Context context, RelativeLayout monsterLayout) { + Animation leftInAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_left_in); + leftInAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_LAYOUT_SHOW_IN_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_LAYOUT_SHOW_IN_ANIMATION_FINISHED)); + } + }); + monsterLayout.clearAnimation(); + monsterLayout.startAnimation(leftInAnimation); + } + + public void monsterLayoutShowOut(Context context, RelativeLayout monsterLayout) { + Animation leftOutAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_left_out); + leftOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_LAYOUT_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_LAYOUT_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + monsterLayout.clearAnimation(); + monsterLayout.startAnimation(leftOutAnimation); + } + + public void monsterInfoLayoutShowIn(Context context, RelativeLayout monsterInfoLayout) { + Animation leftInAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_left_in); + leftInAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_IN_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_IN_ANIMATION_FINISHED)); + } + }); + monsterInfoLayout.clearAnimation(); + monsterInfoLayout.startAnimation(leftInAnimation); + } + + public void monsterInfoLayoutShowOut(Context context, RelativeLayout monsterInfoLayout) { + Animation leftOutAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_left_out); + leftOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_INFO_LAYOUT_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + monsterInfoLayout.clearAnimation(); + monsterInfoLayout.startAnimation(leftOutAnimation); + } + + public void magicLayoutShowIn(Context context, RelativeLayout magicLayout) { + Animation bottomInAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_bottom_in); + bottomInAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_IN_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_IN_ANIMATION_FINISHED)); + } + }); + magicLayout.clearAnimation(); + magicLayout.startAnimation(bottomInAnimation); + } + + public void magicLayoutShowOut(Context context, RelativeLayout magicLayout) { + Animation bottomOutAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_bottom_out); + bottomOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_MAGIC_LAYOUT_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + magicLayout.clearAnimation(); + magicLayout.startAnimation(bottomOutAnimation); + } + + public void countDownTimerShowIn(Context context, TextView countDownTimer) { + Animation topInAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_top_in); + topInAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_COUNT_DOWN_SHOW_IN_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_COUNT_DOWN_SHOW_IN_ANIMATION_FINISHED)); + } + }); + countDownTimer.clearAnimation(); + countDownTimer.startAnimation(topInAnimation); + } + + public void countDownTimerShowOut(Context context, TextView countDownTimer) { + Animation topOutAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_top_out); + topOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_COUNT_DOWN_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_COUNT_DOWN_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + countDownTimer.clearAnimation(); + countDownTimer.startAnimation(topOutAnimation); + } + + public void closeImgShowIn(Context context, ImageView closeImg) { + Animation topInAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_top_in); + topInAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_CLOSE_SHOW_IN_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_CLOSE_SHOW_IN_ANIMATION_FINISHED)); + } + }); + closeImg.clearAnimation(); + closeImg.startAnimation(topInAnimation); + } + + public void closeImgShowOut(Context context, ImageView closeImg) { + Animation topOutAnimation = AnimationUtils.loadAnimation(context, R.anim.anim_top_out); + topOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_CLOSE_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_CLOSE_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + closeImg.clearAnimation(); + closeImg.startAnimation(topOutAnimation); + } + + public void impactViewShowOut(Context context, TextView impactView) { + Animation topOutAnimation = AnimationUtils.loadAnimation(context, R.anim.monster_hunting_impact); + topOutAnimation.setAnimationListener(new SimpleAnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + super.onAnimationStart(animation); + impactView.setVisibility(View.VISIBLE); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_IMPACT_SHOW_OUT_ANIMATION_START)); + } + + @Override + public void onAnimationEnd(Animation animation) { + super.onAnimationEnd(animation); + impactView.setVisibility(View.GONE); + getMonsterEventObservable().onNext(new MonsterEvent(MonsterEvent.MONSTER_IMPACT_SHOW_OUT_ANIMATION_FINISHED)); + } + }); + impactView.clearAnimation(); + impactView.startAnimation(topOutAnimation); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingIntroductionDialog.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingIntroductionDialog.java new file mode 100644 index 000000000..971ff3ffe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingIntroductionDialog.java @@ -0,0 +1,62 @@ +package com.yizhuan.erban.monsterhunting; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * Created by MadisonRong on 02/04/2018. + */ + +public class MonsterHuntingIntroductionDialog extends DialogFragment implements View.OnClickListener { + + private static final String TAG = "MonsterHuntingIntroduct"; + + private TextView confirmTextView; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + Window window = getDialog().getWindow(); + // setup window and width + View view = inflater.inflate(R.layout.dialog_monster_hunting_introduction, window.findViewById(android.R.id.content), false); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + window.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtil.dip2px(getContext(), 431)); + setCancelable(true); + confirmTextView = view.findViewById(R.id.iv_operation_ok); + confirmTextView.setOnClickListener(this); + return view; + } + + public void show(FragmentManager fragmentManager) { + this.show(fragmentManager, TAG); + } + + @Override + public void show(FragmentManager manager, String tag) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_operation_ok: + dismissAllowingStateLoss(); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardDialog.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardDialog.java new file mode 100644 index 000000000..b14bc8e26 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardDialog.java @@ -0,0 +1,155 @@ +package com.yizhuan.erban.monsterhunting; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHunter; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingResult; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingReward; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.manager.MonsterDataManager; +import com.yizhuan.xchat_android_core.monsterhunting.model.MonsterHuntingModel; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; +import java.util.Locale; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 02/04/2018. + */ + +public class MonsterHuntingRewardDialog extends DialogFragment implements View.OnClickListener { + + private static final String TAG = "MonsterHuntingRewardDia"; + + private ImageView closeView; + private ImageView avatarView; + private TextView usernameView; + private TextView userIdView; + private TextView impactValueView; + private TextView rewardCountView; + private RecyclerView rewardRecyclerView; + private ImageView moreRewardView; + private TextView checkDamageView; + private MonsterHuntingRewardsAdapter rewardsAdapter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + Window window = getDialog().getWindow(); + // setup window and width + View view = inflater.inflate(R.layout.dialog_monster_hunting_reward, window.findViewById(android.R.id.content), false); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); +// window.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, UIUtil.dip2px(getContext(), 375)); + setCancelable(false); + init(view); + return view; + } + + private void init(View view) { + closeView = view.findViewById(R.id.iv_monster_hunting_exit); + avatarView = view.findViewById(R.id.iv_luck_man_avatar); + usernameView = view.findViewById(R.id.tv_luck_man_name); + userIdView = view.findViewById(R.id.tv_luck_man_id); + impactValueView = view.findViewById(R.id.tv_impact_value); + rewardCountView = view.findViewById(R.id.tv_reward_title); + rewardRecyclerView = view.findViewById(R.id.rv_reward_things); + moreRewardView = view.findViewById(R.id.iv_reward_things_more); + checkDamageView = view.findViewById(R.id.rl_check_damage); + + closeView.setOnClickListener(this); + moreRewardView.setOnClickListener(this); + checkDamageView.setOnClickListener(this); + + MonsterInfo monsterInfo = MonsterDataManager.get().getCurrentRoomMonsterInfo(); + if (monsterInfo != null) { + MonsterHuntingModel.get().getRoomMonsterHuntingResult(String.valueOf(monsterInfo.getMonsterId())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((monsterHuntingResultServiceResult, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else if (monsterHuntingResultServiceResult != null && monsterHuntingResultServiceResult.isSuccess()) { + if (monsterHuntingResultServiceResult.getData() != null) { + displayResult(monsterHuntingResultServiceResult.getData()); + } + } else if (monsterHuntingResultServiceResult != null && !monsterHuntingResultServiceResult.isSuccess()) { + SingleToastUtil.showToast(monsterHuntingResultServiceResult.getMessage()); + } + }); + } + } + + public void displayResult(MonsterHuntingResult monsterHuntingResult) { + Log.e(TAG, "displayResult() called with: monsterHuntingReward = [" + monsterHuntingResult + "]"); + // 幸运儿 + MonsterHunter luckDog = monsterHuntingResult.getLuckyDog(); + if (luckDog != null) { + ImageLoadUtils.loadAvatar(getContext(), luckDog.getAvatar(), avatarView, true); + usernameView.setText(luckDog.getNick()); + userIdView.setText(String.format(Locale.getDefault(), getContext().getString(R.string.text_user_id), + luckDog.getErbanNo())); + impactValueView.setText(luckDog.getHurt()); + } + // 获得的奖励 + List awards = monsterHuntingResult.getAwards(); + if (awards != null) { + rewardCountView.setText(String.format(Locale.getDefault(), + rewardCountView.getText().toString(), awards.size())); + rewardsAdapter = new MonsterHuntingRewardsAdapter(awards, getContext()); + rewardRecyclerView.setAdapter(rewardsAdapter); + rewardRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), OrientationHelper.HORIZONTAL, false)); + moreRewardView.setVisibility(View.GONE); + } + } + + public void show(FragmentManager fragmentManager) { + this.show(fragmentManager, TAG); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_monster_hunting_exit: + dismissAllowingStateLoss(); + if (getActivity() != null) { + getActivity().finish(); + } + break; + + case R.id.rl_check_damage: + UIHelper.showMonsterResult(getContext(), String.valueOf(MonsterDataManager.get().getCurrentRoomMonsterInfo().getMonsterId())); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardsAdapter.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardsAdapter.java new file mode 100644 index 000000000..286dbd323 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingRewardsAdapter.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.monsterhunting; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.adapters.BaseListRecyclerViewAdapter; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterHuntingReward; + +import java.util.Collection; + +/** + * Created by MadisonRong on 03/04/2018. + */ + +public class MonsterHuntingRewardsAdapter extends BaseListRecyclerViewAdapter { + + private Context context; + + public MonsterHuntingRewardsAdapter(Context context) { + this.context = context; + } + + public MonsterHuntingRewardsAdapter(int capacity, Context context) { + super(capacity); + this.context = context; + } + + public MonsterHuntingRewardsAdapter(Collection collection, Context context) { + super(collection); + this.context = context; + } + + @Override + public MonsterHuntingRewardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new MonsterHuntingRewardViewHolder(LayoutInflater.from(context) + .inflate(R.layout.list_item_monster_hunting_reward, parent, false)); + } + + @Override + public void onBindViewHolder(MonsterHuntingRewardViewHolder holder, int position) { + int pos = holder.getAdapterPosition(); + MonsterHuntingReward reward = get(pos); + ImageLoadUtils.loadRectImage(context, reward.getProdImage(), holder.rewardImageView, + R.drawable.default_cover, UIUtil.dip2px(context, 10)); + switch (Integer.parseInt(reward.getProdType())) { + case MonsterHuntingReward.REWARD_GOLD: + holder.rewardNameView.setText(context.getString(R.string.currency_unit)); + holder.rewardValueView.setVisibility(View.VISIBLE); + holder.rewardValueView.setText(reward.getProdValue()); + break; + case MonsterHuntingReward.REWARD_CAR: + holder.rewardNameView.setText(reward.getProdName()); + holder.rewardValueView.setVisibility(View.VISIBLE); + holder.rewardValueView.setText(reward.getExpireDays() + "天"); + break; + + case MonsterHuntingReward.REWARD_ACCOUNT: + holder.rewardNameView.setText("靓号"); + holder.rewardValueView.setVisibility(View.VISIBLE); + holder.rewardValueView.setText(reward.getProdValue()); + break; + + case MonsterHuntingReward.REWARD_PHYSICAL: + holder.rewardNameView.setText(reward.getProdName()); + holder.rewardValueView.setVisibility(View.VISIBLE); + holder.rewardValueView.setText(reward.getProdValue()); + break; + } + } + + class MonsterHuntingRewardViewHolder extends RecyclerView.ViewHolder { + + TextView rewardValueView; + ImageView rewardImageView; + TextView rewardNameView; + + public MonsterHuntingRewardViewHolder(View itemView) { + super(itemView); + + rewardValueView = itemView.findViewById(R.id.tv_reward_value); + rewardImageView = itemView.findViewById(R.id.iv_reward); + rewardNameView = itemView.findViewById(R.id.tv_reward_name); + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingSvgaManager.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingSvgaManager.java new file mode 100644 index 000000000..b7cd6f43c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/MonsterHuntingSvgaManager.java @@ -0,0 +1,209 @@ +package com.yizhuan.erban.monsterhunting; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.common.svga.SimpleSvgaCallback; +import com.yizhuan.erban.common.svga.SimpleSvgaParseCompletion; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterEvent; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Hashtable; +import java.util.Map; + +/** + * Created by MadisonRong on 01/04/2018. + */ + +public class MonsterHuntingSvgaManager { + + private static final String TAG = "MonsterHuntingSvgaManag"; + + public static final int MONSTER_HUNTING_ANIMATION_APPEAR = 0; + public static final int MONSTER_HUNTING_ANIMATION_NORMAL = 1; + public static final int MONSTER_HUNTING_ANIMATION_ATTACK = 2; + public static final int MONSTER_HUNTING_ANIMATION_DEFEAT = 3; + public static final int MONSTER_HUNTING_ANIMATION_LOTTERY = 4; + + private SVGAParser mSVGAParser; + private SVGAImageView monsterView; + private Map cacheSvgaMap = new Hashtable<>(); + private Map cacheSvgaDrawableMap = new Hashtable<>(); + private Map taskMap = new Hashtable<>(); + + private static final class MonsterHuntingSvgaManagerHolder { + private static final MonsterHuntingSvgaManager instance = new MonsterHuntingSvgaManager(); + } + + public static MonsterHuntingSvgaManager get() { + return MonsterHuntingSvgaManagerHolder.instance; + } + + public void initParser(Context context, SVGAImageView svgaImageView) { + mSVGAParser = new SVGAParser(context); + this.monsterView = svgaImageView; + } + + public void release() { + mSVGAParser = null; + monsterView = null; + cacheSvgaMap.clear(); + cacheSvgaDrawableMap.clear(); + taskMap.clear(); + } + + /** + * 预加载 SVGA 资源 + * + * @param appearUrl 怪兽进场动画 + * @param normalUrl 怪兽正常动画 + * @param attackUrl 怪兽被打动画 + * @param defeatUrl 怪兽打爆动画 + */ + public void preLoadMonsterAnimation(String appearUrl, String normalUrl, String attackUrl, String defeatUrl) { +// appearUrl = "https://img.erbanyy.com/appear3.svga"; +// normalUrl = "https://img.erbanyy.com/normal3.svga"; +// attackUrl = "https://img.erbanyy.com/attack5.svga"; +// defeatUrl = "https://img.erbanyy.com/defeat3.svga"; + String drawUrl = "https://img.erbanyy.com/luckDrawnew.svga"; + loadAnimation(MONSTER_HUNTING_ANIMATION_APPEAR, appearUrl); + loadAnimation(MONSTER_HUNTING_ANIMATION_NORMAL, normalUrl); + loadAnimation(MONSTER_HUNTING_ANIMATION_ATTACK, attackUrl); + loadAnimation(MONSTER_HUNTING_ANIMATION_DEFEAT, defeatUrl); + loadAnimation(MONSTER_HUNTING_ANIMATION_LOTTERY, drawUrl); + } + + /** + * 加载 SVGA 动画,并缓存到内存中 + * + * @param type 动画的类型 + * @see #MONSTER_HUNTING_ANIMATION_APPEAR 怪兽出现动画 + * @see #MONSTER_HUNTING_ANIMATION_NORMAL 怪兽正常动画 + * @see #MONSTER_HUNTING_ANIMATION_ATTACK 怪兽被打动画 + * @see #MONSTER_HUNTING_ANIMATION_DEFEAT 怪兽打爆动画 + * @param url 动画对应的 URL + */ + public void loadAnimation(int type, String url) { + if (TextUtils.isEmpty(url)) { + return; + } + try { + Task task = new Task(type); + taskMap.put(type, task); + mSVGAParser.parse(new URL(url), new SimpleSvgaParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + // 缓存好 SVGA + cacheSvgaMap.put(url, svgaVideoEntity); + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + cacheSvgaDrawableMap.put(type, drawable); + // 从任务队列中减员 + taskMap.remove(type); + // 任务队列为空,表明所有资源都已经加载完毕 + if (taskMap.size() == 0) { + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.ANIMATION_LOADED)); + } + } + + @Override + public void onError() { + super.onError(); + Log.e(TAG, "onError: load SVGA failed"); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + /** + * 播放怪兽的 SVGA + * + * @param drawable + * @param loopCount 循环次数,取值为 0 时无限循环 + * @param svgaCallback + */ + public void displayAnimation(SVGADrawable drawable, + int loopCount, SVGACallback svgaCallback) { + monsterView.setLoops(loopCount); + monsterView.setImageDrawable(drawable); + monsterView.setClearsAfterStop(true); + monsterView.startAnimation(); + monsterView.setCallback(svgaCallback); + } + + public void displayAppearAnimation() { + displayAnimation(cacheSvgaDrawableMap.get(MONSTER_HUNTING_ANIMATION_APPEAR), + 1, new SimpleSvgaCallback() { + @Override + public void onFinished() { + super.onFinished(); + // 进场动画结束后,立马播放正常动画 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_APPEAR_ANIMATION_FINISHED)); + } + }); + } + + public void displayNormalAnimation() { + displayAnimation(cacheSvgaDrawableMap.get(MONSTER_HUNTING_ANIMATION_NORMAL), + 0, new SimpleSvgaCallback()); + } + + public void displayAttackAnimation() { + displayAnimation(cacheSvgaDrawableMap.get(MONSTER_HUNTING_ANIMATION_ATTACK), + 1, new SimpleSvgaCallback() { + @Override + public void onFinished() { + super.onFinished(); + // 攻击动画结束后,回到正常动画上 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_ATTACK_ANIMATION_FINISHED)); + } + }); + } + + public void displayDefeatAnimation() { + displayAnimation(cacheSvgaDrawableMap.get(MONSTER_HUNTING_ANIMATION_DEFEAT), + 1, new SimpleSvgaCallback() { + @Override + public void onFinished() { + super.onFinished(); + // 怪兽被打爆,准备播放抽奖动画,出来抽奖结果 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_DEFEAT_ANIMATION_FINISHED)); + } + }); + } + + public void displayDrawAnimation() { + displayAnimation(cacheSvgaDrawableMap.get(MONSTER_HUNTING_ANIMATION_LOTTERY), + 1, new SimpleSvgaCallback() { + @Override + public void onFinished() { + super.onFinished(); + // 抽奖动画播完,准备弹出结果窗口 + MonsterHuntingAnimationManager.get().getMonsterEventObservable() + .onNext(new MonsterEvent(MonsterEvent.MONSTER_LOTTERY_ANIMATION_FINISHED)); + } + }); + } + + class Task { + // 内部类,占位而已 + public int taskId; + + public Task(int taskId) { + this.taskId = taskId; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/QuitConfirmDialog.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/QuitConfirmDialog.java new file mode 100644 index 000000000..600a456a8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/QuitConfirmDialog.java @@ -0,0 +1,68 @@ +package com.yizhuan.erban.monsterhunting; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by MadisonRong on 02/04/2018. + */ + +public class QuitConfirmDialog extends DialogFragment implements View.OnClickListener { + + private static final String TAG = "QuitConfirmDialog"; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + Window window = getDialog().getWindow(); + // setup window and width + View view = inflater.inflate(R.layout.dialog_quit_monster_hunting, container, false); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); +// window.setLayout(UIUtil.dip2px(getContext(), 316), UIUtil.dip2px(getContext(), 168)); + setCancelable(true); + TextView confirmTextView = view.findViewById(R.id.iv_operation_confirm); + TextView cancelTextView = view.findViewById(R.id.iv_operation_cancel); + confirmTextView.setOnClickListener(this); + cancelTextView.setOnClickListener(this); + return view; + } + + public void show(FragmentManager fragmentManager) { + this.show(fragmentManager, TAG); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_operation_confirm: + getActivity().finish(); + break; + + case R.id.iv_operation_cancel: + dismissAllowingStateLoss(); + break; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/SimpleCountDownTimer.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/SimpleCountDownTimer.java new file mode 100644 index 000000000..940f95b2b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/SimpleCountDownTimer.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.monsterhunting; + +import android.os.CountDownTimer; + +/** + * Created by MadisonRong on 02/04/2018. + */ + +public class SimpleCountDownTimer extends CountDownTimer { + + /** + * @param millisInFuture The number of millis in the future from the call + * to {@link #start()} until the countdown is done and {@link #onFinish()} + * is called. + * @param countDownInterval The interval along the way to receive + * {@link #onTick(long)} callbacks. + */ + public SimpleCountDownTimer(long millisInFuture, long countDownInterval) { + super(millisInFuture, countDownInterval); + } + + @Override + public void onTick(long millisUntilFinished) { + + } + + @Override + public void onFinish() { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/AttackMonsterResultInfo.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/AttackMonsterResultInfo.java new file mode 100644 index 000000000..b7e5b88a8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/AttackMonsterResultInfo.java @@ -0,0 +1,52 @@ +package com.yizhuan.erban.monsterhunting.bean; + + +import android.databinding.BaseObservable; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterAttackInfo; + +public class AttackMonsterResultInfo extends BaseObservable{ + + private int status; + + private int code; + + private String errorMessage = ""; + + private MonsterAttackInfo monsterAttackInfo; + + public AttackMonsterResultInfo() { + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + notifyChange(); + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MonsterAttackInfo getMonsterAttackInfo() { + return monsterAttackInfo; + } + + public void setMonsterAttackInfo(MonsterAttackInfo monsterAttackInfo) { + this.monsterAttackInfo = monsterAttackInfo; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/UpdateMyGoldInfo.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/UpdateMyGoldInfo.java new file mode 100644 index 000000000..69113a8fa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/bean/UpdateMyGoldInfo.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.monsterhunting.bean; + +import android.databinding.BaseObservable; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; + +public class UpdateMyGoldInfo extends BaseObservable { + + private boolean isSucceed; + + private WalletInfo walletInfo; + + public UpdateMyGoldInfo() { + } + + public boolean isSucceed() { + return isSucceed; + } + + public void setSucceed(boolean succeed) { + isSucceed = succeed; + notifyChange(); + } + + public WalletInfo getWalletInfo() { + return walletInfo; + } + + public void setWalletInfo(WalletInfo walletInfo) { + this.walletInfo = walletInfo; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/monsterhunting/viewmodel/MonsterHuntingViewModel.java b/app/src/main/java/com/yizhuan/erban/monsterhunting/viewmodel/MonsterHuntingViewModel.java new file mode 100644 index 000000000..9cb2a63c3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/monsterhunting/viewmodel/MonsterHuntingViewModel.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.monsterhunting.viewmodel; + +import android.util.Log; +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.erban.monsterhunting.bean.AttackMonsterResultInfo; +import com.yizhuan.erban.monsterhunting.bean.UpdateMyGoldInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterAttackInfo; +import com.yizhuan.xchat_android_core.monsterhunting.model.MonsterHuntingModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import java.util.Locale; + +public class MonsterHuntingViewModel extends BaseViewModel{ + + private static final String TAG = "MonsterHuntingViewModel"; + public UpdateMyGoldInfo updateMyGoldInfo = new UpdateMyGoldInfo(); + public AttackMonsterResultInfo attackMonsterResultInfo = new AttackMonsterResultInfo(); + + + public void attackMonster(String monsterId,String roomUid,String magicId) { + MonsterHuntingModel.get().attackMonster(monsterId, roomUid, magicId) + .subscribe((serviceResult, throwable) -> { + if (throwable != null) { + // attack fail + } else if (serviceResult != null && serviceResult.isSuccess()) { + MonsterAttackInfo monsterAttackInfo = serviceResult.getData(); + // 扣钱,发送自定义消息,显示动画 + updateMyGold(); + + refreshAttackMonsterResultInfo(serviceResult.getCode(),null, monsterAttackInfo,1); + + // 发送自定义消息,成功后显示动画 + MonsterHuntingModel.get().sendMonsterHuntingMagicMessage(monsterAttackInfo) + .subscribe((chatRoomMessage, throwable1) ->{ + if (chatRoomMessage != null) { + // 显示动画 + MonsterHuntingModel.get().onSendMonsterAttackMessageSuccess(chatRoomMessage); + } else { + throwable1.printStackTrace(); + } + }); + } else if (serviceResult != null && !serviceResult.isSuccess()) { + Log.e(TAG, String.format(Locale.getDefault(), "attackMonster: code:%s, message: %s", + serviceResult.getCode(), serviceResult.getMessage())); + refreshAttackMonsterResultInfo(serviceResult.getCode(), serviceResult.getErrorMessage(), null, 2); + } else { + refreshAttackMonsterResultInfo(-1, serviceResult.getErrorMessage(), null, 3); + } + }); + } + + private void refreshAttackMonsterResultInfo(int code, String errorMessage, MonsterAttackInfo monsterAttackInfo, int status) { + attackMonsterResultInfo.setCode(code); + attackMonsterResultInfo.setErrorMessage(errorMessage); + attackMonsterResultInfo.setMonsterAttackInfo(monsterAttackInfo); + attackMonsterResultInfo.setStatus(status); + } + + public void updateMyGold() { + PayModel.get().getMyRemoteWalletInfo() + .subscribe((walletInfo, throwable) -> { + if (walletInfo != null) { + updateMyGoldInfo.setWalletInfo(walletInfo); + updateMyGoldInfo.setSucceed(true); + } else if (throwable != null) { + updateMyGoldInfo.setSucceed(false); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/other/SplashBitmapTransformation.java b/app/src/main/java/com/yizhuan/erban/other/SplashBitmapTransformation.java new file mode 100644 index 000000000..3c235c522 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/other/SplashBitmapTransformation.java @@ -0,0 +1,53 @@ +package com.yizhuan.erban.other; + +import android.graphics.Bitmap; +import android.support.annotation.NonNull; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +import java.security.MessageDigest; + +/** + * splash 适配图片 + */ +public class SplashBitmapTransformation extends BitmapTransformation { + private static final String ID = "com.yizhuan.erban.other.SplashBitmapTransformation"; + private static final byte[] ID_BYTES = ID.getBytes(CHARSET); + + public SplashBitmapTransformation() { + } + + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + //glide 会自动计算好一边图片的大小(宽或者高) + int srcWidth = toTransform.getWidth(); + int srcHeight = toTransform.getHeight(); + int yOffset = srcHeight - outHeight; + int xOffset = (srcWidth - outWidth) / 2; + Bitmap bitmap; + if (yOffset > 0) { + bitmap = Bitmap.createBitmap(toTransform, 0, yOffset, outWidth, outHeight); + } else if (xOffset > 0) { + bitmap = Bitmap.createBitmap(toTransform, xOffset, 0, outWidth, outHeight); + } else { + bitmap = toTransform; + } + return bitmap; + } + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + messageDigest.update(ID_BYTES); + } + + @Override + public int hashCode() { + return ID.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof SplashBitmapTransformation; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/other/activity/SplashActivity.java b/app/src/main/java/com/yizhuan/erban/other/activity/SplashActivity.java new file mode 100644 index 000000000..72f1be107 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/other/activity/SplashActivity.java @@ -0,0 +1,174 @@ +package com.yizhuan.erban.other.activity; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; + +import com.bumptech.glide.request.RequestOptions; +import com.netease.nim.uikit.StatusBarUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.MainActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.databinding.ActivitySplashBinding; +import com.yizhuan.erban.other.SplashBitmapTransformation; +import com.yizhuan.erban.other.dialog.PrivacyAgreementDialog; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.initial.SplashComponent; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +/** + * @author xiaoyu + * @date 2017/12/30 + */ +public class SplashActivity extends BaseActivity implements View.OnClickListener, PrivacyAgreementDialog.OnCallBack { + + private static final String SHOW_PRIVACY_AGREEMENT = "show_privacy_agreement"; + private static final int COUNT_DOWN_TIME = 3; + private static final String TAG = SplashActivity.class.getSimpleName(); + private ActivitySplashBinding mBinding; + private SplashComponent mLocalSplashVo; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //修复 https://blog.csdn.net/u011153817/article/details/77335255 + // https://blog.csdn.net/zhangcanyan/article/details/52777265 这样的启动异常问题. + if (!isTaskRoot()) { + finish(); + return; + } + + mBinding = DataBindingUtil.setContentView(this, R.layout.activity_splash); + + mBinding.ivActivity.setOnClickListener(this); + mBinding.tvSkip.setOnClickListener(this); + if (savedInstanceState != null) { + // 从堆栈恢复,不再重复解析之前的intent + setIntent(new Intent()); + } + + initiate(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + } + + @SuppressLint("CheckResult") + protected void initiate() { + InitialModel.get().init(true).subscribe(); + MarketVerifyModel.get().loadVersionConfigFromServer(null).subscribe(); + checkPrivacyAgreement(); + } + + private void checkPrivacyAgreement() { + boolean isShowPrivacyAgreement = (boolean) SharedPreferenceUtils.get(SHOW_PRIVACY_AGREEMENT, true); + if (isShowPrivacyAgreement) { + PrivacyAgreementDialog privacyAgreementDialog = new PrivacyAgreementDialog(this); + privacyAgreementDialog.setCancelable(false); + privacyAgreementDialog.setCanceledOnTouchOutside(false); + privacyAgreementDialog.setOnCallBack(this); + privacyAgreementDialog.show(); + } else { + showSplash(); + } + } + + + private void showSplash() { + // 不过期的,并且已经下载出来图片的闪屏页数据 + mLocalSplashVo = InitialModel.get().getLocalSplashVo(); + if (mLocalSplashVo != null && + !TextUtils.isEmpty(mLocalSplashVo.getPict())) { + animation(); + GlideApp.with(this) + .load(mLocalSplashVo.getPict()) + //添加图片处理机制 + .apply(RequestOptions.bitmapTransform(new SplashBitmapTransformation())) + .into(mBinding.ivActivity); + } else { + MainActivity.start(SplashActivity.this); + finish(); + } + } + + private volatile boolean needJump = false; + + private void animation() { + mBinding.ivActivity.setAlpha(0.4F); + mBinding.ivActivity.animate().alpha(1).setDuration(1000).setStartDelay(0).start(); + mBinding.ivActivity.animate().setDuration(COUNT_DOWN_TIME * 1000).withEndAction(new Runnable() { + @Override + public void run() { + if (needJump) { + return; + } + MainActivity.start(SplashActivity.this); + finish(); + } + }).start(); + } + + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_activity: + if (mLocalSplashVo == null) return; + String link = mLocalSplashVo.getLink(); + int type = mLocalSplashVo.getType(); + if (TextUtils.isEmpty(link) || type == 0) return; + needJump = true; + Intent intent = new Intent(); + intent.putExtra("url", link); + intent.putExtra("type", type); + MainActivity.start(this, intent); + break; + case R.id.tv_skip: + if (mLocalSplashVo == null) { + return; + } + needJump = true; + MainActivity.start(this); + break; + default: + break; + } + + } + + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + ); + } + + @Override + public void onFinish(boolean isConfirm) { + if (isConfirm) { + SharedPreferenceUtils.put(SHOW_PRIVACY_AGREEMENT, false); + showSplash(); + } else { + onBackPressed(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/other/dialog/PrivacyAgreementDialog.java b/app/src/main/java/com/yizhuan/erban/other/dialog/PrivacyAgreementDialog.java new file mode 100644 index 000000000..6035b1fb8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/other/dialog/PrivacyAgreementDialog.java @@ -0,0 +1,107 @@ +package com.yizhuan.erban.other.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.ForegroundColorSpan; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.common.widget.OriginalDrawStatusClickSpan; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_library.utils.ScreenUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +public class PrivacyAgreementDialog extends Dialog implements View.OnClickListener { + + private OnCallBack onCallBack; + + public PrivacyAgreementDialog(@NonNull Context context) { + super(context); + } + + public void setOnCallBack(OnCallBack onCallBack) { + this.onCallBack = onCallBack; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_privacy_agreement); + + findViewById(R.id.tv_confirm).setOnClickListener(this); + findViewById(R.id.tv_cancel).setOnClickListener(this); + + TextView tvDesc = findViewById(R.id.tv_desc); + String privacyAgreementTip = getContext().getString(R.string.tip_privacy_agreement); + String userAgreementTip = getContext().getString(R.string.tip_user_agreement); + String privacyAgreementDescTip = getContext().getString(R.string.tip_privacy_agreement_desc, privacyAgreementTip, userAgreementTip); + SpannableString ss = new SpannableString(privacyAgreementDescTip); + int privacyAgreementTipIndex = privacyAgreementDescTip.indexOf(privacyAgreementTip); + int userAgreementTipIndex = privacyAgreementDescTip.indexOf(userAgreementTip); + + + ss.setSpan(new ForegroundColorSpan(Color.parseColor("#34a7ff")), privacyAgreementTipIndex, privacyAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + CommonWebViewActivity.start(getContext(), UriProvider.getPrivacyAgreement()); + } + }, privacyAgreementTipIndex, privacyAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new ForegroundColorSpan(Color.parseColor("#34a7ff")), userAgreementTipIndex, userAgreementTipIndex + userAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + CommonWebViewActivity.start(getContext(), UriProvider.getUserProtocolUrl()); + } + }, userAgreementTipIndex, userAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvDesc.setText(ss); + tvDesc.setMovementMethod(new LinkMovementMethod()); + Window window = getWindow(); + if (window == null) { + return; + } + WindowManager.LayoutParams lp = window.getAttributes(); + if (lp == null) { + return; + } + int screenWidth = ScreenUtils.getScreenWidth(getContext()); + + lp.width = (int) (screenWidth * .855 + .5f); + lp.gravity = Gravity.CENTER; + lp.height = UIUtil.dip2px(getContext(), 500); + + window.setAttributes(lp); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + + } + + @Override + public void onClick(View v) { + if (onCallBack != null) { + onCallBack.onFinish(v.getId() == R.id.tv_confirm); + } + cancel(); + } + + public interface OnCallBack { + void onFinish(boolean isConfirm); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/other/present/SplashPresenter.java b/app/src/main/java/com/yizhuan/erban/other/present/SplashPresenter.java new file mode 100644 index 000000000..625ac44fa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/other/present/SplashPresenter.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.other.present; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.other.view.ISplashView; + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public class SplashPresenter extends BaseMvpPresenter { + + +} diff --git a/app/src/main/java/com/yizhuan/erban/other/view/ISplashView.java b/app/src/main/java/com/yizhuan/erban/other/view/ISplashView.java new file mode 100644 index 000000000..7d54f9354 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/other/view/ISplashView.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.other.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public interface ISplashView extends IMvpBaseView { + void resultHomeTabsSuccess(List tabInfoList); + + void resultHomeTabsFail(String error); +} diff --git a/app/src/main/java/com/yizhuan/erban/push/HwPushMessageReceiver.java b/app/src/main/java/com/yizhuan/erban/push/HwPushMessageReceiver.java new file mode 100644 index 000000000..83cc7d5e0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/push/HwPushMessageReceiver.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.push; + +import android.content.Context; +import android.os.Bundle; + +import com.netease.nimlib.sdk.mixpush.HWPushMessageReceiver; +import com.orhanobut.logger.Logger; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; + +public class HwPushMessageReceiver extends HWPushMessageReceiver { + + @Override + public void onToken(Context context, String token, Bundle extras) { + super.onToken(context, token, extras); + StatisticManager.Instance().logToLocalFile("华为推送token:" + token); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/push/MeizuPushReceiver.java b/app/src/main/java/com/yizhuan/erban/push/MeizuPushReceiver.java new file mode 100644 index 000000000..bd29e5a7c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/push/MeizuPushReceiver.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.push; + +import android.content.Context; +import android.util.Log; + +import com.meizu.cloud.pushsdk.platform.message.RegisterStatus; +import com.netease.nimlib.sdk.mixpush.MeiZuPushReceiver; +import com.orhanobut.logger.Logger; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; + +/** + * Created by lvzebiao on 2019/1/18. + */ + +public class MeizuPushReceiver extends MeiZuPushReceiver { + + @Override + public void onRegister(Context context, String pushId) { + super.onRegister(context, pushId); + } + + @Override + public void onRegisterStatus(Context context, RegisterStatus registerStatus) { + super.onRegisterStatus(context, registerStatus); + Logger.i("魅族推送ID:" + registerStatus.getPushId()); + StatisticManager.Instance().logToLocalFile("魅族推送ID:" + registerStatus.getPushId()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/push/MiPushReceiver.java b/app/src/main/java/com/yizhuan/erban/push/MiPushReceiver.java new file mode 100644 index 000000000..a9fde561b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/push/MiPushReceiver.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.push; + +import android.content.Context; +import android.util.Log; + +import com.netease.nimlib.sdk.mixpush.MiPushMessageReceiver; +import com.orhanobut.logger.Logger; +import com.xiaomi.mipush.sdk.ErrorCode; +import com.xiaomi.mipush.sdk.MiPushClient; +import com.xiaomi.mipush.sdk.MiPushCommandMessage; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; + +import java.util.List; +import java.util.logging.LogManager; + +/** + * Created by lvzebiao on 2019/1/18. + */ + +public class MiPushReceiver extends MiPushMessageReceiver { + + + @Override + public void onCommandResult(Context context, MiPushCommandMessage message) { + super.onCommandResult(context, message); + + Logger.i("小米推送...."); + String command = message.getCommand(); + List arguments = message.getCommandArguments(); + if (MiPushClient.COMMAND_REGISTER.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + String mRegID = arguments.get(0); + Logger.i("小米推送mRegID:" + mRegID); + StatisticManager.Instance().logToLocalFile("小米推送mRegID:" + mRegID); + } else + StatisticManager.Instance().logToLocalFile("小米推送mRegID_error:" + message.getReason()); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/activity/RadishRecordActivity.java b/app/src/main/java/com/yizhuan/erban/radish/activity/RadishRecordActivity.java new file mode 100644 index 000000000..cbb05837e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/activity/RadishRecordActivity.java @@ -0,0 +1,140 @@ +package com.yizhuan.erban.radish.activity; + +import android.arch.lifecycle.Observer; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.StatusBarUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.radish.presenter.RadishRecordPresenter; +import com.yizhuan.erban.radish.view.IRadishRecordView; +import com.yizhuan.erban.radish.wallet.RadishWalletManager; +import com.yizhuan.erban.radish.widget.RadishRecordNavAdapter; +import com.yizhuan.erban.ui.radish.RadishRecordFragment; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.radish.RadishWalletInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +@CreatePresenter(RadishRecordPresenter.class) +public class RadishRecordActivity extends BaseMvpActivity implements IRadishRecordView { + + @BindView(R.id.mi_radish_record) + MagicIndicator mMagicIndicator; + @BindView(R.id.vp_radish_record) + ViewPager mVpRadishRecord; + @BindView(R.id.tv_total_radish) + TextView tvTotalRadish; + + private Unbinder mUnbinder; + + public static void startActivity(Context context) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MY_RADISH_CLICK, "我的萝卜"); + Intent intent = new Intent(context, RadishRecordActivity.class); + context.startActivity(intent); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_radish_record); + mUnbinder = ButterKnife.bind(this); + initTitleBar("萝卜记录"); + setTotalRadish(0L); + + ArrayList fragments = new ArrayList<>(2); + fragments.add(RadishRecordFragment.newInstance(RadishRecordFragment.TYPE_RADISH_INCOME)); + fragments.add(RadishRecordFragment.newInstance(RadishRecordFragment.TYPE_RADISH_EXPAND)); + mVpRadishRecord.setAdapter(new RoomContributeListAdapter(getSupportFragmentManager(), fragments)); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + + RadishRecordNavAdapter indicator = new RadishRecordNavAdapter(); + indicator.setOnItemSelectListener(position -> mVpRadishRecord.setCurrentItem(position)); + commonNavigator.setAdapter(indicator); + mMagicIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mMagicIndicator, mVpRadishRecord); + + RadishWalletManager.get().registerRadishNum(this, new Observer() { + @Override + public void onChanged(@Nullable RadishWalletInfo radishWalletInfo) { + if (radishWalletInfo != null) { + setTotalRadish(radishWalletInfo.getAmount()); + } + } + }); + getMvpPresenter().getRadishWallet(); + } + + private void setTotalRadish(long total) { + if (tvTotalRadish != null) + tvTotalRadish.setText(getMvpPresenter().formatBigDecimal(total)); + + } + + @Override + public void initTitleBar(String title) { + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(true); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left_white); + mTitleBar.setBackgroundColor(getResources().getColor(R.color.transparent)); + mTitleBar.setLeftClickListener(v -> finish()); + } + + addAction(); + } + + private void addAction() { + if (mTitleBar != null) { + mTitleBar.addAction(new TitleBar.ImageAction(R.mipmap.common_ic_help_white) { + @Override + public void performAction(View view) { + CommonWebViewActivity.start(RadishRecordActivity.this, UriProvider.JAVA_WEB_URL + "/modules/rule/radish.html"); + } + }); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + if (mUnbinder != null) + mUnbinder.unbind(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/adapter/RadishRecordAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/adapter/RadishRecordAdapter.java new file mode 100644 index 000000000..2d99fb29f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/adapter/RadishRecordAdapter.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.radish.adapter; + +import android.support.v4.content.ContextCompat; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RadishRecordInfo; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.util.List; + +import static com.yizhuan.erban.ui.radish.RadishRecordFragment.TYPE_RADISH_INCOME; + +public class RadishRecordAdapter extends BillBaseAdapter { + private byte mType; + + public RadishRecordAdapter(List billItemEntityList, byte type) { + super(billItemEntityList); + addItemType(BillItemEntity.ITEM_NORMAL, R.layout.item_radish_record); + + mType = type; + } + + @Override + public void convertNormal(BaseViewHolder baseViewHolder, BillItemEntity billItemEntity) { + + RadishRecordInfo radishRecordInfo = billItemEntity.mRadishRecordInfo; + if (radishRecordInfo == null) return; + baseViewHolder.setText(R.id.tv_record_name, radishRecordInfo.getDescribeStr()) + .setText(R.id.tv_record_hmd, TimeUtils.getDateTimeString(radishRecordInfo.getCreateTime(), "HH:mm:ss")) + .setText(R.id.tv_record_value, radishRecordInfo.getAmountStr()) + .setTextColor(R.id.tv_record_value, + ContextCompat.getColor(mContext, mType == TYPE_RADISH_INCOME ? R.color.appColor : R.color.color_333333)); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/helper/PrizeAnimUiHelper.java b/app/src/main/java/com/yizhuan/erban/radish/helper/PrizeAnimUiHelper.java new file mode 100644 index 000000000..e2c9ab7df --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/helper/PrizeAnimUiHelper.java @@ -0,0 +1,294 @@ +package com.yizhuan.erban.radish.helper; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.view.View; +import android.view.animation.DecelerateInterpolator; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.xchat_android_core.radish.signin.SignInModel; +import com.yizhuan.xchat_android_core.radish.task.bean.PrizeAnim; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.concurrent.TimeUnit; + +import butterknife.BindView; +import butterknife.ButterKnife; +import cn.sharesdk.framework.Platform; +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +/** + * 动画界面,签到和任务界面一样,整合一处 + * create by lvzebiao @2019/3/26 + */ +public class PrizeAnimUiHelper { + + /** + * 任务界面 + */ + public final static int TYPE_TASK_PAGE = 1; + + /** + * 签到界面 + */ + public final static int TYPE_SIGN_IN_PAGE = 2; + /** + * 累计奖励 + */ + public final static int TYPE_REWARD_PAGE = 3; + /** + * 瓜分金币 + */ + public final static int TYPE_DRAW_GOLD = 4; + @BindView(R.id.iv_reward_bg) + ImageView ivRewardBg; + @BindView(R.id.iv_reward_content) + ImageView ivRewardContent; + @BindView(R.id.tv_detail_prize_name) + TextView tvDetailPrizeName; + @BindView(R.id.tv_label_number) + TextView tvLabelNum; + @BindView(R.id.tv_detail_prize_number) + TextView tvDetailPrizeNumber; + @BindView(R.id.ll_prize_and_num) + LinearLayout llPrizeAndNum; + @BindView(R.id.tv_detail_tips) + TextView tvDetailTips; + @BindView(R.id.tv_detail_share) + TextView tvDetailShare; + + private AnimatorSet contentAllSet; + + private AnimatorSet bgSet; + + private View clRewardAnimContainer; + + private Context context; + + private int mType; + + private PrizeAnim prizeAnim; + + private DialogManager dialogManager; + + private void close() { + clRewardAnimContainer.setVisibility(View.GONE); + prizeAnim = null; + } + + public void onCreate(Context context, View parent, int type, DialogManager dialogManager) { + this.context = context; + ButterKnife.bind(this, parent); + this.clRewardAnimContainer = parent; + clRewardAnimContainer.setOnClickListener(v -> close()); + this.mType = type; + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + this.dialogManager = dialogManager; + clRewardAnimContainer.setVisibility(View.GONE); + if (mType == TYPE_TASK_PAGE) { + tvDetailTips.setVisibility(View.VISIBLE); + tvDetailShare.setVisibility(View.GONE); + } else { + tvDetailTips.setVisibility(View.GONE); + tvDetailShare.setVisibility(View.VISIBLE); + tvDetailShare.setOnClickListener(v -> { + if (prizeAnim == null) { + return; + } + final String day = String.valueOf(prizeAnim.getSignDays()) + "天"; + final String reward = prizeAnim.getPrizeName(); + ShareDialog shareDialog = new ShareDialog(context); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.setOnShareDialogItemClick(new ShareDialog.OnShareDialogItemClick() { + @Override + public void onInAppSharingItemClick() { + + } + + @Override + public void onSharePlatformClick(Platform platform) { + if (mType == TYPE_SIGN_IN_PAGE) { +// StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_SHARE_CLICK, "签到-分享"); + } else if (mType == TYPE_REWARD_PAGE) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_REWARD_SHARE_CLICK, "累计奖励-分享"); + } + + toShare(platform, day, reward); + } + }); + shareDialog.show(); + }); + } + + } + + + public void showPrizeInfoUi(PrizeAnim prizeAnim) { + if (prizeAnim == null) { + return; + } + this.prizeAnim = prizeAnim; + clRewardAnimContainer.setVisibility(View.VISIBLE); + if (!TextUtils.isEmpty(prizeAnim.getPrizePic())) { + ImageLoadUtils.loadDrawable(context, prizeAnim.getPrizePic()) + .compose(RxHelper.bindContext(context)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(Drawable drawable) { + playAnim(drawable); + } + }); + } else + playAnim(ivRewardContent.getContext().getResources().getDrawable(R.drawable.icon_draw_gold)); + + tvDetailPrizeName.setText(prizeAnim.getPrizeName()); + tvLabelNum.setVisibility(View.GONE); + tvDetailPrizeNumber.setVisibility(View.GONE); + + if (mType == TYPE_TASK_PAGE) { + tvDetailTips.setText(prizeAnim.getTips()); + } + } + + public void setType(int type) { + this.mType = type; + } + + @SuppressLint("CheckResult") + private void playAnim(Drawable drawable) { + + ivRewardBg.setImageResource(R.drawable.icon_reward_bg); + ivRewardContent.setImageDrawable(drawable); + + playRewardContentAnim(ivRewardContent); + ivRewardBg.setVisibility(View.INVISIBLE); + //noinspection ResultOfMethodCallIgnored + Single.timer(200, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .compose(RxHelper.bindContext(context)) + .subscribe(aLong -> { + playRewardBgAnim(ivRewardBg); + ivRewardBg.setVisibility(View.VISIBLE); + }); + } + + private void playRewardContentAnim(View ivRewardContent) { + //内容的动画 + //透明度 + ObjectAnimator contentAlpha = ObjectAnimator.ofFloat(ivRewardContent, "alpha", 0f, 1f); + contentAlpha.setDuration(200); + //缩放 + ObjectAnimator contentScaleX = ObjectAnimator.ofFloat(ivRewardContent, "scaleX", 0f, 1.15f, 1f); + ObjectAnimator contentScaleY = ObjectAnimator.ofFloat(ivRewardContent, "scaleY", 0f, 1.15f, 1f); + AnimatorSet contentScale = new AnimatorSet(); + contentScale.play(contentScaleX).with(contentScaleY); + contentScale.setDuration(640); + //内容的放一起 + contentAllSet = new AnimatorSet(); + contentAllSet.play(contentAlpha).with(contentScale); + contentAllSet.setInterpolator(new DecelerateInterpolator()); + contentAllSet.start(); + } + + private void playRewardBgAnim(View ivRewardBg) { + //背景动画 + ObjectAnimator animatorScaleY = ObjectAnimator.ofFloat(ivRewardBg, "scaleY", 0f, 1.1f, 1f); + ObjectAnimator animatorScaleX = ObjectAnimator.ofFloat(ivRewardBg, "scaleX", 0f, 1.1f, 1f); + + ObjectAnimator animatorAlpha = ObjectAnimator.ofFloat(ivRewardBg, "alpha", 0.4f, 1f); + animatorAlpha.setDuration(120); + + bgSet = new AnimatorSet(); + bgSet.play(animatorScaleX).with(animatorScaleY).with(animatorAlpha); + bgSet.setDuration(720); + bgSet.setInterpolator(new DecelerateInterpolator()); + bgSet.start(); + } + + public boolean onBackPressed() { + boolean hasHandle = false; + if (clRewardAnimContainer.getVisibility() == View.VISIBLE) { + clRewardAnimContainer.setVisibility(View.GONE); + hasHandle = true; + } + return hasHandle; + } + + public void onDestroy() { + if (contentAllSet != null) { + contentAllSet.cancel(); + } + if (bgSet != null) { + bgSet.cancel(); + } + } + + private void toShare(Platform platform, String day, String reward) { + + int shareType = SignInModel.SHARE_TYPE_REWARD; // 累计奖励 + if (mType == TYPE_DRAW_GOLD) + shareType = SignInModel.SHARE_TYPE_DRAW_GOLD; // 瓜分金币 + + dialogManager.showProgressDialog(context, "", true); + new SignInModel().getShareImage(shareType, day, reward) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + dialogManager.dismissDialog(); + } + + @Override + public void onSuccess(String s) { + getShareImageSuccess(platform, s); + } + }); + } + + private void getShareImageSuccess(Platform platform, String s) { + ShareModel.get().shareImageForSignIn(platform, s).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + dialogManager.dismissDialog(); + SignInModel signInModel = new SignInModel(); + signInModel.signShare(); + } + + @Override + public void onError(Throwable e) { + dialogManager.dismissDialog(); + } + }); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/helper/TaskCenterDialogHelper.java b/app/src/main/java/com/yizhuan/erban/radish/helper/TaskCenterDialogHelper.java new file mode 100644 index 000000000..3339183cf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/helper/TaskCenterDialogHelper.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.radish.helper; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; + +public class TaskCenterDialogHelper { + + private Context mContext; + private DialogManager mDialogManager; + + public TaskCenterDialogHelper(Context context) { + this.mContext = context; + mDialogManager = new DialogManager(mContext); + } + + public void showDialog(String picUrl) { + View view1 = LayoutInflater.from(mContext).inflate(R.layout.dialog_task, null); + ImageView imageView = view1.findViewById(R.id.iv_task_guide); + if (imageView != null) + ImageLoadUtils.loadImage(mContext, picUrl, imageView); + + TextView cancel = view1.findViewById(R.id.btn_cancel); + cancel.setOnClickListener(v -> mDialogManager.dismissDialog()); + + mDialogManager.showCustomViewDialog(view1); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordFrgPresenter.java b/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordFrgPresenter.java new file mode 100644 index 000000000..72cd0917d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordFrgPresenter.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.radish.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.radish.view.IRadishRecordFrgView; +import com.yizhuan.xchat_android_core.radish.RadishModel; +import com.yizhuan.xchat_android_core.radish.RadishRecordResult; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class RadishRecordFrgPresenter extends BaseMvpPresenter { + + public void getRadishRecord(int page, int pageSize, long date, byte type) { + RadishModel.get().getRadishRecord(page, pageSize, date, type) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(RadishRecordResult radishRecordResult) { + if (radishRecordResult != null && radishRecordResult.isSuccess()) { + if (mMvpView != null) + mMvpView.getRadishRecordSuccess(radishRecordResult.getData()); + } else if (radishRecordResult != null){ + if (mMvpView != null) + mMvpView.getRadishRecordFail(radishRecordResult.getError()); + } + } + + @Override + public void onError(Throwable e) { + if (mMvpView != null) + mMvpView.getRadishRecordFail(e.getMessage()); + + } + }); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordPresenter.java b/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordPresenter.java new file mode 100644 index 000000000..f5b8575af --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/presenter/RadishRecordPresenter.java @@ -0,0 +1,25 @@ +package com.yizhuan.erban.radish.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.radish.view.IRadishRecordView; +import com.yizhuan.xchat_android_core.radish.RadishModel; + +import java.math.RoundingMode; +import java.text.DecimalFormat; + +public class RadishRecordPresenter extends BaseMvpPresenter { + public void getRadishWallet() { + RadishModel.get().updateRadishWallet() + .subscribe(); + } + + public String formatBigDecimal(long bigDecimal) { + try { + DecimalFormat decimalFormat = new DecimalFormat("#,###"); + decimalFormat.setRoundingMode(RoundingMode.HALF_UP); + return decimalFormat.format(bigDecimal); + } catch (Exception e) { + } + return "0"; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/SignDialogTimeManager.java b/app/src/main/java/com/yizhuan/erban/radish/signin/SignDialogTimeManager.java new file mode 100644 index 000000000..10b35b213 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/SignDialogTimeManager.java @@ -0,0 +1,152 @@ +package com.yizhuan.erban.radish.signin; + +import android.content.Context; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.yizhuan.erban.guide.GuideActivity; +import com.yizhuan.erban.other.activity.SplashActivity; +import com.yizhuan.erban.radish.signin.view.SignInDialog; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.erban.ui.login.LoginActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.radish.signin.SignInModel; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.UIUtils; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +/** + * 签到弹框时机的处理 + * create by lvzebiao @2019/3/28 + */ +public class SignDialogTimeManager { + + public final static String KEY_SAVE_SIGN_IN_TIME = "key_sign_in_time"; + + public static void checkSignDialog(Context context, boolean isNeedCheckAddUserInfo) { + if (!ActivityUtil.isCanShowAppCompatDialog(context)) { + return; + } + //闪屏页,登录页,引导页,完善资料页不弹 + if (UIUtils.isTopActivity(context, SplashActivity.class.getName()) + || UIUtils.isTopActivity(context, LoginActivity.class.getName()) + || UIUtils.isTopActivity(context, GuideActivity.class.getName())) { + return; + } + if (isNeedCheckAddUserInfo && UIUtils.isTopActivity(context, AddUserInfoActivity.class.getName())) { + return; + } + if (!isNeedConnectNet()) { + return; + } + SignInModel model = new SignInModel(); + model.signDetail().compose(RxHelper.bindContext(context)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(SignDetailInfo detailInfo) { + if (!ActivityUtil.isValidContext(context)) { + return; + } + + if (detailInfo.isSign() || !detailInfo.isNeedSignDialog()) { + return; + } + saveCache(); + SignInDialog.display(context, detailInfo); + } + }); + } + + public static HashMap cacheToMap() { + String cache = (String) SharedPreferenceUtils.get(KEY_SAVE_SIGN_IN_TIME, ""); + if (!TextUtils.isEmpty(cache)) { + try { + return new Gson().fromJson(cache, new TypeToken>() { + }.getType()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + return null; + } + + public static void saveCache() { + Map map = cacheToMap(); + if (map == null) { + map = new HashMap<>(); + } + if (map.size() > 10) { + map.clear(); + } + map.put(AuthModel.get().getCurrentUid(), System.currentTimeMillis()); + try { + String json = new Gson().toJson(map); + if (!TextUtils.isEmpty(json)) { + SharedPreferenceUtils.put(KEY_SAVE_SIGN_IN_TIME, json); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private static boolean isNeedConnectNet() { + try { + Map map = cacheToMap(); + if (map == null || map.size() == 0) { + return true; + } + long myUid = AuthModel.get().getCurrentUid(); + if (!map.containsKey(myUid)) { + return true; + } + long myTimeValue = map.get(myUid); + if (myTimeValue <= 0) { + return true; + } + return isTomorrow(myTimeValue); + } catch (Exception ex) { + ex.printStackTrace(); + } + return true; + } + + /** + * 判断是不是 第二天 + * + * @param cacheTime + * @return + */ + private static boolean isTomorrow(long cacheTime) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + int currYear = calendar.get(Calendar.YEAR); + int currMonth = calendar.get(Calendar.MONTH); + int currDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); + calendar.setTimeInMillis(cacheTime); + int cacheYear = calendar.get(Calendar.YEAR); + int cacheMonth = calendar.get(Calendar.MONTH); + int cacheDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); + if (currYear > cacheYear) { + return true; + } + boolean equalYear = currYear == cacheYear; + if (equalYear && currMonth > cacheMonth) { + return true; + } + return equalYear && currMonth == cacheMonth && currDayOfMonth > cacheDayOfMonth; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/SignInActivity.java b/app/src/main/java/com/yizhuan/erban/radish/signin/SignInActivity.java new file mode 100644 index 000000000..913d514ea --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/SignInActivity.java @@ -0,0 +1,754 @@ +package com.yizhuan.erban.radish.signin; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.os.SystemClock; +import android.support.constraint.ConstraintLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; + +import com.coorchice.library.SuperTextView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.TutuSwitchView; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.common.widget.dialog.DialogUiHelper; +import com.yizhuan.erban.radish.helper.PrizeAnimUiHelper; +import com.yizhuan.erban.radish.signin.adpter.RewardListAdapter; +import com.yizhuan.erban.radish.signin.adpter.RewardTotalNoticeAdapter; +import com.yizhuan.erban.radish.signin.helper.SignInUiHelper; +import com.yizhuan.erban.radish.signin.presenter.SignInPresenter; +import com.yizhuan.erban.radish.signin.view.CarveUpGoldAdapter; +import com.yizhuan.erban.radish.signin.view.ISignInView; +import com.yizhuan.erban.radish.signin.view.RuleDialog; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.erban.utils.CertificateHelper; +import com.yizhuan.erban.utils.NumberFormatUtil; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_core.radish.signin.SignInModel; +import com.yizhuan.xchat_android_core.radish.signin.bean.DrawNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.ReceiveTotalRewardInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.ReplenishSignInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.RewardNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.RsPlatformType; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDrawInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignInfo; +import com.yizhuan.xchat_android_core.radish.task.bean.PrizeAnim; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RadishNotEnoughException; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; +import com.yy.mobile.rollingtextview.CharOrder; +import com.yy.mobile.rollingtextview.RollingTextView; +import com.yy.mobile.rollingtextview.strategy.Direction; +import com.yy.mobile.rollingtextview.strategy.Strategy; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import cn.sharesdk.framework.Platform; +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; + +/** + * 萝卜签到 + */ +@CreatePresenter(SignInPresenter.class) +public class SignInActivity extends BaseMvpActivity implements ISignInView, IOSSwitchView.OnSwitchStateChangeListener, + ShareDialog.OnShareDialogItemClick, RewardTotalNoticeAdapter.RewardTotalListener { + + @BindView(R.id.bmv_sign_in) + BetterMarqueeView bmvSignIn; + @BindView(R.id.switch_sign_in_notice) + TutuSwitchView switchSignInNotice; + @BindView(R.id.tv_sign_in_op) + TextView tvSignInOp; + @BindView(R.id.title_bar) + TitleBar titleBar; + @BindView(R.id.iv_horn) + ImageView ivHorn; + @BindView(R.id.iv_sign_in_logo) + ImageView ivSignInLogo; + @BindView(R.id.stv_explain) + SuperTextView stvExplain; + @BindView(R.id.scl_top) + ConstraintLayout sclTop; + @BindView(R.id.view_content_line) + View viewContentLine; + @BindView(R.id.view_bg_content) + View viewBgContent; + @BindView(R.id.line_left_short) + View lineLeftShort; + @BindView(R.id.tv_pool_tips) + TextView tvPoolTips; + @BindView(R.id.line_right_short) + View lineRightShort; + @BindView(R.id.rtv_gold_pool) + RollingTextView rtvGoldPool; + @BindView(R.id.tv_award_info) + TextView tvAwardInfo; + @BindView(R.id.sv_container) + ScrollView svContainer; + @BindView(R.id.iv_reward_bg) + ImageView ivRewardBg; + @BindView(R.id.iv_reward_content) + ImageView ivRewardContent; + @BindView(R.id.cl_reward_anim_container) + ConstraintLayout clRewardAnimContainer; + @BindView(R.id.rv_reward_list) + RecyclerView rvRewardList; + @BindView(R.id.tv_label_sign_day) + TextView tvSignDay; + @BindView(R.id.layout_total_reward) + View mRewardTotal; + + private SignDetailInfo mSignDetailInfo; + private RewardListAdapter mRewardListAdapter; + + private PrizeAnimUiHelper priceAnimUiHelper; + + private boolean isFirstLoad = true; + + public static void start(Context context) { + Intent intent = new Intent(context, SignInActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sign_in); + ButterKnife.bind(this); + initTitleBar("签到"); + priceAnimUiHelper = new PrizeAnimUiHelper(); + priceAnimUiHelper.onCreate(this, findViewById(R.id.cl_reward_anim_container), + PrizeAnimUiHelper.TYPE_SIGN_IN_PAGE, getDialogManager()); + initBetterMarqueeView(); + initNumberPoolInfo(); + + mRewardListAdapter = new RewardListAdapter(R.layout.item_reward_notice, null); + rvRewardList.setLayoutManager(new GridLayoutManager(this, 4) { + @Override + public boolean canScrollVertically() { + return false; + } + }); + rvRewardList.setAdapter(mRewardListAdapter); + + switchSignInNotice.setOnSwitchStateChangeListener(this); + + mRewardListAdapter.setOnItemClickListener((adapter, view, position) -> { + RewardNoticeInfo item = mRewardListAdapter.getItem(position); + if (item == null) { + return; + } + if (mSignDetailInfo != null && !mSignDetailInfo.isCanReplenishSign()) { + toast("本轮已用完补签机会"); + return; + } + getMvpPresenter().getDataModel().getReplenishSignInfo(item.getSignDays()) + .compose(RxHelper.bindActivity(this)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(ReplenishSignInfo info) { + handleReplenishSignTypeDialog(info, item.getSignDays()); + } + }); + }); + + loadData(false); + } + + private void loadData(boolean isReplenish) { + getMvpPresenter().getSignDetail(isReplenish); + getMvpPresenter().getRewardTotalNotice(); + getMvpPresenter().getRewardTodayNotice(); + } + + private void handleReplenishSignTypeDialog(ReplenishSignInfo info, int signDay) { + SpannableBuilder builder = new SpannableBuilder(); + String okLabel; + if (info.getType() == ReplenishSignInfo.TYPE_SHARE) { + builder.append("分享好友", + new ForegroundColorSpan(getResources().getColor(R.color.appColor))) + .append(" 即可获得补签机会\n") + .append("分享后返回轻寻才有效哦~", + new ForegroundColorSpan(getResources().getColor(R.color.color_999999))); + okLabel = "分享好友"; + } else { + builder.append("本次补签需要消耗 ") + .append(info.getPrice() + "萝卜", + new ForegroundColorSpan(getResources().getColor(R.color.appColor))); + okLabel = "确定"; + } + + getDialogManager().showOkCancelWithTitleDialog("补签", builder.build(), okLabel, true, () -> { + + Single.create((SingleOnSubscribe) emitter -> { + if (info.getType() == ReplenishSignInfo.TYPE_SHARE) { + //分享 + ShareDialog shareDialog = new ShareDialog(context); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.setOnShareDialogItemClick(new ShareDialog.OnShareDialogItemClick() { + @Override + public void onInAppSharingItemClick() { + + } + + @Override + public void onSharePlatformClick(Platform platform) { + emitter.onSuccess(new RsPlatformType(true, platform)); + } + }); + shareDialog.show(); + } else { + emitter.onSuccess(new RsPlatformType(false, null)); + } + }).observeOn(AndroidSchedulers.mainThread()) + .doOnSuccess(rsPlatformType -> getDialogManager().showProgressDialog(context, true)) + .flatMap((Function>) rsPlatformType -> { + Single single = Single.just(""); + if (rsPlatformType.isConsumeShare()) { + single = single.flatMap((Function>) s -> + getMvpPresenter().getDataModel().getShareImage(SignInModel.SHARE_TYPE_NORMAL, null, null)) + .flatMap((Function>) picUrl -> { + if (TextUtils.isEmpty(picUrl)) { + return Single.error(new Throwable("获取分享图片失败")); + } + return Single.just(picUrl); + }).flatMap((Function>) picUrl -> + ShareModel.get().shareImageForSignIn(rsPlatformType.getPlatform(), picUrl)); + } + return single.flatMap((Function>) s -> + getMvpPresenter().getDataModel().replenishSign(signDay)); + }) + .subscribe(new DontWarnObserver() { + + @Override + public void acceptThrowable(SignInfo signInfo, Throwable throwable) { + super.acceptThrowable(signInfo, throwable); + getDialogManager().dismissDialog(); + if (signInfo != null) { + loadData(true); + SignInUiHelper.showSupplementSignSuccessDialog(context, getDialogManager(), + signInfo.getPrizeName()); + } else if (throwable instanceof RadishNotEnoughException) { + DialogUiHelper.showRadishNotEnoughDialog(context, getDialogManager()); + } else { + toast(throwable.getMessage()); + } + } + + }); + }); + } + + /** + * 广播消息 + */ + @SuppressLint("CheckResult") + private void initBetterMarqueeView() { + getMvpPresenter().getDrawNotice(); + } + + /** + * 初始化奖金池信息 + */ + private void initNumberPoolInfo() { + rtvGoldPool.setText(NumberFormatUtil.formatCommaInt(poolNumber), false); + rtvGoldPool.addCharOrder(","); + rtvGoldPool.addCharOrder(CharOrder.Number); + rtvGoldPool.setCharStrategy(Strategy.CarryBitAnimation(Direction.SCROLL_UP)); + rtvGoldPool.setAnimationDuration(300); + } + + private long poolNumber = 0; + + @Override + public void onBackPressed() { + if (priceAnimUiHelper.onBackPressed()) { + return; + } + super.onBackPressed(); + } + + @OnClick({R.id.tv_sign_in_op, R.id.cl_reward_anim_container, R.id.tv_activity_rule, R.id.tv_sign_in_normal_share}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.tv_sign_in_op: + + if (mSignDetailInfo != null) { + + if (mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_UN_DRAW) { + drawGold(); + + } else if (!mSignDetailInfo.isSign()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_IN_CLICK, "签到按钮-签到页"); + getMvpPresenter().sign(); // 签到 + } else { +// if (BuildConfig.DEBUG) { +// SignInModel signInModel = new SignInModel(); +// signInModel.insertSignDay(28).subscribe(); +// } + } + + } + break; + + case R.id.tv_sign_in_normal_share: + ShareDialog shareDialog = new ShareDialog(this); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.setOnShareDialogItemClick(this); + shareDialog.show(); + break; + + case R.id.cl_reward_anim_container: + clRewardAnimContainer.setVisibility(View.GONE); + break; + + case R.id.tv_activity_rule: + new RuleDialog(SignInActivity.this).openDialog(); + break; + } + } + + @Override + public void signSuccess(long count) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_SUCCESS, + "签到成功-发现页"); + if (count > 0) { + setGoldPool((int) count); + toast("签到成功,奖金池已增加" + count + "金币"); + } + getMvpPresenter().getSignDetail(); + } + + private long lastClick = 0L; + + @Override + public void signFail(String message) { +// toast(message); // 频繁toast会出现无法展示toast的情况; + long currentClick = SystemClock.uptimeMillis(); + if (currentClick - lastClick >= 2000) { + lastClick = currentClick; +// Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(message); + } + } + + @Override + public void getSignDetailSuccess(SignDetailInfo signDetailInfo, boolean isReplenish) { + mSignDetailInfo = signDetailInfo; + + if (mSignDetailInfo != null) { + setSwitchSignInNotice(mSignDetailInfo.getSignRemind()); + if (isFirstLoad) { + setGoldPool(mSignDetailInfo.getShowGoldNum()); + } else if (isReplenish) { + updateReplenishGoldPool(mSignDetailInfo.getShowGoldNum()); + } + + isFirstLoad = false; + setSignOption(mSignDetailInfo); + + if (mSignDetailInfo.isSign()) + setTvSignGift(mSignDetailInfo.getShowText()); + + setTvSignDay(mSignDetailInfo.getTotalDay(), mSignDetailInfo.getDrawGoldDate()); + + if (mRewardTotalNoticeAdapter != null) + mRewardTotalNoticeAdapter.setState(mSignDetailInfo); + + if (mRewardListAdapter != null) { + mRewardListAdapter.setmSignDay(mSignDetailInfo.isSign(), mSignDetailInfo.getTodaySignDay()); + mRewardListAdapter.setUserCanReplenish(mSignDetailInfo.isCanReplenishSign()); + } + } + + } + + @Override + public void getSignDetailFail(String message) { + toast(message); + } + + @Override + public void drawSuccess(SignDrawInfo signDrawInfo) { + dismissDialog(); + + setGoldPool(0L - signDrawInfo.getGoldNum()); + priceAnimUiHelper.setType(PrizeAnimUiHelper.TYPE_DRAW_GOLD); + priceAnimUiHelper.showPrizeInfoUi(PrizeAnim.formatDrawGold(signDrawInfo)); + getMvpPresenter().getSignDetail(); + } + + @Override + public void drawFail(String message) { + dismissDialog(); + toast(message); + } + + @Override + public void setRemindSuccess() { + switchSignInNotice.setEnabled(true); + + } + + @Override + public void setRemindFail(String message) { + switchSignInNotice.setEnabled(true); + toast(message); + } + + @Override + public void getDrawNoticeSuccess(List list) { + ivHorn.setVisibility(ListUtils.isListEmpty(list) ? View.GONE : View.VISIBLE); + + CarveUpGoldAdapter adapter = new CarveUpGoldAdapter(context, list); + bmvSignIn.setAdapter(adapter); + bmvSignIn.start(); + } + + @Override + public void getDrawNoticeFail(String message) { + } + + private RewardTotalNoticeAdapter mRewardTotalNoticeAdapter; + + @Override + public void getRewardTotalNoticeSuccess(List list) { + + if (mRewardTotalNoticeAdapter == null) { + mRewardTotalNoticeAdapter = new RewardTotalNoticeAdapter(mRewardTotal); + mRewardTotalNoticeAdapter.setmRewardTotalListener(this); + + } + mRewardTotalNoticeAdapter.setmList(list); + + if (mSignDetailInfo != null) + mRewardTotalNoticeAdapter.setState(mSignDetailInfo); + } + + @Override + public void getRewardTotalNoticeFail(String message) { + + } + + @Override + public void getRewardTodayNoticeSuccess(List list) { + if (mRewardListAdapter != null) { + mRewardListAdapter.setNewData(list); + } + + } + + @Override + public void getRewardTodayNoticeFail(String message) { + + } + + @Override + public void getShareImageSuccess(String picUrl) { + dismissDialog(); + if (!TextUtils.isEmpty(picUrl) && mSharePlatform != null) { + ShareModel.get().shareImageForSignIn(mSharePlatform, picUrl).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + SignInModel signInModel = new SignInModel(); + signInModel.signShare(); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + } + + @Override + public void getShareImageFail(String message) { + dismissDialog(); + } + + @Override + public void receiveTotalRewardSuccess(ReceiveTotalRewardInfo receiveTotalRewardInfo) { + dismissDialog(); + + priceAnimUiHelper.setType(PrizeAnimUiHelper.TYPE_REWARD_PAGE); + priceAnimUiHelper.showPrizeInfoUi(PrizeAnim.formatReceiveTotalRewardInfo(receiveTotalRewardInfo)); + + getMvpPresenter().getRewardTotalNotice(); + + } + + @Override + public void receiveTotalRewardFail(String message) { + dismissDialog(); + toast(message); + } + + private void setSwitchSignInNotice(boolean isOn) { + switchSignInNotice.setOn(isOn); + } + + private void setSignOption(SignDetailInfo signDetailInfo) { + if (signDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_DRAW) { + tvSignInOp.setBackgroundResource(R.drawable.bg_draw_gold); + tvSignInOp.setText("本次瓜分获得" + signDetailInfo.getDrawGoldNum() + "金币"); + tvSignInOp.setTextSize(15); + tvSignInOp.setEnabled(false); + setDrawOption(signDetailInfo.getDrawGoldNum()); + + } else if (signDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_UN_DRAW) { + tvSignInOp.setBackgroundResource(R.drawable.icon_sign_draw_gold); + tvSignInOp.setText(getString(R.string.label_draw_gold)); + tvSignInOp.setTextSize(18); + tvSignInOp.setEnabled(true); + + } else if (signDetailInfo.isSign()) { + tvSignInOp.setBackgroundResource(R.drawable.icon_sign_in_ed_status); + tvSignInOp.setText(getString(R.string.status_today_has_sign_in)); + tvSignInOp.setTextSize(18); + tvSignInOp.setEnabled(false); + +// if (BuildConfig.DEBUG) { +// tvSignInOp.setEnabled(true); +// } + + } else { + tvSignInOp.setBackgroundResource(R.drawable.icon_sign_in_un_status); + tvSignInOp.setText(getString(R.string.status_point_me_to_sign_in)); + tvSignInOp.setEnabled(true); + } + + } + + private void setDrawOption(long gold) { + tvSignInOp.setBackgroundResource(R.drawable.bg_draw_gold); + String firstPath = "本次瓜分获得"; + String tips = firstPath + gold + "金币"; + SpannableString spannableString = new SpannableString(tips); + + ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#9B40FC")); + spannableString.setSpan(colorSpan, 0, firstPath.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + colorSpan = new ForegroundColorSpan(Color.parseColor("#FF3B6E")); + spannableString.setSpan(colorSpan, firstPath.length(), tips.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvSignInOp.setText(spannableString); + tvSignInOp.setEnabled(false); + } + + private void setGoldPool(long count) { + if (isFirstLoad) { + poolNumber = count; + } else { + poolNumber += count; + } + rtvGoldPool.setText(NumberFormatUtil.formatCommaInt(poolNumber), !isFirstLoad); + } + + private void updateReplenishGoldPool(long newNumber) { + poolNumber = newNumber; + rtvGoldPool.setText(NumberFormatUtil.formatCommaInt(poolNumber), false); + } + + private void setTvSignGift(String showText) { + if (tvAwardInfo != null) { + tvAwardInfo.setText("今日获得" + showText); + } + } + + private void setTvSignDay(int day, String time) { + + if (day == 28) { + String firstPath = "本轮累计已签到"; + String thirdPath = "获得瓜分资格!"; + + String colorTip; + String tips; + SpannableString spannableString; + + colorTip = day +"天,"; + tips = firstPath + colorTip + thirdPath; + spannableString = new SpannableString(tips); + + ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, 0, firstPath.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + colorSpan = new ForegroundColorSpan(Color.parseColor("#FE3E53")); + spannableString.setSpan(colorSpan, firstPath.length(), tips.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvSignDay.setText(spannableString); + + } else { + String firstPath = "本轮累计已签到"; + String thirdPath = "瓜分"; + + String colorTip; + String tips; + SpannableString spannableString; + + if (time == null || TextUtils.isEmpty(time) || time.equals("null")) { + colorTip = String.valueOf(day); + String temp = "天"; + tips = firstPath + colorTip + temp; + spannableString = new SpannableString(tips); + + int start = 0; + int end = firstPath.length(); + ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += colorTip.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#FE3E53")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += temp.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } else { + colorTip = String.valueOf(day); + String temp = "天"+ " "; + tips = firstPath + colorTip + temp + time + thirdPath; + spannableString = new SpannableString(tips); + + int start = 0; + int end = firstPath.length(); + ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += colorTip.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#FE3E53")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += temp.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += time.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#FE3E53")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + start = end; + end += thirdPath.length(); + colorSpan = new ForegroundColorSpan(Color.parseColor("#979797")); + spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + + + tvSignDay.setText(spannableString); + + } + + } + + @Override + public void onStateSwitched(boolean isOn) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_REMIND_SWITCH, "签到提醒开关" + isOn); + switchSignInNotice.setEnabled(false); + getMvpPresenter().setRemind(); + } + + @Override + public void onInAppSharingItemClick() { + } + + private Platform mSharePlatform; + private DialogManager mDialogManager; + + @Override + public void onSharePlatformClick(Platform platform) { + mSharePlatform = platform; + showDialog(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_SHARE_CLICK, "签到-分享"); + getMvpPresenter().getShareImage(SignInModel.SHARE_TYPE_NORMAL, null, null); + + } + + private void showDialog() { + if (mDialogManager == null) + mDialogManager = new DialogManager(this); + mDialogManager.setCanceledOnClickBackKey(false); + mDialogManager.showProgressDialog(this); + + } + + private void dismissDialog() { + if (mDialogManager != null && mDialogManager.isDialogShowing()) + mDialogManager.dismissDialog(); + } + + private long mConfigId = -1; + @Override + public void getRewardTotal(long id) { + showDialog(); + mConfigId = id; + getMvpPresenter().receiveTotalReward(mConfigId); + } + + @Override + public void drawGold() { + if (mSignDetailInfo == null) { + return; + } + if (mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_UN_DRAW) { + CertificateHelper helper = new CertificateHelper(this, new CertificateHelper.CertificateStatusListener() { + @Override + public void certificated() { + showDialog(); + getMvpPresenter().signDraw(); // 瓜分金币 + } + }); + + helper.certificate(true); + + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardListAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardListAdapter.java new file mode 100644 index 000000000..a1d960878 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardListAdapter.java @@ -0,0 +1,96 @@ +package com.yizhuan.erban.radish.signin.adpter; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.RedPointView; +import com.yizhuan.xchat_android_core.radish.signin.bean.RewardNoticeInfo; + +import java.util.List; + +/** + * create by lvzebiao @2019/3/20 + */ +public class RewardListAdapter extends BaseQuickAdapter { + private int mSignDay = -1; + private boolean mIsSign = false; + + /** + * 用户是否能补签,最多补签5次 + */ + private boolean userCanReplenish = false; + + public RewardListAdapter(int layoutId, List data) { + super(layoutId, data); + } + + public void setmSignDay(boolean isSign, int mSignDay) { + this.mSignDay = mSignDay; + this.mIsSign = isSign; + notifyDataSetChanged(); + } + + public void setUserCanReplenish(boolean userCanReplenish) { + this.userCanReplenish = userCanReplenish; + notifyDataSetChanged(); + } + + @Override + protected void convert(BaseViewHolder holder, RewardNoticeInfo item) { + if (item == null) + return; + + holder.itemView.setEnabled(false); + //补签状态 + TextView tvReplenishStatus = holder.getView(R.id.tv_replenish_status); + boolean hasSign = item.getReceive() || (mIsSign && mSignDay == item.getSignDays()); + TextView tvRewardDescription = holder.getView(R.id.tv_reward_description); + tvRewardDescription.setText(item.getSignRewardName()); + ImageView iv = holder.getView(R.id.riv_reward_img); + ImageLoadUtils.loadPhotoThumbnail(mContext, item.getIcon(), iv); + + RedPointView rpv_reward_number = holder.getView(R.id.rpv_reward_number); + rpv_reward_number.setNumber("" + item.getSignDays()); + rpv_reward_number.setBackgroundResource(R.drawable.shape_bg_sign_reward_number_blue); + rpv_reward_number.setVisibility(View.VISIBLE); + if (hasSign) { + holder.setVisible(R.id.iv_is_received, true) + .setVisible(R.id.view_reward_color_bg, true) + .setVisible(R.id.stv_reward_black_cover, true) + .setTextColor(R.id.tv_reward_description, ContextCompat.getColor(mContext, R.color.color_BA98FF)); + rpv_reward_number.setVisibility(View.INVISIBLE); + if (item.getSignType() == RewardNoticeInfo.TYPE_SIGN_REPLENISH) { + tvReplenishStatus.setVisibility(View.VISIBLE); + tvReplenishStatus.setText("已补签"); + tvReplenishStatus.setBackground(null); + } else { + tvReplenishStatus.setVisibility(View.GONE); + } + } else { + holder.setVisible(R.id.iv_is_received, false) + .setVisible(R.id.view_reward_color_bg, false) + .setVisible(R.id.stv_reward_black_cover, false) + .setTextColor(R.id.tv_reward_description, ContextCompat.getColor(mContext, R.color.color_A4A4A6)); + + if (item.isCanReplenishSign()) { + rpv_reward_number.setBackgroundResource(R.drawable.shape_bg_sign_reward_number_gray); + tvReplenishStatus.setVisibility(View.VISIBLE); + tvReplenishStatus.setText("去补签"); + tvReplenishStatus.setBackgroundResource(userCanReplenish ? + R.drawable.shape_bg_replenish_status_ture : R.drawable.shape_bg_replenish_status_false); + holder.itemView.setEnabled(true); + } else { + tvReplenishStatus.setVisibility(View.GONE); + } + } + + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardTotalNoticeAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardTotalNoticeAdapter.java new file mode 100644 index 000000000..d1cff8b6a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/adpter/RewardTotalNoticeAdapter.java @@ -0,0 +1,230 @@ +package com.yizhuan.erban.radish.signin.adpter; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.radish.signin.view.RewardProgressView; +import com.yizhuan.xchat_android_core.radish.signin.bean.RewardNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.Unbinder; + +public class RewardTotalNoticeAdapter{ + private Unbinder mUnbinder; + + @BindView(R.id.il_first) + View vFirst; + @BindView(R.id.il_second) + View vSecond; + @BindView(R.id.il_third) + View vThird; + @BindView(R.id.il_fourth) + View vFourth; + + @BindView(R.id.reward_progress_view) + RewardProgressView mRewardProgressView; + + private List mList; + private SignDetailInfo mSignDetailInfo; + + public RewardTotalNoticeAdapter(View view) { + mUnbinder = ButterKnife.bind(this, view); + } + + public void setmList(List list) { + this.mList = list; + showView(mList); + } + + public List getmList() { + return mList; + } + + public void setState(SignDetailInfo signDetailInfo) { + mSignDetailInfo = signDetailInfo; + showView(mList); + } + + private void showView(boolean isReceived, View root, int levelDay, String label, boolean showIcon) { + ImageView ivReward = root.findViewById(R.id.iv_reward); + TextView tvReward = root.findViewById(R.id.tv_reward); + SuperTextView stv = root.findViewById(R.id.stv_shape); + + stv.setVisibility(View.GONE); + + if (isReceived) { + tvReward.setText("已领取\n" + levelDay + "天"); + tvReward.setTextColor(ContextCompat.getColor(tvReward.getContext(), R.color.color_FEE900)); + ivReward.setImageResource(R.drawable.icon_reward_got); + root.setEnabled(false); + + } else { + tvReward.setTextColor(ContextCompat.getColor(tvReward.getContext(), R.color.color_FEFEFE)); + + if (showIcon) { + ivReward.setImageResource(R.drawable.icon_reward_package); + stv.setVisibility(View.VISIBLE); + root.setEnabled(true); + } else { + ivReward.setImageResource(R.drawable.icon_reward_un_sign_in); + root.setEnabled(false); + } + + tvReward.setText(label); + + } + } + + private void showView(List list) { + if (list != null) { + RewardNoticeInfo info; + boolean showIcon; + switch (list.size()) { + case 3: + info = list.get(2); + showIcon = mSignDetailInfo != null && mSignDetailInfo.getTotalDay() >= info.getSignDays(); + if (info != null) { + showView(info.getReceive(), vThird, info.getSignDays(), info.getSignRewardName() + "\n" + info.getSignDays() + "天", showIcon); + } + + case 2: + info = list.get(1); + showIcon = mSignDetailInfo != null && mSignDetailInfo.getTotalDay() >= info.getSignDays(); + if (info != null) { + showView(info.getReceive(), vSecond, info.getSignDays(), info.getSignRewardName() + "\n" + info.getSignDays() + "天", showIcon); + } + + case 1: + info = list.get(0); + showIcon = mSignDetailInfo != null && mSignDetailInfo.getTotalDay() >= info.getSignDays(); + if (info != null) { + showView(info.getReceive(), vFirst, info.getSignDays(), info.getSignRewardName() + "\n" + info.getSignDays() + "天", showIcon); + } + + } + + showFourth(); + showProgress(); + } + + } + + private void showProgress() { + if (mSignDetailInfo != null) { + + if (mList == null || mList.size() == 0) + return; + + int currentProgress = mSignDetailInfo.getTotalDay(); + switch (mList.size()) { + case 3: + if (currentProgress < mList.get(0).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_LESS_7_DAY); + } else if (currentProgress < mList.get(1).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_7_DAY); + + } else if (currentProgress < mList.get(2).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_14_DAY); + + } else if (currentProgress < 28) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_21_DAY); + + } else + mRewardProgressView.setProress(RewardProgressView.PROGRESS_IS_28_DAY); + break; + + case 2: + if (currentProgress < mList.get(0).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_LESS_7_DAY); + } else if (currentProgress < mList.get(1).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_7_DAY); + + } else if (currentProgress < 28) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_21_DAY); + + } else + mRewardProgressView.setProress(RewardProgressView.PROGRESS_IS_28_DAY); + break; + + case 1: + if (currentProgress < mList.get(0).getSignDays()) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_LESS_7_DAY); + } else if (currentProgress < 28) { + mRewardProgressView.setProress(RewardProgressView.PROGRESS_MORE_21_DAY); + + } else + mRewardProgressView.setProress(RewardProgressView.PROGRESS_IS_28_DAY); + break; + + } + } + } + + private void showFourth() { + + if (mSignDetailInfo != null) { + if (mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_DRAW) { // 已瓜分 + showView(true, vFourth, 28, "已领取\n28天", true); + + } else if (mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_UN_DRAW) { // 能瓜分但未瓜分 + showView(false, vFourth, 28, "瓜分金币\n28天", mSignDetailInfo != null && mSignDetailInfo.getTotalDay() >= 28); + + } else if (mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_UN_OPEN) { // 不可瓜分 + showView(false, vFourth, 28, "瓜分金币\n28天", false); + + } + } + +// if (mSignDetailInfo != null && mSignDetailInfo.getIsDrawGold() == SignDetailInfo.FLAG_DRAW_GOLD_OPEN_DRAW) { +// showView(true, vFourth, 28, "已领取\n28天"); +// +// } else +// showView(false, vFourth, 28, "瓜分金币\n28天"); + + } + + @OnClick({R.id.il_first, R.id.il_second, R.id.il_third, R.id.il_fourth}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.il_first: + if (mRewardTotalListener != null && mList != null && mList.size() > 0) + mRewardTotalListener.getRewardTotal(mList.get(0).getSignRewardConfigId()); + break; + + case R.id.il_second: + if (mRewardTotalListener != null && mList != null && mList.size() > 1) + mRewardTotalListener.getRewardTotal(mList.get(1).getSignRewardConfigId()); + break; + + case R.id.il_third: + if (mRewardTotalListener != null && mList != null && mList.size() > 2) + mRewardTotalListener.getRewardTotal(mList.get(2).getSignRewardConfigId()); + break; + + case R.id.il_fourth: + if (mRewardTotalListener != null) + mRewardTotalListener.drawGold(); + break; + } + } + + private RewardTotalListener mRewardTotalListener; + + public void setmRewardTotalListener(RewardTotalListener rewardTotalListener) { + this.mRewardTotalListener = rewardTotalListener; + } + + public interface RewardTotalListener { + void getRewardTotal(long id); + void drawGold(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/helper/SignInUiHelper.java b/app/src/main/java/com/yizhuan/erban/radish/signin/helper/SignInUiHelper.java new file mode 100644 index 000000000..8f04408aa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/helper/SignInUiHelper.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.radish.signin.helper; + +import android.content.Context; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.utils.SpannableBuilder; + +/** + * create by lvzebiao @2019/4/28 + */ +public class SignInUiHelper { + + public static void showSupplementSignSuccessDialog(Context context, DialogManager dialogManager, + String prizeName) { + if (dialogManager == null) { + dialogManager = new DialogManager(context); + } + View customView = View.inflate(context, R.layout.dialog_supplement_sign_success, null); + TextView tvTitle = customView.findViewById(R.id.tv_title); + tvTitle.setText("补签成功"); + TextView tvContent = customView.findViewById(R.id.tv_content); + if (!TextUtils.isEmpty(prizeName)) { + tvContent.setVisibility(View.VISIBLE); + SpannableBuilder builder = new SpannableBuilder(); + builder.append("获得 ") + .append(prizeName, new ForegroundColorSpan(context.getResources().getColor(R.color.appColor))); + tvContent.setText(builder.build()); + } else { + tvContent.setVisibility(View.GONE); + } + + dialogManager.showOkCancelCustomDialog(customView, "确定", null, true, null); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/presenter/SignInPresenter.java b/app/src/main/java/com/yizhuan/erban/radish/signin/presenter/SignInPresenter.java new file mode 100644 index 000000000..f090f2570 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/presenter/SignInPresenter.java @@ -0,0 +1,192 @@ +package com.yizhuan.erban.radish.signin.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.radish.signin.view.ISignInView; +import com.yizhuan.xchat_android_core.radish.signin.ISignInModel; +import com.yizhuan.xchat_android_core.radish.signin.SignInModel; +import com.yizhuan.xchat_android_core.radish.signin.bean.DrawNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.ReceiveTotalRewardInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.RewardNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDrawInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; + +import java.util.List; + +/** + * create by lvzebiao @2019/3/20 + */ +public class SignInPresenter extends BaseMvpPresenter { + + private ISignInModel dataModel = new SignInModel(); + + public void getSignDetail(boolean isReplenish) { + dataModel.signDetail().subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.getSignDetailFail(error); + } + + @Override + public void onSuccess(SignDetailInfo signDetailInfo) { + if (mMvpView != null) + mMvpView.getSignDetailSuccess(signDetailInfo, isReplenish); + } + }); + + } + + public void getSignDetail() { + getSignDetail(false); + } + + public void sign() { + dataModel.sign().subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.signFail(error); + } + + @Override + public void onSuccess(SignInfo integer) { + if (mMvpView != null) + mMvpView.signSuccess(integer.getSignGoldNum()); + } + }); + } + + public void signDraw() { + dataModel.signDraw().subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.drawFail(error); + + } + + @Override + public void onSuccess(SignDrawInfo signDrawInfo) { + if (mMvpView != null) + mMvpView.drawSuccess(signDrawInfo); + + } + }); + + } + + public void setRemind() { + dataModel.signRemind().subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.setRemindFail(error); + + } + + @Override + public void onSuccess(Boolean aBoolean) { + if (mMvpView != null) + mMvpView.setRemindSuccess(); + + } + }); + } + + public void getDrawNotice() { + dataModel.drawNotice().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.getDrawNoticeFail(error); + + } + + @Override + public void onSuccess(List s) { + if (mMvpView != null) + mMvpView.getDrawNoticeSuccess(s); + + } + }); + } + + public void getRewardTotalNotice() { + dataModel.getRewardTotalNotice().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.getRewardTotalNoticeFail(error); + + } + + @Override + public void onSuccess(List rewardNoticeInfos) { + if (mMvpView != null) + mMvpView.getRewardTotalNoticeSuccess(rewardNoticeInfos); + + } + }); + } + + public void getRewardTodayNotice() { + dataModel.getRewardTodayNotice().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.getRewardTodayNoticeFail(error); + + } + + @Override + public void onSuccess(List rewardNoticeInfos) { + if (mMvpView != null) + mMvpView.getRewardTodayNoticeSuccess(rewardNoticeInfos); + + } + }); + } + + public void getShareImage(int shareType, String day, String reward) { + dataModel.getShareImage(shareType, day, reward).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.getShareImageFail(error); + + } + + @Override + public void onSuccess(String s) { + if (mMvpView != null) + mMvpView.getShareImageSuccess(s); + + } + }); + } + + public void receiveTotalReward(long configId) { + dataModel.receiveTotalReward(configId).subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + if (mMvpView != null) + mMvpView.receiveTotalRewardFail(error); + + } + + @Override + public void onSuccess(ReceiveTotalRewardInfo s) { + if (mMvpView != null) + mMvpView.receiveTotalRewardSuccess(s); + + } + }); + } + + public ISignInModel getDataModel() { + return dataModel; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/view/CarveUpGoldAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/signin/view/CarveUpGoldAdapter.java new file mode 100644 index 000000000..c8448ab63 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/view/CarveUpGoldAdapter.java @@ -0,0 +1,90 @@ +package com.yizhuan.erban.radish.signin.view; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.marqueeview.BetterMarqueeView; +import com.yizhuan.xchat_android_core.radish.signin.bean.DrawNoticeInfo; + +import java.util.List; + +/** + * create by lvzebiao @2019/3/14 + * 瓜分金币的消息轮播器 + */ +public class CarveUpGoldAdapter extends BetterMarqueeView.Adapter{ + + private Context context; + private List data; + private ForegroundColorSpan mFirstColor; + private ForegroundColorSpan mSecondColor; + private ForegroundColorSpan mThirdColor; + + + public CarveUpGoldAdapter(Context context, List data) { + this.context = context; + this.data = data; + + mSecondColor = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.appColor)); + mFirstColor = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.white)); + mThirdColor = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.white)); + } + + @Override + public CarveUpGoldAdapter.MessageViewHolder onCreateView(ViewGroup parent) { + return new CarveUpGoldAdapter.MessageViewHolder( + LayoutInflater.from(this.context) + .inflate(R.layout.item_carve_up_result, + parent, false)); + } + + @Override + public void onBindViewHolder(CarveUpGoldAdapter.MessageViewHolder holder, int position) { + DrawNoticeInfo info = data.get(position); + if (info == null) + return; + + String first = "ID" + info.getErbanNo() + "瓜分"; + String second = String.valueOf(info.getGoldNum()) + "金币"; + String third = "!"; + + SpannableString spannableString = new SpannableString(first + second + third); + spannableString.setSpan(mFirstColor, 0, first.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE); + spannableString.setSpan(mSecondColor, first.length(), first.length() + second.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE); + spannableString.setSpan(mThirdColor, first.length() + second.length(), first.length() + second.length() + third.length(), SpannableString.SPAN_INCLUSIVE_EXCLUSIVE); + holder.notice.setText(spannableString); + } + + @Override + public int getSize() { + return data.size(); + } + + public void setNewData(List newData) { + data.clear(); + data.addAll(newData); + notifyDateSetChange(); + } + + class MessageViewHolder extends BetterMarqueeView.ViewHolder { + + TextView masterName; + TextView apprenticeName; + TextView notice; + + public MessageViewHolder(View view) { + super(view); + masterName = view.findViewById(R.id.tv_master_name); + apprenticeName = view.findViewById(R.id.tv_apprentice_name); + notice = view.findViewById(R.id.tv_notice); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/view/ISignInView.java b/app/src/main/java/com/yizhuan/erban/radish/signin/view/ISignInView.java new file mode 100644 index 000000000..ae48ac7f3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/view/ISignInView.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.radish.signin.view; + +import com.yizhuan.xchat_android_core.radish.signin.bean.DrawNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.ReceiveTotalRewardInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.RewardNoticeInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDrawInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * create by lvzebiao @2019/3/20 + */ +public interface ISignInView extends IMvpBaseView { + void signSuccess(long count); + void signFail(String message); + + void getSignDetailSuccess(SignDetailInfo signDetailInfo, boolean isReplenish); + void getSignDetailFail(String message); + + void drawSuccess(SignDrawInfo signDrawInfo); + void drawFail(String message); + + void setRemindSuccess(); + void setRemindFail(String message); + + void getDrawNoticeSuccess(List list); + void getDrawNoticeFail(String message); + + void getRewardTotalNoticeSuccess(List list); + void getRewardTotalNoticeFail(String message); + + void getRewardTodayNoticeSuccess(List list); + void getRewardTodayNoticeFail(String message); + + void getShareImageSuccess(String picUrl); + void getShareImageFail(String message); + + void receiveTotalRewardSuccess(ReceiveTotalRewardInfo info); + void receiveTotalRewardFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/view/RewardProgressView.java b/app/src/main/java/com/yizhuan/erban/radish/signin/view/RewardProgressView.java new file mode 100644 index 000000000..4895d3feb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/view/RewardProgressView.java @@ -0,0 +1,92 @@ +package com.yizhuan.erban.radish.signin.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * 签到奖品的进度 + * create by lvzebiao @2019/3/15 + */ +public class RewardProgressView extends View { + /**小于7天*/ + public final static int PROGRESS_LESS_7_DAY = 1; + /**>=7天*/ + public final static int PROGRESS_MORE_7_DAY = 2; + /**>=14天*/ + public final static int PROGRESS_MORE_14_DAY = 3; + /**>=21天*/ + public final static int PROGRESS_MORE_21_DAY = 4; + /**=28天*/ + public final static int PROGRESS_IS_28_DAY = 5; + + private int progressType; + + private Paint paint; + + private int lineTop, lineBottom; + + private int bgColor, progressColor; + + public RewardProgressView(Context context) { + this(context, null); + } + + public RewardProgressView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + progressType = PROGRESS_LESS_7_DAY; + paint = new Paint(); + paint.setAntiAlias(true); + paint.setStyle(Paint.Style.FILL); + lineTop = UIUtil.dip2px(context, 2); + lineBottom = UIUtil.dip2px(context, 7); + bgColor = context.getResources().getColor(R.color.color_A98AFF); + progressColor = Color.WHITE; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (progressType == PROGRESS_LESS_7_DAY) { + paint.setColor(bgColor); + canvas.drawRect(0, lineTop, getWidth(), lineBottom, paint); + + } else { + int offsetX = 0; + if (progressType == PROGRESS_MORE_7_DAY){ + offsetX = getWidth() / 6; + + } else if (progressType == PROGRESS_MORE_14_DAY){ + offsetX = getWidth() / 2; + + } else if (progressType == PROGRESS_MORE_21_DAY){ + offsetX = getWidth() * 5 / 6; + + } else if (progressType == PROGRESS_IS_28_DAY){ + offsetX = getWidth(); + + } + paint.setColor(progressColor); + canvas.drawRect(0, lineTop, offsetX, lineBottom, paint); + paint.setColor(bgColor); + canvas.drawRect(offsetX, lineTop, getWidth(), lineBottom, paint); + //画圆点 + int radius = getHeight() / 2; + paint.setColor(progressColor); + canvas.drawCircle(offsetX, radius, radius, paint); + + } + } + + public void setProress(int proress) { + this.progressType = proress; + invalidate(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/view/RuleDialog.java b/app/src/main/java/com/yizhuan/erban/radish/signin/view/RuleDialog.java new file mode 100644 index 000000000..c717466b7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/view/RuleDialog.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.radish.signin.view; + +import android.content.Context; +import android.os.Build; +import android.webkit.WebSettings; +import android.webkit.WebViewClient; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.databinding.DialogRuleBinding; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.dialog_rule) +public class RuleDialog extends BaseBindingDialog { + public RuleDialog(Context context) { + super(context); + } + + @Override + protected void init() { + binding.ivClose.setOnClickListener(v -> dismiss()); + + binding.wvRule.getSettings().setUseWideViewPort(true); + // 设置 WebView 可以在 HTTPS 通道上加载 HTTP 资源,Android 4.4 后的暗坑 + // 因为 Android 4.4 后默认不允许在 HTTPS 通道上加载 HTTP 资源 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + binding.wvRule.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + } + binding.wvRule.getSettings().setTextZoom(100); + binding.wvRule.setWebViewClient(new WebViewClient()); + // 设置Webview的user-agent + binding.wvRule.getSettings().setUserAgentString(binding.wvRule.getSettings().getUserAgentString() + " tutuAppAndroid erbanAppAndroid"); + binding.wvRule.loadUrl(UriProvider.JAVA_WEB_URL + "/modules/rule/rule-popup.html"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/signin/view/SignInDialog.java b/app/src/main/java/com/yizhuan/erban/radish/signin/view/SignInDialog.java new file mode 100644 index 000000000..1fd526186 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/signin/view/SignInDialog.java @@ -0,0 +1,202 @@ +package com.yizhuan.erban.radish.signin.view; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.radish.signin.SignInActivity; +import com.yizhuan.erban.utils.NumberFormatUtil; +import com.yizhuan.xchat_android_core.radish.signin.ISignInModel; +import com.yizhuan.xchat_android_core.radish.signin.SignInModel; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignDetailInfo; +import com.yizhuan.xchat_android_core.radish.signin.bean.SignInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yy.mobile.rollingtextview.CharOrder; +import com.yy.mobile.rollingtextview.RollingTextView; +import com.yy.mobile.rollingtextview.strategy.Direction; +import com.yy.mobile.rollingtextview.strategy.Strategy; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * 签到弹框 + * create by lvzebiao @2019/3/15 + */ +public class SignInDialog extends AppCompatDialog { + + @BindView(R.id.tv_award_info) + TextView tvAwardInfo; + private Context context; + + @BindView(R.id.iv_close) + ImageView ivClose; + @BindView(R.id.rtv_gold_pool) + RollingTextView rtvGoldPool; + @BindView(R.id.tv_sign_in_op) + TextView tvSignInOp; + + private SignDetailInfo detailInfo; + + private boolean hasClickSignIn = false; + + private ISignInModel model = new SignInModel(); + + public SignInDialog(Context context, SignDetailInfo detailInfo) { + this(context, 0, detailInfo); + } + + public SignInDialog(Context context, int theme, SignDetailInfo detailInfo) { + super(context, theme); + this.context = context; + this.detailInfo = detailInfo; + } + + public static void display(Context context, SignDetailInfo detailInfo) { + SignInDialog dialog = new SignInDialog(context, detailInfo); + dialog.show(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_sign_in); + ButterKnife.bind(this); + setCancelable(true); + setCanceledOnTouchOutside(true); + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.dimAmount = 0.65f; + window.setAttributes(windowParams); + //默认动画 + //window.setWindowAnimations(R.style.anim_sign_in); + } + rtvGoldPool.addCharOrder(","); + rtvGoldPool.addCharOrder(CharOrder.Number); + rtvGoldPool.setCharStrategy(Strategy.CarryBitAnimation(Direction.SCROLL_UP)); + rtvGoldPool.setAnimationDuration(300); + rtvGoldPool.setOnClickListener(v -> SignInActivity.start(context)); + loadData(true); + } + + private void loadData(boolean isSetPoolNumbe) { + setDataView(isSetPoolNumbe); + } + + private void setDataView(boolean isSetPoolNumber) { + if (detailInfo == null) { + return; + } + refreshSignStatus(); + if (isSetPoolNumber) { + rtvGoldPool.setText(NumberFormatUtil.formatCommaInt(detailInfo.getShowGoldNum()), false); + } + tvAwardInfo.setVisibility(View.INVISIBLE); + setAwardInfo(); + } + + /** + * 刷新状态 + */ + private void refreshSignStatus() { + tvSignInOp.setClickable(false); + tvSignInOp.setTextColor(context.getResources().getColor(R.color.white)); + tvSignInOp.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + if (detailInfo.isSign()) { + tvSignInOp.setBackgroundResource(R.drawable.icon_sign_in_ed_status); + tvSignInOp.setText(context.getString(R.string.sign_in_continue_number_days, + detailInfo.getTotalDay())); + } else { + tvSignInOp.setClickable(true); + tvSignInOp.setBackgroundResource(R.drawable.icon_sign_in_un_status); + tvSignInOp.setText(R.string.status_point_me_to_sign_in); + tvSignInOp.setOnClickListener(v -> requestSign()); + } + } + + private void setAwardInfo() { + if (detailInfo == null) { + return; + } + if (detailInfo.isSign() && !TextUtils.isEmpty(detailInfo.getSignPrizeName())) { + tvAwardInfo.setVisibility(View.VISIBLE); + tvAwardInfo.setText("今日获得" + detailInfo.getShowText()); + } + } + + @OnClick({R.id.iv_close}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.iv_close: + if (!hasClickSignIn) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_POPUP_SIGN_CLOSED, + "签到弹框关闭按钮"); + } + dismiss(); + break; + } + } + + private void requestSign() { + if (detailInfo == null) { + return; + } + hasClickSignIn = true; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_POPUP_SIGN_IN_CLICK, + "签到按钮-签到弹窗"); + tvSignInOp.setClickable(false); + model.sign().compose(RxHelper.bindContext(context)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + tvSignInOp.setClickable(true); + } + + @Override + public void onSuccess(SignInfo signInfo) { + long addGoldNum = signInfo.getSignGoldNum(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SIGN_SUCCESS, + "签到成功-弹框"); + SingleToastUtil.showToast("签到成功,奖金池已增加" + addGoldNum + "金币"); + //启动播放动画 + long newPoolNumber = addGoldNum + detailInfo.getShowGoldNum(); + rtvGoldPool.setText(NumberFormatUtil.formatCommaInt(newPoolNumber), true); + detailInfo.setIsSign(1); + detailInfo.setTotalDay(detailInfo.getTotalDay() + 1); + loadData(false); + model.signDetail().subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(SignDetailInfo info) { + detailInfo = info; + setAwardInfo(); + } + }); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/activity/TaskCenterActivity.java b/app/src/main/java/com/yizhuan/erban/radish/task/activity/TaskCenterActivity.java new file mode 100644 index 000000000..e29c79155 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/activity/TaskCenterActivity.java @@ -0,0 +1,172 @@ +package com.yizhuan.erban.radish.task.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewStub; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.adapter.RoomContributeListAdapter; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.radish.helper.PrizeAnimUiHelper; +import com.yizhuan.erban.radish.task.fragment.TaskCenterFragment; +import com.yizhuan.erban.radish.task.presenter.TaskCenterPresenter; +import com.yizhuan.erban.radish.task.view.ITaskCenterView; +import com.yizhuan.erban.radish.widget.TaskCenterNavAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.radish.task.bean.PrizeAnim; +import com.yizhuan.xchat_android_core.radish.task.bean.TaskInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +import java.util.ArrayList; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * 任务中心 + * create by lvzebiao @2019/3/26 + */ +@CreatePresenter(TaskCenterPresenter.class) +public class TaskCenterActivity extends BaseMvpActivity implements ITaskCenterView { + + public interface FromPage { + String GIFT = "-礼物面板"; + String FIND = "-发现页"; + String RADISH_NOT_ENOUGH_DIALOG = "-萝卜不足弹窗"; + } + + /** + * 任务中心是否第一次启动 + */ + public final static String KEY_TASK_CENTER_FIRST_START = "task_center_first_start"; + + @BindView(R.id.title_bar) + TitleBar titleBar; + @BindView(R.id.mi_task) + MagicIndicator magicIndicator; + @BindView(R.id.vp_task_center) + ViewPager viewPager; + @BindView(R.id.vs_start_tips) + ViewStub vsStartTips; + + PrizeAnimUiHelper priceAnimUiHelper; + + public static void start(Context context, String fromPage) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_FIND_TASK_CLICK, + "任务中心" + fromPage); + Intent intent = new Intent(context, TaskCenterActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_task_center); + ButterKnife.bind(this); + initTitleBar(context.getResources().getString(R.string.task_center)); + priceAnimUiHelper = new PrizeAnimUiHelper(); + priceAnimUiHelper.onCreate(this, findViewById(R.id.cl_reward_anim_container), + PrizeAnimUiHelper.TYPE_TASK_PAGE, getDialogManager()); + + ArrayList fragments = new ArrayList<>(2); + TaskCenterFragment days = TaskCenterFragment.newInstance(TaskCenterFragment.TYPE_TASK); + days.setiTaskCenterView(this); + TaskCenterFragment task = TaskCenterFragment.newInstance(TaskCenterFragment.TYPE_ACHIEVEMENT); + task.setiTaskCenterView(this); + fragments.add(days); + fragments.add(task); + + viewPager.setAdapter(new RoomContributeListAdapter(getSupportFragmentManager(), fragments)); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + + TaskCenterNavAdapter indicator = new TaskCenterNavAdapter(); + indicator.setOnItemSelectListener(position -> viewPager.setCurrentItem(position)); + commonNavigator.setAdapter(indicator); + magicIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(magicIndicator, viewPager); + +// showStartTips(); + } + + @Override + public void onBackPressed() { + if (priceAnimUiHelper.onBackPressed()) { + return; + } + super.onBackPressed(); + } + + @Override + public void playPriceAnim(TaskInfo info) { + if (priceAnimUiHelper != null && info != null) + priceAnimUiHelper.showPrizeInfoUi(PrizeAnim.formatTaskInfo(info)); + } + + public void initTitleBar(String title) { + mTitleBar = findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.mipmap.common_ic_back_white); + mTitleBar.setCommonBackgroundColor(getResources().getColor(R.color.transparent)); + mTitleBar.setLeftClickListener(v -> onLeftClickListener()); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + priceAnimUiHelper.onDestroy(); + } + + private int indexTips = 0; + + /** + * 首次启动展示 提示图 + */ + private void showStartTips() { + boolean isFirst = (boolean) SharedPreferenceUtils.get(KEY_TASK_CENTER_FIRST_START, true); + if (!isFirst) { + return; + } + SharedPreferenceUtils.put(KEY_TASK_CENTER_FIRST_START, false); + View llTaskTtartContainer = vsStartTips.inflate(); + int[] topTipsRes = new int[]{R.drawable.cover_task_top_first, R.drawable.cover_task_top_second, + R.drawable.cover_task_top_third, R.drawable.cover_task_top_fourth}; + + ImageView ivTipsTop = llTaskTtartContainer.findViewById(R.id.iv_tips_top); + ivTipsTop.setImageResource(topTipsRes[indexTips++]); + + TextView tv_skip_guide = llTaskTtartContainer.findViewById(R.id.tv_skip_guide); + tv_skip_guide.setOnClickListener(v -> + llTaskTtartContainer.setVisibility(View.GONE)); + tv_skip_guide.setVisibility(View.VISIBLE); + llTaskTtartContainer.setOnClickListener(v -> { + if (indexTips < topTipsRes.length) { + if (indexTips == topTipsRes.length - 1) { + tv_skip_guide.setVisibility(View.GONE); + } else { + tv_skip_guide.setVisibility(View.VISIBLE); + } + ivTipsTop.setImageResource(topTipsRes[indexTips++]); + } else { + llTaskTtartContainer.setVisibility(View.GONE); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/adpter/TaskCenterAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/task/adpter/TaskCenterAdapter.java new file mode 100644 index 000000000..9908a48b7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/adpter/TaskCenterAdapter.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.radish.task.adpter; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.radish.task.bean.TaskInfo; + +/** + * create by lvzebiao @2019/3/26 + */ +public class TaskCenterAdapter extends BaseQuickAdapter { + + private Context context; + + public TaskCenterAdapter(Context context) { + super(R.layout.item_task); + this.context = context; + } + + @Override + protected void convert(BaseViewHolder helper, TaskInfo item) { + helper.setText(R.id.tv_task_name, item.getName()); + helper.setText(R.id.tv_task_desc, item.getDescription()); + + TextView tvOperationStatus = helper.getView(R.id.tv_operation_status); + helper.addOnClickListener(R.id.tv_operation_status); + tvOperationStatus.setClickable(true); + if (item.getStatus() == TaskInfo.STATUS_HAS_RECEIVED) { + //已完成 + tvOperationStatus.setText(R.string.task_done); + tvOperationStatus.setBackgroundResource(R.drawable.icon_task_has_received); + tvOperationStatus.setTextColor(context.getResources().getColor(R.color.color_B3B3B3)); + tvOperationStatus.setClickable(false); + } else if (item.getStatus() == TaskInfo.STATUS_FINISHED_NOT_RECEIVE) { + //完成未领取 + tvOperationStatus.setText(R.string.task_receive); + tvOperationStatus.setBackgroundResource(R.drawable.icon_task_finished_not_receive); + tvOperationStatus.setTextColor(context.getResources().getColor(R.color.white)); + } else { + //未完成 + tvOperationStatus.setText(R.string.task_go_to_finish); + tvOperationStatus.setBackgroundResource(R.drawable.icon_task_un_finish); + tvOperationStatus.setTextColor(context.getResources().getColor(R.color.white)); + } + + ImageView ivPrizeIcon = helper.getView(R.id.iv_prize_icon); + if (TextUtils.isEmpty(item.getPrizeIcon())) { + ivPrizeIcon.setVisibility(View.INVISIBLE); + } else { + ivPrizeIcon.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(context, item.getPrizeIcon(), ivPrizeIcon); + } + + TextView tvPrizeNum = helper.getView(R.id.tv_prize_num); + if (item.getPrizeNum() > 0) { + tvPrizeNum.setVisibility(View.VISIBLE); + tvPrizeNum.setText("x" + item.getPrizeNum()); + } else { + tvPrizeNum.setVisibility(View.INVISIBLE); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/fragment/TaskCenterFragment.java b/app/src/main/java/com/yizhuan/erban/radish/task/fragment/TaskCenterFragment.java new file mode 100644 index 000000000..6576d4b67 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/fragment/TaskCenterFragment.java @@ -0,0 +1,221 @@ +package com.yizhuan.erban.radish.task.fragment; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SimpleItemAnimator; +import android.view.LayoutInflater; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.radish.helper.TaskCenterDialogHelper; +import com.yizhuan.erban.radish.task.adpter.TaskCenterAdapter; +import com.yizhuan.erban.radish.task.presenter.TaskCenterFrgPresenter; +import com.yizhuan.erban.radish.task.view.ITaskCenterView; +import com.yizhuan.erban.radish.task.view.ITaskCenterViewFrg; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.HorizontalDecoration; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.xchat_android_core.radish.task.ITaskModel; +import com.yizhuan.xchat_android_core.radish.task.TaskModel; +import com.yizhuan.xchat_android_core.radish.task.bean.TaskInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import butterknife.BindView; +import butterknife.ButterKnife; + +@CreatePresenter(TaskCenterFrgPresenter.class) +public class TaskCenterFragment extends BaseMvpFragment implements ITaskCenterViewFrg{ + + public static final int TYPE_TASK = 1; + public static final int TYPE_ACHIEVEMENT = 2; + + @BindView(R.id.rv_task_list) + RecyclerView rvTaskList; + @BindView(R.id.swipe_refresh) + SwipeRefreshLayout swipeRefresh; + + private TaskCenterAdapter adapter; + ITaskModel model = new TaskModel(); + private ITaskCenterView iTaskCenterView; + + public static TaskCenterFragment newInstance(int type) { + TaskCenterFragment fragment = new TaskCenterFragment(); + Bundle bundle = new Bundle(); + bundle.putInt("type", type); + fragment.setArguments(bundle); + return fragment; + } + + public void setiTaskCenterView(ITaskCenterView iTaskCenterView) { + this.iTaskCenterView = iTaskCenterView; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_task_center; + } + + @Override + public void onFindViews() { + ButterKnife.bind(this, mView); + + rvTaskList.setLayoutManager(new LinearLayoutManager(mContext)); + rvTaskList.addItemDecoration(new HorizontalDecoration(UIUtil.dip2px(mContext, 12), true, true)); + ((SimpleItemAnimator) rvTaskList.getItemAnimator()).setSupportsChangeAnimations(false); // 禁recyclerView动画, 防止图片闪烁 + + adapter = new TaskCenterAdapter(mContext); + adapter.setHasStableIds(true); // 禁recyclerView动画, 防止图片闪烁 + adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adp, View view, int position) { + if (!(view.getId() == R.id.tv_operation_status)) { + return; + } + TaskInfo info = null; + if (position < adapter.getData().size()) { + info = adapter.getData().get(position); + } + if (info == null) { + return; + } + final TaskInfo item = info; + if (!item.isSupport()) { + SingleToastUtil.showToast(XChatConstants.UPDATE_VERSION_TIPS); + return; + } + if (item.getStatus() == TaskInfo.STATUS_FINISHED_NOT_RECEIVE) { + view.setClickable(false); + + if (mType == TYPE_TASK) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_TASK_GET_CLICK, + "每日任务领取按钮" + item.getName()); + + } else if (mType == TYPE_ACHIEVEMENT) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CJTASK_GET_CLICK, + "成就任务领取按钮" + item.getName()); + + } + + new TaskModel().receivePrice(item.getConfigId(), item.getPrizeType()) + .compose(RxHelper.bindContext(mContext)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + view.setClickable(true); + SingleToastUtil.showToast(error); + } else { + item.setStatus(TaskInfo.STATUS_HAS_RECEIVED); + adapter.notifyItemChanged(position); + //播放动画 + if (iTaskCenterView != null) + iTaskCenterView.playPriceAnim(item); + } + } + }); + + } else if (item.getStatus() == TaskInfo.STATUS_UN_FINISH) { + boolean record = false; + if (item.getSkipType() == TaskInfo.SHIP_TYPE_APP) { + boolean result = RouterHandler.handle(mContext, item.getRouterType(), item.getRouterValue()); + if (!result) { + SingleToastUtil.showToast(XChatConstants.UPDATE_VERSION_TIPS); + return; + } + + record = true; + + } else if (item.getSkipType() == TaskInfo.SHIP_TYPE_TASK){ + TaskCenterDialogHelper helper = new TaskCenterDialogHelper(mContext); + helper.showDialog(item.getStepPic()); + record = true; + + } else + SingleToastUtil.showToast(XChatConstants.UPDATE_VERSION_TIPS); + + if (record) { + if (mType == TYPE_TASK) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_TASK_TOFINSH_CLICK, + "去完成按钮" + item.getName()); + + } else if (mType == TYPE_ACHIEVEMENT) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_CJTASK_TOFINSH_CLICK, + "去完成按钮" + item.getName()); + + } + + } + } + } + }); + + rvTaskList.setAdapter(adapter); + swipeRefresh.setOnRefreshListener(this::loadData); + } + + @Override + public void onResume() { + super.onResume(); + loadData(); + } + + @SuppressLint("CheckResult") + private void loadData() { + //noinspection ResultOfMethodCallIgnored + if (mType == TYPE_TASK) { + model.getTaskList() + .compose(bindToLifecycle()) + .subscribe((taskInfos, throwable) -> { + swipeRefresh.setRefreshing(false); + if (throwable != null) { + toast(throwable.getMessage()); + } else { + adapter.setNewData(taskInfos); + } + }); + + } else if (mType == TYPE_ACHIEVEMENT) { + model.getAchievementTaskList() + .compose(bindToLifecycle()) + .subscribe((taskInfos, throwable) -> { + swipeRefresh.setRefreshing(false); + if (throwable != null) { + toast(throwable.getMessage()); + } else { + adapter.setNewData(taskInfos); + } + }); + + } + + } + + @Override + public void onSetListener() { + + } + + private int mType = 1; + @Override + public void initiate() { + Bundle bundle = getArguments(); + if (bundle != null) + mType = bundle.getInt("type", 1); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterFrgPresenter.java b/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterFrgPresenter.java new file mode 100644 index 000000000..da4835cef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterFrgPresenter.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.radish.task.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.radish.task.view.ITaskCenterViewFrg; + +public class TaskCenterFrgPresenter extends BaseMvpPresenter { +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterPresenter.java b/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterPresenter.java new file mode 100644 index 000000000..9b5b1acf2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/presenter/TaskCenterPresenter.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.radish.task.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.radish.task.view.ITaskCenterView; + +/** + * create by lvzebiao @2019/3/27 + */ +public class TaskCenterPresenter extends BaseMvpPresenter { + + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterView.java b/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterView.java new file mode 100644 index 000000000..9a748c4ed --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterView.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.radish.task.view; + +import com.yizhuan.xchat_android_core.radish.task.bean.TaskInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + * create by lvzebiao @2019/3/27 + */ +public interface ITaskCenterView extends IMvpBaseView { + void playPriceAnim(TaskInfo info); +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterViewFrg.java b/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterViewFrg.java new file mode 100644 index 000000000..b726bb91b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/task/view/ITaskCenterViewFrg.java @@ -0,0 +1,6 @@ +package com.yizhuan.erban.radish.task.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface ITaskCenterViewFrg extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordFrgView.java b/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordFrgView.java new file mode 100644 index 000000000..df5dba45e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordFrgView.java @@ -0,0 +1,9 @@ +package com.yizhuan.erban.radish.view; + +import com.yizhuan.xchat_android_core.bills.bean.RadishRecordListInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IRadishRecordFrgView extends IMvpBaseView { + void getRadishRecordSuccess(RadishRecordListInfo list); + void getRadishRecordFail(String message); +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordView.java b/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordView.java new file mode 100644 index 000000000..f09a90de2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/view/IRadishRecordView.java @@ -0,0 +1,6 @@ +package com.yizhuan.erban.radish.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface IRadishRecordView extends IMvpBaseView { +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/wallet/RadishWalletManager.java b/app/src/main/java/com/yizhuan/erban/radish/wallet/RadishWalletManager.java new file mode 100644 index 000000000..79b5716e2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/wallet/RadishWalletManager.java @@ -0,0 +1,59 @@ +package com.yizhuan.erban.radish.wallet; + +import android.arch.lifecycle.LifecycleOwner; +import android.arch.lifecycle.MutableLiveData; +import android.arch.lifecycle.Observer; + +import com.yizhuan.xchat_android_core.radish.RadishModel; +import com.yizhuan.xchat_android_core.radish.RadishWalletInfo; +import com.yizhuan.xchat_android_core.radish.event.RadishWalletInfoUpdateEvent; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +/** + * 萝卜数据统一管理,与data层接通数据 + * 连接UI层显示 + * create by lvzebiao @2019/3/25 + */ +public class RadishWalletManager { + + private static final class Helper { + public static final RadishWalletManager INSTANCE = new RadishWalletManager(); + } + + private RadishWalletManager() { + EventBus.getDefault().register(this); + ldRadishWallet.setValue(new RadishWalletInfo()); + } + + public static RadishWalletManager get() { + return Helper.INSTANCE; + } + + private MutableLiveData ldRadishWallet = new MutableLiveData<>(); + + public void registerRadishNum(LifecycleOwner owner, Observer observer) { + ldRadishWallet.observe(owner, observer); + } + + public MutableLiveData getLdRadishNumber() { + return ldRadishWallet; + } + + public void updateRadishNum(long newNum) { + RadishWalletInfo info = RadishModel.get().getRadishWalletInfo(); + info.setAmount(newNum); + ldRadishWallet.setValue(info); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRadishWalletInfoUpdateEvent(RadishWalletInfoUpdateEvent event) { + RadishWalletInfo info = RadishModel.get().getRadishWalletInfo(); + if (info != null) { + ldRadishWallet.setValue(info); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/widget/RadishRecordNavAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/widget/RadishRecordNavAdapter.java new file mode 100644 index 000000000..aaf026e4d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/widget/RadishRecordNavAdapter.java @@ -0,0 +1,75 @@ +package com.yizhuan.erban.radish.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.ArrayList; +import java.util.List; + +public class RadishRecordNavAdapter extends CommonNavigatorAdapter { + + private List mTitleList = new ArrayList<>(); + + public RadishRecordNavAdapter() { + mTitleList.add("收入"); + mTitleList.add("支出"); + } + + @Override + public int getCount() { + return mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_B3FFFFFF)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.white)); + scaleTransitionPagerTitleView.setMinScale(1.0f); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(index)); + + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(index); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(context, 0)); + indicator.setRoundRadius(UIUtil.dip2px(context, 0)); + indicator.setLineWidth(UIUtil.dip2px(context, 0)); + indicator.setColors(Color.parseColor("#FF894F")); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + //lp.bottomMargin = 0; + indicator.setLayoutParams(lp); + return indicator; + } + + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener mOnItemSelectListener) { + this.mOnItemSelectListener = mOnItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/radish/widget/TaskCenterNavAdapter.java b/app/src/main/java/com/yizhuan/erban/radish/widget/TaskCenterNavAdapter.java new file mode 100644 index 000000000..16009beef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/radish/widget/TaskCenterNavAdapter.java @@ -0,0 +1,75 @@ +package com.yizhuan.erban.radish.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.ArrayList; +import java.util.List; + +public class TaskCenterNavAdapter extends CommonNavigatorAdapter { + + private List mTitleList = new ArrayList<>(); + + public TaskCenterNavAdapter() { + mTitleList.add("每日任务"); + mTitleList.add("成就任务"); + } + + @Override + public int getCount() { + return mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_B3FFFFFF)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.white)); + scaleTransitionPagerTitleView.setMinScale(1.0f); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(index)); + + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(index); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(context, 4)); + indicator.setRoundRadius(UIUtil.dip2px(context, 2)); + indicator.setLineWidth(UIUtil.dip2px(context, 17)); + indicator.setColors(Color.parseColor("#FFFFFF")); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + //lp.bottomMargin = 0; + indicator.setLayoutParams(lp); + return indicator; + } + + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener mOnItemSelectListener) { + this.mOnItemSelectListener = mOnItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/reciever/ConnectiveChangedReceiver.java b/app/src/main/java/com/yizhuan/erban/reciever/ConnectiveChangedReceiver.java new file mode 100644 index 000000000..a29d13f10 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/reciever/ConnectiveChangedReceiver.java @@ -0,0 +1,199 @@ +package com.yizhuan.erban.reciever; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Handler; + +import com.yizhuan.xchat_android_library.utils.BlankUtil; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Creator: 舒强睿 + * Date:2015/2/12 + * Time:20:21 + *

+ * Description:监听网络状态改变 + */ +public class ConnectiveChangedReceiver extends BroadcastReceiver { + + public static final String ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + + private Context context; + + int currentState;//当前网络状态 第一次初始化 + boolean hasChanged;//网络类型是否已经通知改变(interval时间后会重置为false) + final long interval = 2000L;//检验网络变化时间间隔为interval (毫秒) + + private static ConnectiveChangedReceiver receiver = new ConnectiveChangedReceiver(); + private IntentFilter intentFilter; + private Handler handler; + + private List listeners;//观察者(观察网络变化对象)列表 + + private ConnectiveChangedReceiver() { + } + + public int getCurrentState() { + return currentState; + } + + public void init(Context context) { + this.context = context; + this.currentState = NetworkUtils.getNetworkType(context); + + intentFilter = new IntentFilter(); + intentFilter.addAction(ConnectiveChangedReceiver.ACTION); + } + + public static ConnectiveChangedReceiver getInstance() { + return receiver; + } + + public void registerConnectiveChange(ConnectiveChangedListener listener) { + + if (listener != null) { + + if (listeners == null) { + listeners = new ArrayList(); + } + + listeners.add(listener); + + tryOpenObserver(); + } + } + + public void unRegisterConnectiveChange(ConnectiveChangedListener listener) { + + if (listener != null && listeners != null && listeners.size() > 0) { + + listeners.remove(listener); + + tryClosedObserver(); + } + } + + /** + * 可能listeners 对象变成 null了,这里交给引用的地方 unRegisterConnectiveChange(..) + */ + private void tryOpenObserver() { + + if (listeners != null && listeners.size() == 1) { + context.registerReceiver(this, intentFilter); + } + } + + private void tryClosedObserver() { + + if (BlankUtil.isBlank(listeners)) { + context.unregisterReceiver(this); + } + } + + + @Override + public void onReceive(final Context context, Intent intent) { + + /*int afterChanged = NetworkUtils.getNetworkType(context);//检测通知时网络链接是否真的有变化*/ + if (!hasChanged) { + hasChanged = true; + + if (handler == null) { + handler = new Handler(); + } + + handler.postDelayed(new Runnable() { + + @Override + public void run() { + hasChanged = false; + int networkState = NetworkUtils.getNetworkType(context); + + if (networkState != currentState) {//通知网络发生变化 + if (!BlankUtil.isBlank(listeners)) { + + if (currentState == NetworkUtils.NET_WIFI) {//wifi + if (networkState == NetworkUtils.NET_3G + || networkState == NetworkUtils.NET_2G) { + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).wifiChange2MobileData(); + } + } else {//wifi转无网络 + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).change2NoConnection(); + } + } + } else if (currentState == NetworkUtils.NET_3G + || currentState == NetworkUtils.NET_2G) { //手机流量 + if (networkState == NetworkUtils.NET_WIFI) {//3G->wifi + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).mobileDataChange2Wifi(); + } + } else {//3G转无网络 + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).change2NoConnection(); + } + } + } else {//无网络 + if (networkState == NetworkUtils.NET_WIFI) { + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).connectiveWifi(); + } + } else if (networkState == NetworkUtils.NET_3G + || networkState == NetworkUtils.NET_2G) { + int size = listeners.size(); + for (int i = 0; i < size; i++) { + listeners.get(i).connectiveMobileData(); + } + } + } + } + currentState = networkState; + } + } + }, interval); + } + } + + /** + * 网络连接改变 + */ + public static interface ConnectiveChangedListener { + /* public void onConnectiveChange(int previousNetType, int currentNetType);*/ + + /** + * wifi 转 2G/3G/4G + */ + public void wifiChange2MobileData(); + + /** + * 有网络变为无网络 + */ + public void change2NoConnection(); + + /** + * 无网络连上wifi + */ + public void connectiveWifi(); + + /** + * 无网络连上移动数据网络 + */ + public void connectiveMobileData(); + + /** + * 移动数据网络 改为连上wifi + */ + public void mobileDataChange2Wifi(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/reciever/IncomingCallReceiver.java b/app/src/main/java/com/yizhuan/erban/reciever/IncomingCallReceiver.java new file mode 100644 index 000000000..f91810456 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/reciever/IncomingCallReceiver.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.reciever; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.telephony.TelephonyManager; + +import com.yizhuan.xchat_android_core.im.state.PhoneCallStateModel; + +/** + * Created by zhouxiangfeng on 2017/5/31. + */ + +public class IncomingCallReceiver extends BroadcastReceiver{ + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { + final String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + PhoneCallStateModel.get().callStateChanged(state); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/reciever/NotificationClickReceiver.java b/app/src/main/java/com/yizhuan/erban/reciever/NotificationClickReceiver.java new file mode 100644 index 000000000..3f7b8344d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/reciever/NotificationClickReceiver.java @@ -0,0 +1,24 @@ +package com.yizhuan.erban.reciever; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; + +/** + * Created by chenran on 2017/11/16. + */ + +public class NotificationClickReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + //todo 跳转之前要处理的逻辑 + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + AVRoomActivity.start(context, roomInfo.getUid()); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/reciever/OnePixelReceiver.java b/app/src/main/java/com/yizhuan/erban/reciever/OnePixelReceiver.java new file mode 100644 index 000000000..001c99e64 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/reciever/OnePixelReceiver.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.reciever; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.yizhuan.erban.ui.keepalive.OnePiexlActivity; + +/** + * + * @author chenran + * @date 2017/11/16 + */ + +public class OnePixelReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + + if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + //屏幕关闭启动1像素Activity + Intent it = new Intent(context, OnePiexlActivity.class); + it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(it); + } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { + //屏幕打开 结束1像素 + context.sendBroadcast(new Intent("finish")); + Intent main = new Intent(Intent.ACTION_MAIN); + main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + main.addCategory(Intent.CATEGORY_HOME); + context.startActivity(main); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/service/DaemonService.java b/app/src/main/java/com/yizhuan/erban/service/DaemonService.java new file mode 100644 index 000000000..58baa0136 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/service/DaemonService.java @@ -0,0 +1,113 @@ +package com.yizhuan.erban.service; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.IBinder; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.reciever.NotificationClickReceiver; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; + +/** + * @author chenran + * @date 2017/11/16 + */ + +public class DaemonService extends Service { + private static final String TAG = "DaemonService"; + public static final int NOTICE_ID = 100; + private static final String CHANNEL_ID = "IN_ROOM"; + private static final String CHANNEL_NAME = "在房间里面通知提示"; + private String title; + private boolean isStartForeground = false; + + public static void start(Context context, RoomInfo roomInfo) { + Intent intent = new Intent(context, DaemonService.class); + intent.putExtra("title", roomInfo.getTitle()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent); + } else { + context.startService(intent); + } + } + + public static void stop(Context context) { + Intent intent = new Intent(context, DaemonService.class); + context.stopService(intent); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + //8.0系统适配 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + createNotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); + } + + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + title = roomInfo.getTitle(); + Notification.Builder builder = new Notification.Builder(this); + builder.setSmallIcon(R.mipmap.app_logo); + builder.setContentTitle(title); + builder.setContentText("点击返回房间"); + builder.setTicker("正在房间内"); + Intent clickIntent = new Intent(this, NotificationClickReceiver.class); + PendingIntent contentIntent = PendingIntent.getBroadcast(this.getApplicationContext(), (int) System.currentTimeMillis(), clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); + builder.setContentIntent(contentIntent); + //8.0系统适配 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setChannelId(CHANNEL_ID); + } + startForeground(NOTICE_ID, builder.build()); + isStartForeground = true; + } else { + Notification.Builder builder = new Notification.Builder(this); + builder.setSmallIcon(R.mipmap.app_logo); + builder.setContentText("无房间信息"); + builder.setTicker("无房间信息"); + //8.0系统适配 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setChannelId(CHANNEL_ID); + } + startForeground(NOTICE_ID, builder.build()); + isStartForeground = true; + stopSelf(); + } + return START_NOT_STICKY; + } + + @TargetApi(Build.VERSION_CODES.O) + private void createNotificationChannel(String channelId, String channelName, int importance) { + NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + notificationManager.createNotificationChannel(channel); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (isStartForeground) { + stopForeground(true); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/share/Holder.java b/app/src/main/java/com/yizhuan/erban/share/Holder.java new file mode 100644 index 000000000..c1c447e3b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/share/Holder.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.share; + +/** + * Created by MadisonRong on 08/06/2018. + */ + +public class Holder { +} diff --git a/app/src/main/java/com/yizhuan/erban/share/viewholder/InAppSharingMsgViewHolder.java b/app/src/main/java/com/yizhuan/erban/share/viewholder/InAppSharingMsgViewHolder.java new file mode 100644 index 000000000..3c26ee9a1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/share/viewholder/InAppSharingMsgViewHolder.java @@ -0,0 +1,113 @@ +package com.yizhuan.erban.share.viewholder; + +import android.graphics.Color; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingFamilyAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingMiniWorldAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingRoomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.InAppSharingTeamAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.xchat_android_core.share.bean.InAppSharingInfo; +import com.yizhuan.xchat_android_core.share.bean.InAppSharingTeamInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; + +/** + * Created by MadisonRong on 08/06/2018. + */ + +public class InAppSharingMsgViewHolder extends MsgViewHolderBase implements View.OnClickListener { + + private View layout; + private TextView title; + private ImageView avatar; + private TextView action; + private String routerValue; + private int routerType; + + public InAppSharingMsgViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + public void onClick(View v) { + CustomAttachment attachment = (CustomAttachment) message.getAttachment(); + if (attachment.getSecond() == CustomAttachment.CUSTOM_MSG_SHARE_TEAM) { + InAppSharingTeamAttachment inAppSharingTeamAttachment = (InAppSharingTeamAttachment) attachment; + InAppSharingTeamInfo inAppSharingTeamInfo = inAppSharingTeamAttachment.getInfo(); + TeamInfo info = inAppSharingTeamInfo.getInfo(); + if (info == null) { + return; + } + // 分享群组时,点击动作打开家族客态页 + RouterHandler.handle(context, RouterType.FAMILY, info.getFamilyId()); + } else { + RouterHandler.handle(context, routerType, routerValue); + } + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_in_app_sharing; + } + + @Override + protected void inflateContentView() { + layout = findViewById(R.id.ll_in_app_sharing_msg_view_holder); + title = findViewById(R.id.tv_title); + avatar = findViewById(R.id.iv_avatar); + action = findViewById(R.id.tv_action); + } + + @Override + protected void bindContentView() { + CustomAttachment customAttachment = (CustomAttachment) message.getAttachment(); + InAppSharingInfo inAppSharingInfo; + switch (customAttachment.getSecond()) { + default: + case CustomAttachment.CUSTOM_MSG_SHARE_ROOM: + InAppSharingRoomAttachment roomAttachment = (InAppSharingRoomAttachment) customAttachment; + inAppSharingInfo = roomAttachment.getInfo(); + break; + + case CustomAttachment.CUSTOM_MSG_SHARE_FAMILY: + InAppSharingFamilyAttachment familyAttachment = (InAppSharingFamilyAttachment) customAttachment; + inAppSharingInfo = familyAttachment.getInfo(); + break; + + case CustomAttachment.CUSTOM_MSG_SHARE_TEAM: + InAppSharingTeamAttachment teamAttachment = (InAppSharingTeamAttachment) customAttachment; + inAppSharingInfo = teamAttachment.getInfo(); + break; + + case CustomAttachment.CUSTOM_MSG_SHARE_MINI_WORLD: + InAppSharingMiniWorldAttachment miniWorldAttachment = (InAppSharingMiniWorldAttachment) customAttachment; + inAppSharingInfo = miniWorldAttachment.getInfo(); + break; + } + if (inAppSharingInfo != null) { + if (isReceivedMessage()) { + title.setTextColor(Color.BLACK); + action.setTextColor(Color.BLACK); + } else { + title.setTextColor(Color.WHITE); + action.setTextColor(Color.WHITE); + } + title.setText(inAppSharingInfo.getTitle()); + ImageLoadUtils.loadRectImage(context, inAppSharingInfo.getAvatar(), avatar, + R.drawable.default_avatar, 5); + action.setText(inAppSharingInfo.getActionName()); + routerType = inAppSharingInfo.getRouterType(); + routerValue = inAppSharingInfo.getRouterValue(); + layout.setOnClickListener(this); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/sys/ErbanSysMsgViewModel.java b/app/src/main/java/com/yizhuan/erban/sys/ErbanSysMsgViewModel.java new file mode 100644 index 000000000..a6b89766b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/sys/ErbanSysMsgViewModel.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.sys; + +import com.yizhuan.xchat_android_library.net.rxnet.RxNet; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.msg.sys.ApproveMsgInfo; +import com.yizhuan.xchat_android_core.msg.sys.ErbanSysMsgModel; + +import java.util.Map; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 03/07/2018. + */ + +public class ErbanSysMsgViewModel { + + private ErbanSysMsgModel.Api api = RxNet.create(ErbanSysMsgModel.Api.class); + + public Single requestUrl(String url, int type, Map params) { + String uid = String.valueOf(AuthModel.get().getCurrentUid()); + return api.requestUrl(url, type, uid, params) + .compose(RxHelper.handleBeanData()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/adapter/AddTeamMemberAdapter.java b/app/src/main/java/com/yizhuan/erban/team/adapter/AddTeamMemberAdapter.java new file mode 100644 index 000000000..252a87dec --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/adapter/AddTeamMemberAdapter.java @@ -0,0 +1,62 @@ +package com.yizhuan.erban.team.adapter; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; + +/** + * Created by MadisonRong on 29/05/2018. + */ + +public class AddTeamMemberAdapter extends BaseAdapter { + + protected Context context; + + public AddTeamMemberAdapter(Context context) { + this(R.layout.item_add_team_member, BR.memberInfo, context); + } + + public AddTeamMemberAdapter(int layoutResId, int brid, Context context) { + super(layoutResId, brid); + this.context = context; + } + + @Override + protected void convert(BindingViewHolder helper, FamilyMemberInfo item) { + super.convert(helper, item); +// helper.getBinding().setVariable(BR.memberInfo, item); + TextView tvMemberAdd = helper.getView(R.id.tv_member_add); + tvMemberAdd.setSelected(item.isSelect()); + helper.getView(R.id.ll_member_layout).setOnClickListener(v -> { + if (onCheckedChangeListener != null) { + if (item.isSelect()) { + onCheckedChangeListener.onUnSelect(item); + }else { + onCheckedChangeListener.onSelect(item); + } + } + }); + + if (this.mData.indexOf(item) == this.mData.size() - 1) { + helper.getView(R.id.diver).setVisibility(View.GONE); + } + } + + private OnCheckedChangeListener onCheckedChangeListener; + + public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) { + this.onCheckedChangeListener = onCheckedChangeListener; + } + + public interface OnCheckedChangeListener { + void onSelect(FamilyMemberInfo familyMemberInfo); + + void onUnSelect(FamilyMemberInfo familyMemberInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/adapter/TeamListAdapter.java b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamListAdapter.java new file mode 100644 index 000000000..04a58ed38 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamListAdapter.java @@ -0,0 +1,48 @@ +package com.yizhuan.erban.team.adapter; + +import android.content.Context; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; + +/** + * Created by MadisonRong on 11/06/2018. + */ + +public class TeamListAdapter extends BaseAdapter { + + private int type = AbstractSelectFriendAction.TYPE_NORMAL; + private Context context; + + public TeamListAdapter(Context context) { + this(R.layout.item_team_list, BR.teamInfo, context); + } + + public TeamListAdapter(int layoutResId, int brid, Context context) { + super(layoutResId, brid); + this.context = context; + } + + public void setType(int type) { + this.type = type; + } + + @Override + protected void convert(BindingViewHolder helper, TeamInfo item) { + super.convert(helper, item); + ImageView avatar = helper.getView(R.id.iv_avatar); + TextView teamName = helper.getView(R.id.tv_team_name); + + helper.addOnClickListener(R.id.ll_container); + ImageLoadUtils.loadAvatar(context, item.getIcon(), avatar, true); + teamName.setText(item.getName()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/adapter/TeamMemberListAdapter.java b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamMemberListAdapter.java new file mode 100644 index 000000000..e8a59ea5b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamMemberListAdapter.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.team.adapter; + +import android.content.Context; +import android.databinding.ViewDataBinding; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.common.ui.imageview.HeadImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.team.view.TeamMemberListActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; + +/** + * Created by MadisonRong on 30/05/2018. + */ + +public class TeamMemberListAdapter extends BaseAdapter { + + private Context context; + private int type; + + public TeamMemberListAdapter(Context context, int type) { + this(R.layout.item_team_member_list, BR.memberInfo, context, type); + } + + public TeamMemberListAdapter(int layoutResId, int brid, Context context, int type) { + super(layoutResId, brid); + this.context = context; + this.type = type; + } + + @Override + protected void convert(BindingViewHolder helper, TeamMemberInfo item) { + ViewDataBinding binding = helper.getBinding(); + + HeadImageView ivAvatar = helper.getView(R.id.iv_avatar); + ImageView officePosition = helper.getView(R.id.iv_user_office_position); + TextView tvName = helper.getView(R.id.tv_name); + TextView tvErbanId = helper.getView(R.id.tv_erban_id); + TextView tvMemberRemove = helper.getView(R.id.tv_member_remove); + + + GlideApp.with(context) + .load(TextUtils.isEmpty(item.getAvatar()) ? R.drawable.default_avatar : item.getAvatar()) + .placeholder(R.drawable.default_avatar) + .error(R.drawable.default_avatar) + .into(ivAvatar); + + tvName.setText(item.getNick()); + tvErbanId.setText(context.getString(R.string.family_member_erban_id, String.valueOf(item.getErbanNo()))); + ImageButton button = helper.getView(R.id.btn_member_operation); + + UserLevelVo userLevelVo = item.getUserLevelVo(); + ImageView ivUserLevel = helper.getView(R.id.iv_user_level); + ImageView ivUserCharm = helper.getView(R.id.iv_user_charm); + ivUserLevel.setVisibility(userLevelVo == null ? View.GONE : View.VISIBLE); + ivUserLevel.setVisibility(userLevelVo == null ? View.GONE : View.VISIBLE); + if (userLevelVo != null) { + ivUserLevel.setVisibility(TextUtils.isEmpty(userLevelVo.getExperUrl()) ? View.GONE : View.VISIBLE); + if (!TextUtils.isEmpty(userLevelVo.getExperUrl())) { + ImageLoadUtils.loadImage(mContext, userLevelVo.getExperUrl(), ivUserLevel); + } + ivUserCharm.setVisibility(TextUtils.isEmpty(userLevelVo.getCharmUrl()) ? View.GONE : View.VISIBLE); + if (!TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + ivUserCharm.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, userLevelVo.getCharmUrl(), ivUserCharm); + } + } + +// if (item.getUid() == AuthModel.get().getCurrentUid()) { +// button.setVisibility(View.GONE); +// } else { +// button.setVisibility(View.VISIBLE); +// } +// int role = TeamModel.get().getTeamInfoCache(item.getTid()).getRole(); + switch (item.getRole()) { + case TeamMemberInfo.ROLE_TEAM_OWNER: + officePosition.setVisibility(View.VISIBLE); + officePosition.setImageResource(R.drawable.icon_family_office_position_boss); + button.setVisibility(View.GONE); + break; + + case TeamMemberInfo.ROLE_TEAM_MANAGER: + officePosition.setVisibility(View.VISIBLE); + officePosition.setImageResource(R.drawable.icon_family_office_position_manager); + button.setVisibility(item.getUid() == AuthModel.get().getCurrentUid() ? + View.GONE : View.VISIBLE); + break; + + case TeamMemberInfo.ROLE_TEAM_MEMBER: + officePosition.setVisibility(View.GONE); + button.setVisibility(item.getUid() == AuthModel.get().getCurrentUid() ? + View.GONE : View.VISIBLE); + break; + } + + switch (type) { + default: + case TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL: + button.setVisibility(View.GONE); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_REMOVE: + button.setImageResource(R.drawable.ic_family_remove_person); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MANAGEMENT: + if (item.getRole() == TeamMemberInfo.ROLE_TEAM_MANAGER) { + button.setImageResource(R.drawable.ic_family_remove_manager); + } else { + button.setImageResource(R.drawable.ic_family_add_manager); + } + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MUTE: + if (item.isDisable()) { + button.setImageResource(R.drawable.ic_family_remove_mute); + + } else { + button.setImageResource(R.drawable.ic_family_add_mute); + } + break; + } + + if (this.mData != null && this.mData.size() > 0 && + this.mData.indexOf(item) == this.mData.size() - 1) { + helper.getView(R.id.diver).setVisibility(View.GONE); + } + + button.setOnClickListener(v -> onOperationButtonClickedListener.onOperationButtonClicked(helper.getAdapterPosition(), item, type)); + } + + private OnOperationButtonClickedListener onOperationButtonClickedListener; + + public void setOnOperationButtonClickedListener(OnOperationButtonClickedListener onOperationButtonClickedListener) { + this.onOperationButtonClickedListener = onOperationButtonClickedListener; + } + + public interface OnOperationButtonClickedListener { + void onOperationButtonClicked(int position, TeamMemberInfo teamMemberInfo, int type); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/adapter/TeamWeeklyBillAdapter.java b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamWeeklyBillAdapter.java new file mode 100644 index 000000000..6bf3ae482 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/adapter/TeamWeeklyBillAdapter.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.team.adapter; + +import android.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.erban.ui.widget.UserInfoDialog; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.team.bean.TeamTransactionRecordInfo; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by MadisonRong on 31/05/2018. + */ + +public class TeamWeeklyBillAdapter extends BaseAdapter { + + private Context context; + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM月dd日 HH:mm:ss"); + + public TeamWeeklyBillAdapter(Context context) { + this(R.layout.item_team_weekly_bill_transcation_record, BR.transactionRecordInfo, context); + } + + public TeamWeeklyBillAdapter(int layoutResId, int brid, Context context) { + super(layoutResId, brid); + this.context = context; + } + + @Override + protected void convert(BindingViewHolder helper, TeamTransactionRecordInfo item) { + if (null == item) return; + + CircleImageView civImg = helper.getView(R.id.civ_img); + TextView tvNick = helper.getView(R.id.tv_nick); + TextView tvFrom = helper.getView(R.id.tv_from); + TextView tvData = helper.getView(R.id.tv_data); + TextView tvTime = helper.getView(R.id.tv_time); + + + GlideApp.with(context) + .load(item.getAvatar()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(civImg); + + civImg.setOnClickListener(v -> { + UserInfoDialog userInfoDialog = new UserInfoDialog(context, item.getUid()); + userInfoDialog.show(); + }); + + tvNick.setText(item.getNick()); + tvFrom.setText(item.getSource()); + tvData.setText(FormatUtils.formatToShortDown(item.getAmount()) + FamilyModel.Instance().getMyFamily().getMoneyName()); + tvTime.setText(simpleDateFormat.format(new Date(item.getTime()))); + + if (this.mData != null && this.mData.size() > 0 && + this.mData.indexOf(item) == this.mData.size() - 1) { + helper.getView(R.id.diver).setVisibility(View.GONE); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/bean/NimTeamMember.java b/app/src/main/java/com/yizhuan/erban/team/bean/NimTeamMember.java new file mode 100644 index 000000000..1c15e999f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/bean/NimTeamMember.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.team.bean; + +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.TeamMember; + +import java.util.Map; + +/** + * 为了实现自定义@人的界面而产生的中间数据结构,里面的数据不一定准确 + * Created by MadisonRong on 31/05/2018. + */ + +public class NimTeamMember implements TeamMember { + + private String tid; + private String account; + private TeamMemberType type; + private String teamNick; + private boolean isInTeam; + + public void setTid(String tid) { + this.tid = tid; + } + + public void setAccount(String account) { + this.account = account; + } + + public void setType(TeamMemberType type) { + this.type = type; + } + + public void setTeamNick(String teamNick) { + this.teamNick = teamNick; + } + + public void setInTeam(boolean inTeam) { + isInTeam = inTeam; + } + + @Override + public String getTid() { + return tid; + } + + @Override + public String getAccount() { + return account; + } + + @Override + public TeamMemberType getType() { + return type; + } + + @Override + public String getTeamNick() { + return teamNick; + } + + @Override + public boolean isInTeam() { + return isInTeam; + } + + @Override + public Map getExtension() { + return null; + } + + @Override + public boolean isMute() { + return false; + } + + @Override + public long getJoinTime() { + return 0; + } + + @Override + public String getInvitorAccid() { + return ""; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/dialog/QuitTeamDialog.java b/app/src/main/java/com/yizhuan/erban/team/dialog/QuitTeamDialog.java new file mode 100644 index 000000000..f791e3ff9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/dialog/QuitTeamDialog.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.team.dialog; + +import android.support.v7.app.AppCompatDialogFragment; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +/** + * Created by MadisonRong on 29/05/2018. + */ +@ActLayoutRes(R.layout.dialog_quit_team) +public class QuitTeamDialog extends AppCompatDialogFragment { + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/event/TeamMemberUpdateEvent.java b/app/src/main/java/com/yizhuan/erban/team/event/TeamMemberUpdateEvent.java new file mode 100644 index 000000000..436f376c4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/event/TeamMemberUpdateEvent.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.team.event; + +/** + * @author jack + * @Description + * @Date 2018/7/26 + */ + +public class TeamMemberUpdateEvent { + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/AddMemberActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/AddMemberActivity.java new file mode 100644 index 000000000..59c2bff61 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/AddMemberActivity.java @@ -0,0 +1,260 @@ +package com.yizhuan.erban.team.view; + +import android.app.Activity; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityAddTeamMemberBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.AddTeamMemberAdapter; +import com.yizhuan.erban.team.viewmodel.FamilyMemberViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * 查询出家族里所有成员的人,从中筛选 + * Created by MadisonRong on 29/05/2018. + */ +@ActLayoutRes(R.layout.activity_add_team_member) +public class AddMemberActivity extends BaseBindingActivity + implements AddTeamMemberAdapter.OnCheckedChangeListener { + + public static final int FIRST_PAGE = 1; + public static final int REQUEST_CODE_SELECT_MEMBER = 100; + public static final String EXTRA_TEAM_ID = "EXTRA_TEAM_ID"; + public static final String EXTRA_SELECTED_MEMBER = "EXTRA_SELECTED_MEMBER"; + + private FamilyMemberViewModel familyMemberViewModel; + private AddTeamMemberAdapter addTeamMemberAdapter; + private String teamId; + private int page = FIRST_PAGE; + private ArrayList selectMembers = new ArrayList<>(); + + public static void start(Activity activity) { + Intent intent = new Intent(activity, AddMemberActivity.class); + activity.startActivityForResult(intent, REQUEST_CODE_SELECT_MEMBER); + } + + + public static void start(Activity activity,ArrayList memberInfoList) { + Intent intent = new Intent(activity, AddMemberActivity.class); + intent.putExtra(EXTRA_SELECTED_MEMBER, memberInfoList); + activity.startActivityForResult(intent, REQUEST_CODE_SELECT_MEMBER); + } + + public static void start(Activity activity, String tid) { + Intent intent = new Intent(activity, AddMemberActivity.class); + intent.putExtra(EXTRA_TEAM_ID, tid); + activity.startActivityForResult(intent, REQUEST_CODE_SELECT_MEMBER); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.family_member_list)); + + if (getIntent() != null) { + teamId = getIntent().getStringExtra(EXTRA_TEAM_ID); + ArrayList serializableExtra = (ArrayList) getIntent().getSerializableExtra(EXTRA_SELECTED_MEMBER); + if (serializableExtra != null) { + selectMembers = serializableExtra; + } + } + + familyMemberViewModel = new FamilyMemberViewModel(); + addTeamMemberAdapter = new AddTeamMemberAdapter(this); + mBinding.rvMember.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + mBinding.rvMember.setAdapter(addTeamMemberAdapter); + + addTeamMemberAdapter.setOnCheckedChangeListener(this); + mBinding.setClick(this); + showLoading(); + + mBinding.srlMemberList.setEnableLoadmore(true); + mBinding.srlMemberList.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { + @Override + public void onLoadmore(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(AddMemberActivity.this)) { + mBinding.srlMemberList.finishLoadmore(); + return; + } + List data = addTeamMemberAdapter.getData(); + if (ListUtils.isListEmpty(data)) { + mBinding.srlMemberList.finishLoadmore(); + return; + } + loadData(); + } + + @Override + public void onRefresh(RefreshLayout refreshLayout) { + if (!NetworkUtil.isNetAvailable(AddMemberActivity.this)) { + mBinding.srlMemberList.finishRefresh(); + return; + } + firstLoad(); + } + }); + } + + private void firstLoad() { + page = FIRST_PAGE; + loadData(); + } + + private void loadData() { + familyMemberViewModel.getNotInTeamFamilyMembers(teamId, null, page) + .compose(bindToLifecycle()) + .subscribe((respFamilymember, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + finishLoadingData(); + } else { + mBinding.tvMemberCount.setText(getString(R.string.family_member_label2, + String.valueOf(respFamilymember.getCount()))); + List teamMemberInfos = respFamilymember.getMembers(); + if (!ListUtils.isListEmpty(teamMemberInfos)) { + Iterator iterator = teamMemberInfos.iterator(); + while (iterator.hasNext()){ + FamilyMemberInfo teamMemberInfo = iterator.next(); + if (teamMemberInfo.getUid() == AuthModel.get().getCurrentUid()) { + iterator.remove(); + } + if (isMemberInSelect(teamMemberInfo)){ + teamMemberInfo.setSelect(true); + } + } + hideStatus(); + if (page == FIRST_PAGE) { + addTeamMemberAdapter.setNewData(teamMemberInfos); + mBinding.srlMemberList.finishRefresh(); + } else { + addTeamMemberAdapter.addData(teamMemberInfos); + mBinding.srlMemberList.finishLoadmore(); + } + } else { + finishLoadingData(); + } + page++; + } + }); + } + + private void finishLoadingData() { + if (page == FIRST_PAGE) { + showNoData("家族内所有成员都已经在群里了哦"); + mBinding.srlMemberList.finishRefresh(); + } else { + mBinding.srlMemberList.finishLoadmore(); + } + } + + private boolean isMemberInSelect(FamilyMemberInfo familyMemberInfo){ + boolean isContain = false; + if (selectMembers != null) { + for (FamilyMemberInfo selectMember : selectMembers) { + if (selectMember.getUid() == familyMemberInfo.getUid()){ + isContain = true; + break; + } + } + } + return isContain; + } + + @Override + protected void onResume() { + super.onResume(); + firstLoad(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_CODE_SELECT_MEMBER) { + ArrayList searchMembers = + (ArrayList) data.getSerializableExtra(AddMemberSearchActivity.EXTRA_SEARCH_MEMBER); + for (FamilyMemberInfo searchMember : searchMembers) { + if (searchMember.isSelect()){ + onSelect(searchMember); + }else { + onUnSelect(searchMember); + } + } + + } + + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_search: + AddMemberSearchActivity.start(this, teamId, selectMembers); + break; + + case R.id.btn_confirm: + Intent intent = new Intent(); + intent.putExtra(EXTRA_SELECTED_MEMBER, selectMembers); + setResult(RESULT_OK, intent); + finish(); + break; + } + } + + + @Override + public void onSelect(FamilyMemberInfo familyMemberInfo) { + if (!isMemberInSelect(familyMemberInfo)) { + if (selectMembers != null) { + selectMembers.add(familyMemberInfo); + for (int i = 0; i < addTeamMemberAdapter.getData().size(); i++) { + if (addTeamMemberAdapter.getData().get(i).getUid() == familyMemberInfo.getUid()){ + addTeamMemberAdapter.getData().get(i).setSelect(true); + addTeamMemberAdapter.notifyDataSetChanged(); + break; + } + + } + } + } + + } + + @Override + public void onUnSelect(FamilyMemberInfo familyMemberInfo) { + boolean isRemove = false; + if (selectMembers != null) { + for (int i = 0; i < selectMembers.size(); i++) { + if (selectMembers.get(i).getUid() == familyMemberInfo.getUid()){ + selectMembers.remove(i); + isRemove = true; + break; + } + } + } + if (isRemove){ + for (int i = 0; i < addTeamMemberAdapter.getData().size(); i++) { + if (addTeamMemberAdapter.getData().get(i).getUid() == familyMemberInfo.getUid()){ + addTeamMemberAdapter.getData().get(i).setSelect(false); + addTeamMemberAdapter.notifyDataSetChanged(); + break; + } + + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/AddMemberSearchActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/AddMemberSearchActivity.java new file mode 100644 index 000000000..402b1f3b8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/AddMemberSearchActivity.java @@ -0,0 +1,220 @@ +package com.yizhuan.erban.team.view; + +import android.app.Activity; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityAddTeamMemberSearchListBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.AddTeamMemberAdapter; +import com.yizhuan.erban.team.viewmodel.FamilyMemberViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by MadisonRong on 31/05/2018. + */ +@ActLayoutRes(R.layout.activity_add_team_member_search_list) +public class AddMemberSearchActivity extends BaseBindingActivity + implements AddTeamMemberAdapter.OnCheckedChangeListener { + + public static final String EXTRA_TEAM_ID = "EXTRA_TEAM_ID"; + public static final String EXTRA_TEAM_SELECT_MEMBERS = "EXTRA_TEAM_SELECT_MEMBERS"; + public static final String EXTRA_SEARCH_MEMBER = "EXTRA_SEARCH_MEMBER"; + + private FamilyMemberViewModel familyMemberViewModel; + private AddTeamMemberAdapter addTeamMemberAdapter; + private String teamId; + private ArrayList selectMembers = new ArrayList<>(); + + public static void start(Activity context, String tid, ArrayList selectMembers) { + Intent intent = new Intent(context, AddMemberSearchActivity.class); + intent.putExtra(EXTRA_TEAM_ID, tid); + intent.putExtra(EXTRA_TEAM_SELECT_MEMBERS, selectMembers); + context.startActivityForResult(intent, AddMemberActivity.REQUEST_CODE_SELECT_MEMBER); + } + + @Override + protected void init() { + + if (getIntent() != null) { + teamId = getIntent().getStringExtra(EXTRA_TEAM_ID); + ArrayList serializableExtra = (ArrayList) getIntent().getSerializableExtra(EXTRA_TEAM_SELECT_MEMBERS); + if (serializableExtra != null) { + selectMembers = serializableExtra; + } + } + + familyMemberViewModel = new FamilyMemberViewModel(); + addTeamMemberAdapter = new AddTeamMemberAdapter(this); + mBinding.rvMember.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + mBinding.rvMember.setAdapter(addTeamMemberAdapter); + + mBinding.searchEdit.addTextChangedListener(textWatcher); + mBinding.searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + mBinding.searchEdit.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + String str = v.getText().toString(); + if (!searchMemberList(str)) return false; + hideIME(); + return true; + } + return false; + + }); + + mBinding.ivClearText.setVisibility(View.GONE); + + addTeamMemberAdapter.setOnCheckedChangeListener(this); + mBinding.setClick(this); + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + mBinding.ivClearText.setVisibility(View.GONE); + } else { + mBinding.ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + private boolean searchMemberList(String str) { + if (TextUtils.isEmpty(str)) { +// Toast.makeText(this, "请输入搜索内容!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return true; + } + familyMemberViewModel.getNotInTeamFamilyMembers(teamId, mBinding.searchEdit.getText().toString(), 0) + .compose(bindToLifecycle()) + .subscribe((respFamilymember, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + List familyMemberInfos = respFamilymember.getMembers(); + if (!ListUtils.isListEmpty(familyMemberInfos)) { + Iterator iterator = familyMemberInfos.iterator(); + while (iterator.hasNext()) { + FamilyMemberInfo teamMemberInfo = iterator.next(); + if (teamMemberInfo.getUid() == AuthModel.get().getCurrentUid()) { + iterator.remove(); + } + if (isMemberInSelect(teamMemberInfo)) { + teamMemberInfo.setSelect(true); + } + } + hideStatus(); + addTeamMemberAdapter.setNewData(familyMemberInfos); + addTeamMemberAdapter.notifyDataSetChanged(); + } else { + showNoData(); + } + } + }); + return false; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + + case R.id.tv_search: + String str = mBinding.searchEdit.getText().toString(); + if (searchMemberList(str)) return; + hideIME(); + break; + + case R.id.iv_clear_text: + mBinding.searchEdit.setText(""); + break; + + case R.id.btn_confirm: + Intent intent = new Intent(); + ArrayList searchMemberList = new ArrayList<>(addTeamMemberAdapter.getData()); + intent.putExtra(EXTRA_SEARCH_MEMBER, searchMemberList); + setResult(RESULT_OK, intent); + finish(); + break; + } + } + + @Override + public void onSelect(FamilyMemberInfo familyMemberInfo) { + if (!isMemberInSelect(familyMemberInfo)) { + if (selectMembers != null) { + selectMembers.add(familyMemberInfo); + for (int i = 0; i < addTeamMemberAdapter.getData().size(); i++) { + if (addTeamMemberAdapter.getData().get(i).getUid() == familyMemberInfo.getUid()) { + addTeamMemberAdapter.getData().get(i).setSelect(true); + addTeamMemberAdapter.notifyDataSetChanged(); + break; + } + + } + } + } + } + + @Override + public void onUnSelect(FamilyMemberInfo familyMemberInfo) { + boolean isRemove = false; + if (selectMembers != null) { + for (int i = 0; i < selectMembers.size(); i++) { + if (selectMembers.get(i).getUid() == familyMemberInfo.getUid()) { + selectMembers.remove(i); + isRemove = true; + break; + } + } + } + if (isRemove) { + for (int i = 0; i < addTeamMemberAdapter.getData().size(); i++) { + if (addTeamMemberAdapter.getData().get(i).getUid() == familyMemberInfo.getUid()) { + addTeamMemberAdapter.getData().get(i).setSelect(false); + addTeamMemberAdapter.notifyDataSetChanged(); + break; + } + + } + } + } + + private boolean isMemberInSelect(FamilyMemberInfo familyMemberInfo) { + boolean isContain = false; + for (FamilyMemberInfo selectMember : selectMembers) { + if (selectMember.getUid() == familyMemberInfo.getUid()) { + isContain = true; + break; + } + } + return isContain; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/CreateTeamMessageActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/CreateTeamMessageActivity.java new file mode 100644 index 000000000..699262fda --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/CreateTeamMessageActivity.java @@ -0,0 +1,195 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingTakePhotoActivity; +import com.yizhuan.erban.databinding.ActivityCreateTeamMessageBinding; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; + +import java.util.ArrayList; +import java.util.Objects; + +/** + * Created by MadisonRong on 28/05/2018. + */ +@ActLayoutRes(R.layout.activity_create_team_message) +public class CreateTeamMessageActivity extends BaseBindingTakePhotoActivity + implements BaseBindingTakePhotoActivity.OnUploadListener { + + private static final String TAG = "CreateTeamMessageActivi"; + + private TeamViewModel teamViewModel; + private String url = "https://img.erbanyy.com/default_group_avatar.png"; + private ArrayList members = new ArrayList<>(); + + public static void start(Context context) { + context.startActivity(new Intent(context, CreateTeamMessageActivity.class)); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.title_create_team)); + + teamViewModel = new TeamViewModel(); + + mBinding.etTeamName.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + // 有输入,则按钮变成可按状态 + if (!Objects.equals(s.toString(), "")) { + if (s.toString().length() <= 15) { + mBinding.btnCreateTeam.setEnabled(true); + } else { + toast("最多15字"); + } + } else { + mBinding.btnCreateTeam.setEnabled(false); + } + } + }); + mBinding.setClick(this); + mBinding.switchAuthMethod.setOn(true,false); + setOnUploadListener(this); + + GlideApp.with(this) + .load(url) + .dontAnimate() + .into(mBinding.ivTeamIcon); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + switch (requestCode) { + case AddMemberActivity.REQUEST_CODE_SELECT_MEMBER: + ArrayList listExtra = (ArrayList) + data.getSerializableExtra(AddMemberActivity.EXTRA_SELECTED_MEMBER); + if (listExtra != null) { + Log.e(TAG, "onActivityResult: " + listExtra); + members = listExtra; + showSelectMemberView(members); + } + break; + } + } + } + + private void showSelectMemberView(ArrayList members) { + ImageView[] avatars = new ImageView[]{mBinding.ivSelectMember1, + mBinding.ivSelectMember2, mBinding.ivSelectMember3, + mBinding.ivSelectMember4, mBinding.ivSelectMember5, mBinding.ivSelectMember6}; + for (int i = 0; i < avatars.length; i++) { + avatars[i].setVisibility(View.GONE); + } + mBinding.tvSelectMember.setVisibility(View.GONE); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < members.size(); i++) { + if (i < avatars.length){ + avatars[i].setVisibility(View.VISIBLE); + GlideApp.with(this) + .load(members.get(i).getIcon()) + .dontAnimate() + .into(avatars[i]); + }else { + sb.append(" "); + break; + } + } + if (members.size() > 0){ + mBinding.tvSelectMember.setVisibility(View.VISIBLE); + mBinding.tvSelectMember.setText(sb.append("共").append(members.size()).append("人").toString()); + } + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_create_team: + mBinding.btnCreateTeam.setEnabled(false); + KeyBoardUtils.hideKeyBoard(this, mBinding.etTeamName); + // 输入内容为空格,不允许提交 + if (!Objects.equals(mBinding.etTeamName.getText().toString().trim(), "")) { + String[] teamMembers = new String[members.size()]; + for (int i = 0; i < members.size() ; i++) { + teamMembers[i] = String.valueOf(members.get(i).getUid()); + } + boolean isVerify = mBinding.switchAuthMethod.isOn(); + teamViewModel.createTeam( + FamilyModel.Instance().getMyFamily().getFamilyId(), + String.valueOf(AuthModel.get().getCurrentUid()), + url, + mBinding.etTeamName.getText().toString(), + isVerify, + teamMembers) + .compose(bindToLifecycle() + ) + .subscribe((serviceResult, throwable) -> { + mBinding.btnCreateTeam.setEnabled(true); + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } else { + FamilyModel.Instance().syncMyFamilyFromServer().subscribe(); + toast("创建成功"); + finish(); + } + }); + } else { + mBinding.btnCreateTeam.setEnabled(true); + toast("请输入内容"); + } + break; + + case R.id.rl_upload_team_icon: + showTakePhotoOperationDialog(); + break; + + case R.id.rl_select_member: + AddMemberActivity.start(this, members); + break; + + case R.id.rl_switch_auth_method: + mBinding.switchAuthMethod.performClick(); + break; + + case R.id.switch_auth_method: + mBinding.switchAuthMethod.setOn(!mBinding.switchAuthMethod.isOn(), true); + break; + } + } + + @Override + public void onUploadSuccess(String url) { + this.url = url; + GlideApp.with(this) + .load(url) + .dontAnimate() + .into(mBinding.ivTeamIcon); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/NimTeamManagementActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamManagementActivity.java new file mode 100644 index 000000000..0d5dd634d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamManagementActivity.java @@ -0,0 +1,421 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.view.View; + +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingTakePhotoActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityTeamManagementBinding; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.share.bean.SessionType; +import com.yizhuan.xchat_android_core.team.bean.TeamEvent; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; + +import java.util.ArrayList; +import java.util.List; + +import cn.sharesdk.framework.Platform; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * Created by MadisonRong on 29/05/2018. + */ +@ActLayoutRes(R.layout.activity_team_management) +public class NimTeamManagementActivity extends BaseBindingTakePhotoActivity + implements ShareDialog.OnShareDialogItemClick, BaseBindingTakePhotoActivity.OnUploadListener { + + private static final String TAG = "NimTeamManagementActivi"; + + public static final String EXTRA_TEAM_ID = "EXTRA_TEAM_ID"; + + private String teamId; + private TeamViewModel teamViewModel; + private ShareDialog shareDialog; + private TeamInfo teamInfo; + + public static void start(Context context, String teamId) { + Intent intent = new Intent(context, NimTeamManagementActivity.class); + intent.putExtra(EXTRA_TEAM_ID, teamId); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.text_team_info_title)); + mBinding.setClick(this); + setOnUploadListener(this); + teamViewModel = new TeamViewModel(); + if (getIntent() != null) { + teamId = getIntent().getStringExtra(EXTRA_TEAM_ID); + } + mBinding.titleBar.addAction(new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_share; + } + + @Override + public void performAction(View view) { + shareDialog = new ShareDialog(NimTeamManagementActivity.this); + shareDialog.setOnShareDialogItemClick(NimTeamManagementActivity.this); + shareDialog.show(); + } + }); + + mBinding.switchMessageNotifyType.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + mBinding.switchMessageNotifyType.setEnabled(false); + if (teamInfo == null) return; + boolean muteState = teamInfo.isPromt(); + teamViewModel.muteNotification(teamInfo.getId(), String.valueOf(AuthModel.get().getCurrentUid()), isOn) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + mBinding.switchMessageNotifyType.setEnabled(true); + if (throwable != null) { + throwable.printStackTrace(); + toast("操作失败"); + mBinding.switchMessageNotifyType.setOn(muteState,true,false); + } else { + // update cache + teamInfo.setPromt(isOn); + TeamModel.get().setTeamInfoCache(teamInfo.getTid(), teamInfo); + } + }); + } + }); + + mBinding.switchJoinAuth.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + mBinding.switchJoinAuth.setEnabled(false); + boolean on = TeamModel.get().getCurrentTeamInfo().isVerify(); + teamViewModel.updateTeamJoinAuthMethod(teamInfo.getId(), isOn) + .compose(bindToLifecycle()) + .subscribe((teamInfo, throwable) -> { + mBinding.switchJoinAuth.setEnabled(true); + if (throwable != null) { + throwable.printStackTrace(); + toast("更新加入方式失败"); + mBinding.switchJoinAuth.setOn(on,true,false); + } else { + NimTeamManagementActivity.this.teamInfo.setVerify(teamInfo.isVerify()); + TeamModel.get().setTeamInfoCache(teamInfo.getTid(), teamInfo); + // 显示身份验证方式的 text + mBinding.tvTeamAuth.setText(teamInfo.isVerify() ? getString(R.string.text_team_join_auth_on) + : getString(R.string.text_team_join_auth_off)); + } + }); + } + }); + + } + + + @Override + protected void onResume() { + super.onResume(); + teamInfo = TeamModel.get().getTeamInfoCache(teamId); + if (teamInfo == null) { + teamViewModel.getTeamInfo(teamId) + .subscribe((teamInfo, throwable) -> { + if (throwable != null){ + toast(throwable.getMessage()); + finish(); + return; + } + if (teamInfo != null) { + TeamModel.get().setTeamInfoCache(teamId, teamInfo); + mBinding.setTeamInfo(teamInfo); + this.teamInfo = teamInfo; + // 显示身份验证方式的 text + mBinding.tvTeamAuth.setText(teamInfo.isVerify() ? getString(R.string.text_team_join_auth_on) + : getString(R.string.text_team_join_auth_off)); + //根据角色显示相关界面 + showViewByRole(teamInfo.getRole()); + } + }); + } else { + mBinding.setTeamInfo(teamInfo); + // 显示身份验证方式的 text + mBinding.tvTeamAuth.setText(teamInfo.isVerify() ? getString(R.string.text_team_join_auth_on) + : getString(R.string.text_team_join_auth_off)); + //根据角色显示相关界面 + showViewByRole(teamInfo.getRole()); + } + } + + + + private void showViewByRole(int role){ + // 根据用户的权限显示「退出群」text 还是 「删除群」text + switch (role) { + case TeamMemberInfo.ROLE_TEAM_OWNER: + mBinding.btnOperation.setText(R.string.btn_text_delete_team); + mBinding.rlTeamJoinAuth.setVisibility(View.VISIBLE); + requestFamilyInfo(); + break; + + case TeamMemberInfo.ROLE_TEAM_MANAGER: + mBinding.btnOperation.setText(R.string.btn_text_quit_team); + mBinding.rlTeamMuteMember.setVisibility(View.GONE); + mBinding.vDiv2.setVisibility(View.GONE); + mBinding.rlSetTeamManagers.setVisibility(View.GONE); + mBinding.vDiv3.setVisibility(View.GONE); + mBinding.rlTeamJoinAuth.setVisibility(View.GONE); + mBinding.vDiv4.setVisibility(View.GONE); + mBinding.rlGroupStatistics.setVisibility(View.GONE); + mBinding.vDiv5.setVisibility(View.GONE); + break; + + case TeamMemberInfo.ROLE_TEAM_MEMBER: + mBinding.btnOperation.setText(R.string.btn_text_quit_team); + mBinding.rlTeamJoinAuth.setVisibility(View.GONE); + mBinding.llTeamManageLabel.setVisibility(View.GONE); + mBinding.llTeamManageContainer.setVisibility(View.GONE); + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SelectFriendActivity.CODE_REQUEST_TO_SHARE_TEAM && resultCode == RESULT_OK) { + String targetUid = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_UID); + String nick = data.getStringExtra(SelectFriendActivity.EXTRA_TARGET_NAME); + int sessionType = data.getIntExtra(SelectFriendActivity.EXTRA_SESSION_TYPE, SessionType.P2P); + IMNetEaseManager.get().sendSharingTeamMessage(sessionType, targetUid, mBinding.getTeamInfo()); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.rl_team_member_count: + if (teamInfo == null) return; + if (TeamModel.get().getTeamInfoCache(teamInfo.getTid()).getRole() == TeamMemberInfo.ROLE_TEAM_OWNER || + TeamModel.get().getTeamInfoCache(teamInfo.getTid()).getRole() == TeamMemberInfo.ROLE_TEAM_MANAGER) { + TeamMemberListActivity.start(this, teamInfo.getTid(), teamInfo.getId(), TeamMemberListActivity.OP_TEAM_MEMBER_REMOVE); + } else { + TeamMemberListActivity.start(this, teamInfo.getTid(), teamInfo.getId(), TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL); + } + break; + case R.id.rl_clear_chat_history: + displayClearChatHistoryDialog(); + break; + + case R.id.rl_team_icon: + if (teamInfo == null) return; + if (teamInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MEMBER){ + return; + } + showTakePhotoOperationDialog(); + break; + + case R.id.rl_team_name: + if (teamInfo == null) return; + if (teamInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MEMBER){ + return; + } + UpdateTeamNameActivity.start(this, teamInfo.getTid()); + break; + + case R.id.rl_set_team_managers: + if (teamInfo == null) return; + if (teamInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MEMBER){ + return; + } + TeamMemberListActivity.start(this, teamInfo.getTid(), teamInfo.getId(), TeamMemberListActivity.OP_TEAM_MEMBER_MANAGEMENT); + break; + + case R.id.rl_team_mute_member: + if (teamInfo == null) return; + if (teamInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MEMBER){ + return; + } + TeamMemberListActivity.start(this, teamInfo.getTid(), teamInfo.getId(), TeamMemberListActivity.OP_TEAM_MEMBER_MUTE); + break; + case R.id.rl_group_statistics: + TeamWeeklyBillActivity.start(this, teamInfo.getId()); + break; + + case R.id.btn_operation: + if (teamInfo == null) return; + // 根据用户的权限显示「退出群」dialog 还是 「删除群」dialog + switch (teamInfo.getRole()) { + case TeamMemberInfo.ROLE_TEAM_OWNER: + displayDeleteTeamDialog(); + break; + + case TeamMemberInfo.ROLE_TEAM_MANAGER: + case TeamMemberInfo.ROLE_TEAM_MEMBER: + displayQuitTeamDialog(); + break; + } + break; + } + } + + private void displayClearChatHistoryDialog() { + List buttonItems = new ArrayList<>(); + ButtonItem buttonItem1 = new ButtonItem(getString(R.string.text_clear_chat_history), () -> { + teamViewModel.clearChattingHistory(teamId); + MessageListPanelHelper.getInstance().notifyClearMessages(teamId); + toast("清空成功"); + }); + buttonItems.add(buttonItem1); + + DialogManager dialogManager = getDialogManager(); + if (dialogManager != null) { + dialogManager.showCommonPopupDialog(buttonItems, getString(R.string.cancel)); + } + } + + private void displayDeleteTeamDialog() { + getDialogManager().showOkCancelWithTitleDialog(getString(R.string.tips_delete_team), + () -> teamViewModel.deleteTeam(teamInfo.getId(), teamInfo.getUid()) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("删除失败" + throwable.getMessage()); + } else { + toast("删除成功"); + RxBus.get().post(new TeamEvent().setOperation(TeamEvent.OP_DELETE_TEAM)); + finish(); + } + })); + } + + private void displayQuitTeamDialog() { + String[] tips = new String[]{"退出后将收不到群消息,确认退出", teamInfo.getName(), "总群吗?"}; + getDialogManager().showOkCancelWithTitleDialog(tips, + () -> teamViewModel.quiteTeam(teamInfo.getId()) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("退出失败" + throwable.getMessage()); + } else { + toast("退出成功"); + RxBus.get().post(new TeamEvent().setOperation(TeamEvent.OP_QUIT_TEAM)); + finish(); + } + })); + } + + @Override + public void onInAppSharingItemClick() { + if (shareDialog != null && shareDialog.isShowing()) { + shareDialog.dismiss(); + } + SelectFriendActivity.startForSharingTeam(this); + } + + @Override + public void onSharePlatformClick(Platform platform) { + if (teamInfo != null) { + ShareModel.get().shareFamilyTeam( + platform, + teamInfo.getFamilyId(), + teamInfo.getIcon(), + teamInfo.getName() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + } + } + + @Override + public void onUploadSuccess(String url) { + teamViewModel.updateTeamIcon(teamInfo.getId(), url) + .compose(bindToLifecycle()) + .subscribe((teamInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("更新群头像失败"); + } else { + GlideApp.with(this) + .load(url) + .dontAnimate() + .into(mBinding.ivTeamIcon); + TeamModel.get().setTeamInfoCache(teamInfo.getTid(), teamInfo); + } + }); + } + + + /** + * 获取家族信息,决定输入面板的红包,家族游戏是否出现 + */ + private void requestFamilyInfo() { + if (FamilyModel.Instance().getMyFamily() != null) { + FamilyModel.Instance().loadFamilySimpleInfo( + FamilyModel.Instance().getMyFamily().getFamilyId() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + if (familyInfo.isOpenMoney()){ + mBinding.rlGroupStatistics.setVisibility(View.VISIBLE); + }else { + mBinding.rlGroupStatistics.setVisibility(View.GONE); + } + } + + @Override + public void onError(Throwable e) { + + } + }); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageActivity.java new file mode 100644 index 000000000..d0dafa204 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageActivity.java @@ -0,0 +1,418 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.model.SimpleCallback; +import com.netease.nim.uikit.api.model.contact.ContactChangedObserver; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.api.model.team.TeamDataChangedObserver; +import com.netease.nim.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.netease.nim.uikit.api.wrapper.NimToolBarOptions; +import com.netease.nim.uikit.business.ait.event.AitContactActionEvent; +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.actions.ImageAction; +import com.netease.nim.uikit.business.session.constant.Extras; +import com.netease.nim.uikit.business.session.fragment.MessageFragment; +import com.netease.nim.uikit.business.session.module.list.MessageListPanelEx; +import com.netease.nim.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.DragLayout; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.erban.ui.im.actions.FamilyGameAction; +import com.yizhuan.erban.ui.im.actions.LuckyMoneyAction; +import com.yizhuan.erban.ui.im.avtivity.BaseMessageActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.initial.bean.InitInfo; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.team.bean.TeamEvent; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 24/05/2018. + */ + +public class NimTeamMessageActivity extends BaseMessageActivity { + + private static final String TAG = "NimTeamMessageActivity"; + + // model + private Team team; + + private View invalidTeamTipView; + + private TextView invalidTeamTipText; + + private ImageView managementView; + + private NimTeamMessageFragment fragment; + + private TeamViewModel teamViewModel; + + private DragLayout teamAvatarLayout; + private ImageView teamAvatar; + + public static void start(Context context, String tid) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, tid); + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonTeamSessionCustomization); + intent.setClass(context, NimTeamMessageActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + + context.startActivity(intent); + } + + protected void findViews() { + invalidTeamTipView = findViewById(R.id.invalid_team_tip); + invalidTeamTipText = findViewById(R.id.invalid_team_text); + managementView = findViewById(R.id.iv_team_member_list); + teamAvatarLayout = (DragLayout) findViewById(R.id.avatar_image_layout); + teamAvatar = (ImageView) findViewById(R.id.avatar_image); + teamAvatarLayout.setOnClickListener(v -> { + if (FamilyModel.Instance().getMyFamily() != null) { + FamilyHomeActivity.start(this, FamilyModel.Instance().getMyFamily().getFamilyId()); + } + }); + if (FamilyModel.Instance().getMyFamily() != null) { + ImageLoadUtils.loadAvatar(getApplicationContext(), FamilyModel.Instance().getMyFamily().getFamilyIcon(), + teamAvatar, true); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + findViews(); + + teamViewModel = new TeamViewModel(); + + openTeamManagementPage(); + + registerTeamUpdateObserver(true); + + RxBus.get().toFlowable(TeamEvent.class) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(teamEvent -> { + switch (teamEvent.getOperation()) { + case TeamEvent.OP_DELETE_TEAM: + case TeamEvent.OP_QUIT_TEAM: + requestTeamInfo(); + break; + + case TeamEvent.OP_UPDATE_MSG: + MessageListPanelEx messageListPanelEx = fragment.getMessageListPanelEx(); + int itemIndex = messageListPanelEx.getItemIndex(teamEvent.getMsgUuid()); + messageListPanelEx.refreshViewHolderByIndex(itemIndex); + break; + } + }); + EventBus.getDefault().register(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + registerTeamUpdateObserver(false); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onStart() { + super.onStart(); + requestFamilyInfo(); + } + + @Override + protected void onResume() { + super.onResume(); + requestTeamInfo(); + } + + /** + * 获取家族信息,决定输入面板的红包,家族游戏是否出现 + */ + private void requestFamilyInfo() { + if (FamilyModel.Instance().getMyFamily() == null) { + return; + } + FamilyModel.Instance().loadFamilySimpleInfo( + FamilyModel.Instance().getMyFamily().getFamilyId() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + if (familyInfo.isOpenMoney()) { + SessionCustomization sessionCustomization = new SessionCustomization(); + ArrayList actions = new ArrayList<>(); + actions.add(new ImageAction()); + actions.add(new LuckyMoneyAction()); + if (familyInfo.isOpenGame()) { + actions.add(new FamilyGameAction()); + } + sessionCustomization.actions = actions; + sessionCustomization.withSticker = true; + fragment.reloadInputPanel(sessionCustomization); + } else { + SessionCustomization sessionCustomization = new SessionCustomization(); + ArrayList actions = new ArrayList<>(); + actions.add(new ImageAction()); + sessionCustomization.actions = actions; + sessionCustomization.withSticker = true; + fragment.reloadInputPanel(sessionCustomization); + } + } + + @Override + public void onError(Throwable e) { +// Toast.makeText(NimTeamMessageActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + } + + /** + * 强行完成@人页面的跳转 + * + * @see com.netease.nim.uikit.business.ait.AitManager 下的 afterTextChanged 方法里改掉原来的跳转逻辑, + * 通过 rxbus 的方式在这里打开我们的成员列表页面 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void openAitTeamMemberPage(AitContactActionEvent event) { + String content = event.getContent(); + if (content != null && !Objects.equals(content, "") && content.endsWith("@")) { + TeamMemberListActivity.start(this, sessionId, + TeamModel.get().getTeamInfoCache(sessionId).getId(), TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL); + } + } + + public void openTeamManagementPage() { + managementView.setOnClickListener(v -> { + NimTeamManagementActivity.start(this, team.getId()); + }); + } + + /** + * 请求群基本信息 + */ + private void requestTeamInfo() { + // 请求群基本信息 + Team t = NimUIKit.getTeamProvider().getTeamById(sessionId); + if (t != null) { + updateTeamInfo(t); + } else { + NimUIKit.getTeamProvider().fetchTeamById(sessionId, new SimpleCallback() { + @Override + public void onResult(boolean success, Team result, int code) { + if (success && result != null) { + updateTeamInfo(result); + } else { + onRequestTeamInfoFailed(); + } + } + }); + } + + teamViewModel.getTeamInfo(sessionId) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe((teamInfo, throwable) -> { + if (teamInfo != null) { + TeamModel.get().setCurrentTeamInfo(teamInfo); + TeamModel.get().setTeamInfoCache(sessionId, teamInfo); + } + }); + } + + private void onRequestTeamInfoFailed() { +// Toast.makeText(NimTeamMessageActivity.this, "获取群组信息失败!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("获取群组信息失败!"); + finish(); + } + + /** + * 更新群信息 + * + * @param d + */ + private void updateTeamInfo(final Team d) { + if (d == null) { + return; + } + + team = d; + fragment.setTeam(team); + + setTitle(team == null ? sessionId : team.getName() + "(" + team.getMemberCount() + "人)"); + + invalidTeamTipText.setText(team.getType() == TeamTypeEnum.Normal ? R.string.normal_team_invalid_tip : R.string.team_invalid_tip); + invalidTeamTipView.setVisibility(team.isMyTeam() ? View.GONE : View.VISIBLE); + + managementView.setVisibility(team.isMyTeam() ? View.VISIBLE : View.GONE); + teamAvatarLayout.setVisibility(team.isMyTeam() ? View.VISIBLE : View.GONE); + } + + @Override + public void setTitle(CharSequence title) { + super.setTitle(title); + getToolBar().setTitle(title); + } + + /** + * 注册群信息更新监听 + * + * @param register + */ + private void registerTeamUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register); + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + } + + /** + * 群资料变动通知和移除群的通知(包括自己退群和群被解散) + */ + TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() { + @Override + public void onUpdateTeams(List teams) { + if (team == null) { + return; + } + for (Team t : teams) { + if (t.getId().equals(team.getId())) { + updateTeamInfo(t); + break; + } + } + } + + @Override + public void onRemoveTeam(Team team) { + if (team == null) { + return; + } + if (team.getId().equals(NimTeamMessageActivity.this.team.getId())) { + updateTeamInfo(team); + } + } + }; + + /** + * 群成员资料变动通知和移除群成员通知 + */ + TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() { + + @Override + public void onUpdateTeamMember(List members) { + fragment.refreshMessageList(); + } + + @Override + public void onRemoveTeamMember(List member) { + Log.e(TAG, "onRemoveTeamMember() called with: member = [" + member + "]"); + } + }; + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + fragment.refreshMessageList(); + } + + @Override + public void onDeletedFriends(List accounts) { + fragment.refreshMessageList(); + } + + @Override + public void onAddUserToBlackList(List account) { + fragment.refreshMessageList(); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + fragment.refreshMessageList(); + } + }; + + @Override + protected MessageFragment fragment() { + // 添加fragment + Bundle arguments = getIntent().getExtras(); + if (arguments != null) { + arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.Team); + } + fragment = new NimTeamMessageFragment(); + fragment.setArguments(arguments); + fragment.setContainerId(R.id.message_fragment_container); + + // 等级限制 + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + UserLevelVo userLevelVo = userInfo.getUserLevelVo(); + if (userLevelVo != null) { + fragment.setCurrentLevel(userLevelVo.experLevelSeq); + } + } + InitInfo initInfo = InitialModel.get().getCacheInitInfo(); + if (initInfo != null) { + fragment.setLimitLevel(initInfo.getPrivateChatLevelNo()); + } + return fragment; + } + + @Override + protected int getContentViewId() { + return R.layout.activity_team_message; + } + + @Override + protected void initToolBar() { + ToolBarOptions options = new NimToolBarOptions(); + options.titleString = "群聊"; + setToolBar(R.id.toolbar, options); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageFragment.java b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageFragment.java new file mode 100644 index 000000000..2d05feaa2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/NimTeamMessageFragment.java @@ -0,0 +1,150 @@ +package com.yizhuan.erban.team.view; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.netease.nim.uikit.business.session.fragment.MessageFragment; +import com.netease.nim.uikit.business.session.module.input.InputPanel; +import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent; +import com.netease.nim.uikit.business.session.module.input.NimImageActionEvent; +import com.netease.nim.uikit.business.session.module.list.MessageListPanelEx; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.model.LeaveTeamAttachment; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.IMMessageManager; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import io.reactivex.Observable; + +/** + * Created by MadisonRong on 10/07/2018. + */ + +public class NimTeamMessageFragment extends MessageFragment { + private Team team; + + private RxPermissions rxPermissions; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + rxPermissions = new RxPermissions(this); + } + + @Override + public boolean isAllowSendMessage(IMMessage message) { + if (team == null || !team.isMyTeam()) { +// Toast.makeText(getActivity(), R.string.team_send_message_not_allow, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.team_send_message_not_allow); + return false; + } + + return true; + } + + @Override + public void onResume() { + super.onResume(); + TeamMember teamMember = NIMClient.getService(TeamService.class) + .queryTeamMemberBlock(sessionId, String.valueOf(AuthModel.get().getCurrentUid())); + if (teamMember != null && teamMember.isMute()) { + inputPanel.disableButtons(); + } + } + + public void setTeam(Team team) { + this.team = team; + } + + public MessageListPanelEx getMessageListPanelEx() { + return messageListPanel; + } + + public InputPanel getInputPanel() { + return inputPanel; + } + + @Override + public List filterLoadedMessage(List messageList) { + if (messageList != null) { + messageList = IMMessageManager.filterMessage(messageList); + } + return messageList; + } + + // @Override + public void appendAPNSConfig(IMMessage message) { + + //iphone 手机通知标题配置 + Map apsField = new HashMap<>(); + Map alert = new HashMap<>(); + if (team != null) { + alert.put("title", team.getName()); + } + alert.put("body", message.getContent()); + apsField.put("alert", alert); + + if (message.getPushPayload() == null) { + Map payload = new HashMap<>(); + payload.put("apsField", apsField); + message.setPushPayload(payload); + } else { + message.getPushPayload().put("apsField", apsField); + } + } + + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressLint("CheckResult") + public void onNimAudioChatEvent(NimAudioChatEvent event) { + checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO) + .subscribe(result -> { + if (result) { + event.getSuccess().accept(result); + } else { + SingleToastUtil.showToast(getString(R.string.ask_again)); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressLint("CheckResult") + public void onNimImageActionEvent(NimImageActionEvent event) { + checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA) + .subscribe(result -> { + if (result) { + event.getSuccess().accept(result); + } else { + SingleToastUtil.showToast(getString(R.string.ask_again)); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/TeamListFragment.java b/app/src/main/java/com/yizhuan/erban/team/view/TeamListFragment.java new file mode 100644 index 000000000..0fb57cdbe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/TeamListFragment.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.team.view; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.FragmentTeamListBinding; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.team.adapter.TeamListAdapter; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +/** + * Created by MadisonRong on 11/06/2018. + */ +@ActLayoutRes(R.layout.fragment_team_list) +public class TeamListFragment extends BaseBindingFragment { + + private TeamListAdapter adapter; + private TeamViewModel teamViewModel; + private int type; + private SelectFriendActivity friendActivity; + + public static TeamListFragment newInstanceForSelect(int type){ + TeamListFragment fragment = new TeamListFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(AbstractSelectFriendAction.KEY_TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + if (activity instanceof SelectFriendActivity){ + friendActivity = (SelectFriendActivity) activity; + } + } + + @Override + public void initiate() { + + if (getArguments() != null) { + type = getArguments().getInt(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_NORMAL); + } + + teamViewModel = new TeamViewModel(); + adapter = new TeamListAdapter(getContext()); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + mBinding.recyclerView.setAdapter(adapter); + adapter.setType(type); + adapter.setOnItemChildClickListener((adapter1, view, position) -> { + TeamInfo item = adapter.getItem(position); + if (friendActivity != null && item != null) { + friendActivity.shareToTeam(item.getTid(), item.getIcon(), item.getName()); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + teamViewModel.queryJoin() + .subscribe((teamInfos, throwable) -> { + if (!ListUtils.isListEmpty(teamInfos)) { + adapter.setNewData(teamInfos); + adapter.notifyDataSetChanged(); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberListActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberListActivity.java new file mode 100644 index 000000000..5e7eb9490 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberListActivity.java @@ -0,0 +1,384 @@ +package com.yizhuan.erban.team.view; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.SimpleItemAnimator; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.model.Team; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityTeamMemberListBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.TeamMemberListAdapter; +import com.yizhuan.erban.team.bean.NimTeamMember; +import com.yizhuan.erban.team.event.TeamMemberUpdateEvent; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.family.bean.FamilyMemberInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.functions.Consumer; + +/** + * Created by MadisonRong on 30/05/2018. + */ +@ActLayoutRes(R.layout.activity_team_member_list) +public class TeamMemberListActivity extends BaseBindingActivity + implements TeamMemberListAdapter.OnOperationButtonClickedListener, TeamMemberListAdapter.OnItemClickListener { + + private static final String TAG = "TeamMemberListActivity"; + + public static final String EXTRA_ID = "EXTRA_ID"; + public static final String EXTRA_TEAM_ID = "EXTRA_TEAM_ID"; + public static final int FIRST_PAGE = 1; + + public static final int REQUEST_CODE = 0x10; + public static final String RESULT_TYPE = "type"; + public static final String RESULT_DATA = "data"; + public static final int TYPE_SELECT_AIT_MEMBER = 2; + + public static final String KEY_OPERATION_TYPE = "KEY_OPERATION_TYPE"; + + public static final int OP_TEAM_MEMBER_NORMAL = 0; + public static final int OP_TEAM_MEMBER_REMOVE = 1; + public static final int OP_TEAM_MEMBER_MANAGEMENT = 2; + public static final int OP_TEAM_MEMBER_MUTE = 3; + + private String tid; + private String chatId; + private int type; + private int page = FIRST_PAGE; + private boolean isLoading = false; + private TeamMemberListAdapter teamMemberListAdapter; + private TeamViewModel teamViewModel; + private TeamInfo teamInfo; + + private TitleBar.Action addMemberAction = new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_family_add; + } + + @Override + public void performAction(View view) { + AddMemberActivity.start(TeamMemberListActivity.this, tid); + } + }; + + private TitleBar.Action searchAction = new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_family_search; + } + + @Override + public void performAction(View view) { + TeamMemberSearchListActivity.start(TeamMemberListActivity.this, teamInfo.getTid(), type); + } + }; + + + public static void start(Context context, String tid, String chatId, int type) { + Intent intent = new Intent(context, TeamMemberListActivity.class); + intent.putExtra(KEY_OPERATION_TYPE, type); + intent.putExtra(EXTRA_ID, chatId); + intent.putExtra(EXTRA_TEAM_ID, tid); + ((Activity) context).startActivityForResult(intent, REQUEST_CODE); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.title_team_member_list)); + teamViewModel = new TeamViewModel(); + + type = getIntent().getIntExtra(KEY_OPERATION_TYPE, OP_TEAM_MEMBER_NORMAL); + chatId = getIntent().getStringExtra(EXTRA_ID); + tid = getIntent().getStringExtra(EXTRA_TEAM_ID); + mBinding.titleBar.addAction(searchAction); + if (type == OP_TEAM_MEMBER_REMOVE && ( + TeamModel.get().getTeamInfoCache(tid).getRole() == TeamMemberInfo.ROLE_TEAM_OWNER || + TeamModel.get().getTeamInfoCache(tid).getRole() == TeamMemberInfo.ROLE_TEAM_MANAGER)) { + mBinding.titleBar.addAction(addMemberAction); + } + + + teamMemberListAdapter = new TeamMemberListAdapter(this, type); + mBinding.rvMember.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + + teamMemberListAdapter.setOnLoadMoreListener(() -> { + if (!NetworkUtil.isNetAvailable(TeamMemberListActivity.this)) { + teamMemberListAdapter.loadMoreComplete(); + return; + } + loadData(page); + }, mBinding.rvMember); + + mBinding.rvMember.setAdapter(teamMemberListAdapter); + teamMemberListAdapter.setOnOperationButtonClickedListener(this); + teamMemberListAdapter.setOnItemClickListener(this); + mBinding.rvMember.getItemAnimator().setChangeDuration(0); + ((SimpleItemAnimator) mBinding.rvMember.getItemAnimator()).setSupportsChangeAnimations(false); + + updateTeamMemberCount(String.valueOf(TeamModel.get().getTeamInfoCache(tid).getMemberCount())); + + teamInfo = TeamModel.get().getTeamInfoCache(tid); + + showLoading(); + mBinding.setClick(this); + + mBinding.srlMemberList.setOnRefreshListener(() -> { + if (!NetworkUtil.isNetAvailable(TeamMemberListActivity.this)) { + mBinding.srlMemberList.setRefreshing(false); + return; + } + firstLoad(); + }); +// mBinding.srlMemberList.setOnRefreshLoadmoreListener(new OnRefreshLoadmoreListener() { +// @Override +// public void onLoadmore(RefreshLayout refreshLayout) { +// if (!NetworkUtil.isNetAvailable(TeamMemberListActivity.this)) { +// mBinding.srlMemberList.finishLoadmore(); +// return; +// } +// List data = teamMemberListAdapter.getData(); +// if (ListUtils.isListEmpty(data)) { +// mBinding.srlMemberList.finishLoadmore(); +// return; +// } +// loadData(page); +// } +// +// @Override +// public void onRefresh(RefreshLayout refreshLayout) { +// if (!NetworkUtil.isNetAvailable(TeamMemberListActivity.this)) { +// mBinding.srlMemberList.finishRefresh(); +// return; +// } +// firstLoad(); +// } +// }); + + firstLoad(); + + addRxEvent(); + } + + private void addRxEvent() { + /** + * 家族成员更新 + */ + RxBusHelper.doOnMainThread(TeamMemberUpdateEvent.class, mCompositeDisposable, teamMemberUpdate -> firstLoad()); + } + + private void firstLoad() { + loadData(FIRST_PAGE); + } + + private void loadData(int targetPage) { + if (isLoading) { + return; + } + this.page = targetPage; + isLoading = true; + teamViewModel.getTeamMemberList(chatId, String.valueOf(page)) + .compose(bindToLifecycle()) + .subscribe((respTeamMemberInfo, throwable) -> { + isLoading = false; + mBinding.srlMemberList.setRefreshing(false); + if (throwable != null) { + toast(throwable.getMessage()); + return; + } + List teamMemberInfos = respTeamMemberInfo.getMemberList(); + if (!ListUtils.isListEmpty(teamMemberInfos)) { + hideStatus(); + if (page == FIRST_PAGE) { + teamMemberListAdapter.setNewData(teamMemberInfos); + } else { + teamMemberListAdapter.addData(teamMemberInfos); + teamMemberListAdapter.loadMoreComplete(); + } + page++; + } else { + finishLoadingData(); + } + updateTeamMemberCount(String.valueOf(respTeamMemberInfo.getCount())); + }); + } + + private void updateTeamMemberCount(String memberCount) { + mBinding.tvMemberCount.setText(getString(R.string.family_member_label2, memberCount)); + } + + private void finishLoadingData() { + if (page == FIRST_PAGE) { + showNoData(); + mBinding.srlMemberList.setRefreshing(false); + } else { + teamMemberListAdapter.loadMoreEnd(true); + } + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK) { + switch (requestCode) { + case AddMemberActivity.REQUEST_CODE_SELECT_MEMBER: + ArrayList listExtra = (ArrayList) data.getSerializableExtra(AddMemberActivity.EXTRA_SELECTED_MEMBER); + if (listExtra != null) { + List selectMemberUids = new ArrayList<>(); + for (FamilyMemberInfo familyMemberInfo : listExtra) { + selectMemberUids.add(String.valueOf(familyMemberInfo.getUid())); + } + String[] newMembers = new String[selectMemberUids.size()]; + newMembers = selectMemberUids.toArray(newMembers); + // 添加成员,并且刷新列表 + teamViewModel.addMemberToTeam(chatId, newMembers) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } else { + firstLoad(); + } + }); + } + break; + } + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_search: + TeamMemberSearchListActivity.start(this, teamInfo.getTid(), type); + break; + } + } + + @Override + public void onOperationButtonClicked(int position, TeamMemberInfo teamMemberInfo, int type) { + switch (type) { + default: + case TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL: + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_REMOVE: + getDialogManager().showOkCancelWithTitleDialog(new String[]{"移出后将收不到群消息,确认移出", teamMemberInfo.getNick(), "吗?"}, + () -> teamViewModel.kickOutTeamMember(chatId, String.valueOf(teamMemberInfo.getUid())) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } else { + teamMemberListAdapter.remove(position); + Team team = NIMClient.getService(TeamService.class).queryTeamBlock(tid); + updateTeamMemberCount(String.valueOf(team.getMemberCount())); + } + })); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MANAGEMENT: + boolean wannaSetManager = !(teamMemberInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MANAGER); + String[] message = wannaSetManager ? new String[]{"成为管理员后将拥有修改群名称的权限,确定设置", teamMemberInfo.getNick(), "为群管理吗?"} + : new String[]{"取消管理员后将不再拥有修改群名称的权限,确定取消", teamMemberInfo.getNick(), "为群管理吗?"}; + getDialogManager().showOkCancelWithTitleDialog(message, () -> + teamViewModel.setTeamManager(chatId, String.valueOf(teamMemberInfo.getUid()), wannaSetManager) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } else { + teamMemberInfo.setRole(wannaSetManager ? TeamMemberInfo.ROLE_TEAM_MANAGER : TeamMemberInfo.ROLE_TEAM_MEMBER); + teamInfo.setManagerCount(wannaSetManager ? teamInfo.getManagerCount() + 1 : teamInfo.getManagerCount() - 1); + teamMemberListAdapter.notifyItemChanged(position); + } + })); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MUTE: + boolean wannaMute = !teamMemberInfo.isDisable(); + if (wannaMute) { + getDialogManager().showOkCancelWithTitleDialog( + new String[]{"禁言后将不能在群里发言,确定要禁言", teamMemberInfo.getNick(), "吗?"}, + () -> + muteTeamMember(teamMemberInfo, true, position)); + } else { + muteTeamMember(teamMemberInfo, false, position); + } + break; + } + } + + private void muteTeamMember(TeamMemberInfo teamMemberInfo, boolean wannaMute, int position) { + teamViewModel.muteTeamMember(chatId, String.valueOf(teamMemberInfo.getUid()), wannaMute) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("操作失败"); + } else { + teamMemberInfo.setDisable(wannaMute); + teamInfo.setDisabledCount(wannaMute ? + teamInfo.getDisabledCount() + 1 : + teamInfo.getDisabledCount() - 1); + teamMemberListAdapter.notifyItemChanged(position); + } + }); + } + + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + switch (type) { + case TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL: + Intent intent = new Intent(); + TeamMemberInfo teamMemberInfo = (TeamMemberInfo) adapter.getItem(position); + if (teamMemberInfo != null) { + NimTeamMember teamMember = new NimTeamMember(); + teamMember.setTid(tid); + teamMember.setAccount(String.valueOf(teamMemberInfo.getUid())); + teamMember.setTeamNick(teamMemberInfo.getTeamNick()); + intent.putExtra(RESULT_DATA, teamMember); + intent.putExtra(RESULT_TYPE, TYPE_SELECT_AIT_MEMBER); + } + setResult(RESULT_OK, intent); + finish(); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberSearchListActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberSearchListActivity.java new file mode 100644 index 000000000..597aa009f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/TeamMemberSearchListActivity.java @@ -0,0 +1,289 @@ +package com.yizhuan.erban.team.view; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Toast; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityTeamMemberSearchListBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.rxbus.RxBusHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.TeamMemberListAdapter; +import com.yizhuan.erban.team.bean.NimTeamMember; +import com.yizhuan.erban.team.event.TeamMemberUpdateEvent; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.Iterator; + +import static com.yizhuan.erban.team.view.TeamMemberListActivity.EXTRA_ID; +import static com.yizhuan.erban.team.view.TeamMemberListActivity.KEY_OPERATION_TYPE; +import static com.yizhuan.erban.team.view.TeamMemberListActivity.OP_TEAM_MEMBER_NORMAL; +import static com.yizhuan.erban.team.view.TeamMemberListActivity.REQUEST_CODE; +import static com.yizhuan.erban.team.view.TeamMemberListActivity.RESULT_DATA; + +/** + * Created by MadisonRong on 31/05/2018. + */ +@ActLayoutRes(R.layout.activity_team_member_search_list) +public class TeamMemberSearchListActivity extends BaseBindingActivity + implements TeamMemberListAdapter.OnOperationButtonClickedListener, TeamMemberListAdapter.OnItemClickListener { + + private String tid; + private int type; + private TeamMemberListAdapter teamMemberListAdapter; + private TeamViewModel teamViewModel; + private TeamInfo teamInfo; + + public static void start(Context context, String tid, int type) { + Intent intent = new Intent(context, TeamMemberSearchListActivity.class); + intent.putExtra(KEY_OPERATION_TYPE, type); + intent.putExtra(EXTRA_ID, tid); + ((Activity) context).startActivityForResult(intent, REQUEST_CODE); + } + + @Override + protected void init() { + teamViewModel = new TeamViewModel(); + + type = getIntent().getIntExtra(KEY_OPERATION_TYPE, OP_TEAM_MEMBER_NORMAL); + tid = getIntent().getStringExtra(EXTRA_ID); + + teamInfo = TeamModel.get().getTeamInfoCache(tid); + + teamMemberListAdapter = new TeamMemberListAdapter(this, type); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + mBinding.recyclerView.setAdapter(teamMemberListAdapter); + teamMemberListAdapter.setOnOperationButtonClickedListener(this); + teamMemberListAdapter.setOnItemClickListener(this); + View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null, false); + teamMemberListAdapter.addHeaderView(headerView); + + mBinding.searchEdit.addTextChangedListener(textWatcher); + mBinding.searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + mBinding.searchEdit.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + String str = v.getText().toString(); + if (!searchMemberList(str)) return false; + hideIME(); + return true; + } + return false; + + }); + + mBinding.ivClearText.setVisibility(View.GONE); + + mBinding.setClick(this); + + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + mBinding.ivClearText.setVisibility(View.GONE); + } else { + mBinding.ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == mBinding.ivBack.getId()) { + hideIME(); + finish(); + } else if (id == mBinding.tvSearch.getId()) { + String str = mBinding.searchEdit.getText().toString(); + if (searchMemberList(str)) return; + hideIME(); + + } else if (id == mBinding.ivClearText.getId()) { + mBinding.searchEdit.setText(""); + } + + } + + private boolean searchMemberList(String str) { + if (TextUtils.isEmpty(str)) { +// Toast.makeText(this, "请输入搜索内容!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return true; + } + showLoading(); + + teamViewModel.queryErbanNo(teamInfo.getId(), str, 1) + .compose(bindToLifecycle()) + .subscribe((teamMemberInfos, throwable) -> { + hideStatus(); + if (throwable != null) { + throwable.printStackTrace(); +// toast(throwable.getMessage()); + showPageError(0); + } else { + if (!ListUtils.isListEmpty(teamMemberInfos)) { + teamMemberListAdapter.setNewData(teamMemberInfos); + } else { + showNoData(); + } + } + }); + + return false; + } + + @Override + public void onOperationButtonClicked(int position, TeamMemberInfo teamMemberInfo, int type) { + switch (type) { + default: + case OP_TEAM_MEMBER_NORMAL: + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_REMOVE: + getDialogManager().showTipsDialog(getString(R.string.dialog_tips_remove_team_member, teamMemberInfo.getNick()), + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + teamViewModel.kickOutTeamMember(teamInfo.getId(), String.valueOf(teamMemberInfo.getUid())) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } else { + toast("成功移出群"); + RxBusHelper.post(new TeamMemberUpdateEvent()); + Iterator iterator = teamMemberListAdapter.getData().iterator(); + while (iterator.hasNext()){ + TeamMemberInfo item = iterator.next(); + if (item.getId().equals(teamMemberInfo.getId())){ + iterator.remove(); + break; + } + } + teamMemberListAdapter.notifyDataSetChanged(); + + } + }); + } + }); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MANAGEMENT: + boolean wannaSetManager = !(teamMemberInfo.getRole() == TeamMemberInfo.ROLE_TEAM_MANAGER); + String message = wannaSetManager ? getString(R.string.dialog_tips_set_manager, teamMemberInfo.getNick()) + : getString(R.string.dialog_tips_cancel_set_manager, teamMemberInfo.getNick()); + getDialogManager().showTipsDialog(message, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + teamViewModel.setTeamManager(teamInfo.getId(), String.valueOf(teamMemberInfo.getUid()), wannaSetManager) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } else { + teamMemberInfo.setRole(wannaSetManager ? TeamMemberInfo.ROLE_TEAM_MANAGER : TeamMemberInfo.ROLE_TEAM_MEMBER); + teamInfo.setManagerCount(wannaSetManager ? teamInfo.getManagerCount() + 1 : teamInfo.getManagerCount() - 1); + teamMemberListAdapter.notifyItemChanged(position); + } + }); + } + }); + break; + + case TeamMemberListActivity.OP_TEAM_MEMBER_MUTE: + boolean wannaMute = !teamMemberInfo.isDisable(); + if (wannaMute) { + getDialogManager().showTipsDialog( + getString(R.string.dialog_tips_mute_team_member, teamMemberInfo.getNick()), + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + muteTeamMember(teamMemberInfo, true, position); + } + }); + } else { + muteTeamMember(teamMemberInfo, false, position); + } + } + } + + private void muteTeamMember(TeamMemberInfo teamMemberInfo, boolean wannaMute, int position) { + teamViewModel.muteTeamMember(teamInfo.getId(), String.valueOf(teamMemberInfo.getUid()), wannaMute) + .compose(bindToLifecycle()) + .subscribe((s, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("操作失败"); + } else { + teamMemberInfo.setDisable(wannaMute); + teamInfo.setDisabledCount(wannaMute ? + teamInfo.getDisabledCount() + 1 : + teamInfo.getDisabledCount() - 1); + teamMemberListAdapter.notifyItemChanged(position); + } + }); + } + + @Override + public void onItemClick(BaseQuickAdapter adapter, View view, int position) { + switch (type) { + case OP_TEAM_MEMBER_NORMAL: + Intent intent = new Intent(); + TeamMemberInfo teamMemberInfo = (TeamMemberInfo) adapter.getItem(position); + if (teamMemberInfo != null) { + NimTeamMember teamMember = new NimTeamMember(); + teamMember.setTid(tid); + teamMember.setAccount(teamMemberInfo.getAccount()); + teamMember.setTeamNick(teamMemberInfo.getTeamNick()); + intent.putExtra(RESULT_DATA, teamMember); + } + setResult(RESULT_OK, intent); + finish(); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillActivity.java new file mode 100644 index 000000000..50167b427 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillActivity.java @@ -0,0 +1,164 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityTeamWeeklyBillBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.TeamWeeklyBillAdapter; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.team.bean.TeamTransactionRecordInfo; + +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 31/05/2018. + */ +@ActLayoutRes(R.layout.activity_team_weekly_bill) +public class TeamWeeklyBillActivity extends BaseBindingActivity + implements OnRefreshLoadmoreListener { + + public static final int PAGE_FIRST = 1; + + private String chatId; + private TeamViewModel teamViewModel; + private TeamWeeklyBillAdapter teamWeeklyBillAdapter; + private View headerView; + private View emptyView; + private int page = PAGE_FIRST; + + public static void start(Context context, String chatId) { + Intent intent = new Intent(context, TeamWeeklyBillActivity.class); + intent.putExtra(TeamMemberListActivity.EXTRA_ID, chatId); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.title_team_statistics)); + chatId = getIntent().getStringExtra(TeamMemberListActivity.EXTRA_ID); + + mBinding.rvFamilyCurrency.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + teamWeeklyBillAdapter = new TeamWeeklyBillAdapter(this); + teamWeeklyBillAdapter.setEnableLoadMore(true); + mBinding.rvFamilyCurrency.setAdapter(teamWeeklyBillAdapter); + mBinding.swipeRefresh.setOnRefreshLoadmoreListener(this); + + teamViewModel = new TeamViewModel(); + + mBinding.setClick(this); + + emptyView = LayoutInflater.from(this).inflate(R.layout.fragment_no_data, null, false); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + emptyView.setLayoutParams(layoutParams); + + headerView = LayoutInflater.from(this).inflate(R.layout.header_team_currency_bill, null, false); + teamWeeklyBillAdapter.setHeaderView(headerView); + teamWeeklyBillAdapter.setHeaderAndEmpty(true); + headerView.findViewById(R.id.ll_search).setOnClickListener(this); + } + + @Override + protected void onResume() { + super.onResume(); + firstLoad(); + } + + private void firstLoad() { + page = PAGE_FIRST; + loadBill(); + } + + private void loadBill() { + teamViewModel.queryTeamTransactionRecords(chatId, page) + .compose(bindToLifecycle()) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((transactionRecordInfos, throwable) -> { + updateHeaderView(FormatUtils.formatToShortDown(transactionRecordInfos.getWeekAmount()), + FormatUtils.formatToShortDown(transactionRecordInfos.getTotalAmount())); + List weekRecords = transactionRecordInfos.getWeekRecords(); + if (!ListUtils.isListEmpty(weekRecords)) { + teamWeeklyBillAdapter.setEnableLoadMore(true); + mBinding.swipeRefresh.setEnableLoadmore(true); + if (page == PAGE_FIRST) { + teamWeeklyBillAdapter.setNewData(weekRecords); + mBinding.swipeRefresh.finishRefresh(); + } else { + teamWeeklyBillAdapter.addData(weekRecords); + mBinding.swipeRefresh.finishLoadmore(); + } + page ++; + } + finishLoadingData(); + }); + } + + private void finishLoadingData() { + if (page == PAGE_FIRST) { + mBinding.swipeRefresh.finishRefresh(); + teamWeeklyBillAdapter.setEmptyView(emptyView); + teamWeeklyBillAdapter.setEnableLoadMore(false); + mBinding.swipeRefresh.setEnableLoadmore(false); + } else { + mBinding.swipeRefresh.finishLoadmore(); + } + } + + public void updateHeaderView(String weekAmount, String totalAmount) { + String coinName = FamilyModel.Instance().getMyFamily().getMoneyName(); + ((TextView) headerView.findViewById(R.id.tv_team_currency_weekly_bill)) + .setText(getString(R.string.text_team_currency_weekly_bill, coinName)); + ((TextView) headerView.findViewById(R.id.tv_team_currency_balance)).setText(weekAmount); + ((TextView) headerView.findViewById(R.id.tv_team_currency_income)).setText(totalAmount + coinName); + } + + @Override + public void onLoadmore(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(TeamWeeklyBillActivity.this)) { + mBinding.swipeRefresh.finishLoadmore(); + return; + } + List data = teamWeeklyBillAdapter.getData(); + if (ListUtils.isListEmpty(data)) { + mBinding.swipeRefresh.finishLoadmore(); + return; + } + loadBill(); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(TeamWeeklyBillActivity.this)) { + mBinding.swipeRefresh.finishRefresh(); + return; + } + firstLoad(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_search: + TeamWeeklyBillSearchActivity.start(this, chatId); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillSearchActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillSearchActivity.java new file mode 100644 index 000000000..e583c6abd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/TeamWeeklyBillSearchActivity.java @@ -0,0 +1,193 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Toast; + +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadmoreListener; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityTeamWeeklyBillSearchBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.team.adapter.TeamWeeklyBillAdapter; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.team.bean.TeamTransactionRecordInfo; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by MadisonRong on 20/07/2018. + */ +@ActLayoutRes(R.layout.activity_team_weekly_bill_search) +public class TeamWeeklyBillSearchActivity extends BaseBindingActivity + implements OnRefreshLoadmoreListener { + + public static final int PAGE_FIRST = 1; + + private String chatId; + private TeamWeeklyBillAdapter teamWeeklyBillAdapter; + private TeamViewModel teamViewModel; + private int page = PAGE_FIRST; + + public static void start(Context context, String chatId) { + Intent intent = new Intent(context, TeamWeeklyBillSearchActivity.class); + intent.putExtra(TeamMemberListActivity.EXTRA_ID, chatId); + context.startActivity(intent); + } + + @Override + protected void init() { + chatId = getIntent().getStringExtra(TeamMemberListActivity.EXTRA_ID); + + mBinding.rvFamilyCurrency.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); + teamWeeklyBillAdapter = new TeamWeeklyBillAdapter(this); + teamWeeklyBillAdapter.setEnableLoadMore(true); + mBinding.rvFamilyCurrency.setAdapter(teamWeeklyBillAdapter); + mBinding.swipeRefresh.setOnRefreshLoadmoreListener(this); + + teamViewModel = new TeamViewModel(); + + View headerView = LayoutInflater.from(this).inflate(R.layout.layout_search_header, null, false); + teamWeeklyBillAdapter.addHeaderView(headerView); + + mBinding.searchEdit.addTextChangedListener(textWatcher); + mBinding.searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); +// mBinding.searchEdit.setOnEditorActionListener((v, actionId, event) -> { +// if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { +// String str = v.getText().toString(); +// if (!searchMemberList(str)) return false; +// hideIME(); +// return true; +// } +// return false; +// +// }); + + mBinding.ivClearText.setVisibility(View.GONE); + + mBinding.setClick(this); + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + mBinding.ivClearText.setVisibility(View.GONE); + } else { + mBinding.ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == mBinding.ivBack.getId()) { + hideIME(); + finish(); + } else if (id == mBinding.tvSearch.getId()) { + String str = mBinding.searchEdit.getText().toString(); + if (searchMemberList(str)) return; + hideIME(); + + } else if (id == mBinding.ivClearText.getId()) { + mBinding.searchEdit.setText(""); + } + + } + + private boolean searchMemberList(String str) { + if (TextUtils.isEmpty(str)) { +// Toast.makeText(this, "请输入搜索内容!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入搜索内容!"); + return true; + } + showLoading(); + + loadBill(); + + return false; + } + + private void firstLoad() { + page = PAGE_FIRST; + loadBill(); + } + + private void loadBill() { + teamViewModel.searchTeamTransactionRecords(chatId, mBinding.searchEdit.getText().toString(), page) + .compose(bindToLifecycle()) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((transactionRecordInfos, throwable) -> { + List weekRecords = transactionRecordInfos.getWeekRecords(); + if (!ListUtils.isListEmpty(weekRecords)) { + hideStatus(); + if (page == PAGE_FIRST) { + teamWeeklyBillAdapter.setNewData(weekRecords); + mBinding.swipeRefresh.finishRefresh(); + } else { + teamWeeklyBillAdapter.addData(weekRecords); + mBinding.swipeRefresh.finishLoadmore(); + } + page++; + } + finishLoadingData(); + }); + } + + private void finishLoadingData() { + if (page == PAGE_FIRST) { + showNoData(); + mBinding.swipeRefresh.finishRefresh(); + } else { + mBinding.swipeRefresh.finishLoadmore(); + } + } + + @Override + public void onLoadmore(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(TeamWeeklyBillSearchActivity.this)) { + mBinding.swipeRefresh.finishLoadmore(); + return; + } + List data = teamWeeklyBillAdapter.getData(); + if (ListUtils.isListEmpty(data)) { + mBinding.swipeRefresh.finishLoadmore(); + return; + } + loadBill(); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(TeamWeeklyBillSearchActivity.this)) { + mBinding.swipeRefresh.finishRefresh(); + return; + } + firstLoad(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/view/UpdateTeamNameActivity.java b/app/src/main/java/com/yizhuan/erban/team/view/UpdateTeamNameActivity.java new file mode 100644 index 000000000..bf88820ee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/view/UpdateTeamNameActivity.java @@ -0,0 +1,77 @@ +package com.yizhuan.erban.team.view; + +import android.content.Context; +import android.content.Intent; +import android.support.design.widget.Snackbar; +import android.text.InputFilter; +import android.view.View; +import android.widget.EditText; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.ActivityUpdateTeamNameBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.erban.team.viewmodel.TeamViewModel; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; + +import static com.yizhuan.erban.team.view.NimTeamManagementActivity.EXTRA_TEAM_ID; + +/** + * Created by MadisonRong on 28/06/2018. + */ +@ActLayoutRes(R.layout.activity_update_team_name) +public class UpdateTeamNameActivity extends BaseBindingActivity { + + private EditText teamName; + private TeamViewModel teamViewModel; + private String tid; + private TeamInfo teamInfo; + + public static void start(Context context, String tid) { + Intent intent = new Intent(context, UpdateTeamNameActivity.class); + intent.putExtra(EXTRA_TEAM_ID, tid); + context.startActivity(intent); + } + + @Override + protected void init() { + tid = getIntent().getStringExtra(EXTRA_TEAM_ID); + teamInfo = TeamModel.get().getTeamInfoCache(tid); + teamViewModel = new TeamViewModel(); + teamName = mBinding.etContentTeamName; + teamName.setText(teamInfo.getName()); + teamName.setFilters(new InputFilter[]{new InputFilter.LengthFilter(15)}); + initTitleBar("修改群名称"); + } + + @Override + public void initTitleBar(String title) { + super.initTitleBar(title); + TitleBar titleBar = (TitleBar) findViewById(R.id.title_bar); + titleBar.setActionTextColor(R.color.text_color_primary); + titleBar.addAction(new TitleBar.TextAction("保存") { + @Override + public void performAction(View view) { + String content = teamName.getText().toString(); + //修改个人介绍 + if (!content.trim().isEmpty()) { + teamViewModel.updateTeamName(teamInfo.getId(), content) + .compose(bindToLifecycle()) + .subscribe((teamInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + toast("更新失败"); + } else { + TeamModel.get().setTeamInfoCache(teamInfo.getTid(), teamInfo); + finish(); + } + }); + } else { + Snackbar.make(mBinding.layoutCoordinator, "所填内容为空!", Snackbar.LENGTH_SHORT).show(); + } + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/viewmodel/FamilyMemberViewModel.java b/app/src/main/java/com/yizhuan/erban/team/viewmodel/FamilyMemberViewModel.java new file mode 100644 index 000000000..1ff752c30 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/viewmodel/FamilyMemberViewModel.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.team.viewmodel; + +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_core.family.bean.response.memberList.RespFamilymember; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; + +import io.reactivex.Single; + +/** + * Created by MadisonRong on 29/05/2018. + */ + +public class FamilyMemberViewModel extends BaseViewModel { + + + /** + * 获取不在群组内的成员列表 + * @param tid 云信群组 ID + * @param key 查询关键字 + * @param page 页码 + * @return + */ + public Single getNotInTeamFamilyMembers(String tid, String key, int page) { + return FamilyModel.Instance().getNotInTeamMember( + tid, key, page, 10); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/team/viewmodel/TeamViewModel.java b/app/src/main/java/com/yizhuan/erban/team/viewmodel/TeamViewModel.java new file mode 100644 index 000000000..973406599 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/team/viewmodel/TeamViewModel.java @@ -0,0 +1,266 @@ +package com.yizhuan.erban.team.viewmodel; + +import com.yizhuan.erban.base.BaseViewModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyRecordsInfo; +import com.yizhuan.xchat_android_core.team.bean.RespTeamMemberInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamMemberInfo; +import com.yizhuan.xchat_android_core.team.bean.TeamTransactionInfo; +import com.yizhuan.xchat_android_core.team.model.TeamModel; + +import java.util.List; + +import io.reactivex.Single; + +/** + * Created by MadisonRong on 29/05/2018. + */ + +public class TeamViewModel extends BaseViewModel { + + private static final String TAG = "TeamViewModel"; + + + /** + * 分页获取群组成员列表 + * + * @param chatId 群聊 ID + * @param page 页码 + * @return + */ + public Single getTeamMemberList(String chatId, String page) { + return TeamModel.get().getTeamMemberList(chatId, page); + } + + /** + * 创建群组 + * + * @param familyId 家族 ID + * @param uid 创建者的用户 UID + * @param icon 群头像(七牛的 url) + * @param name 群组名称 + * @param isVerify 是否开启身份验证 + * @param members 群组成员 + * @return + */ + public Single createTeam(String familyId, String uid, String icon, String name, boolean isVerify, + String[] members) { + return TeamModel.get().createTeam(familyId,uid,icon,name,isVerify,members); + } + + /** + * 群主(族长)删除本群组 + * + * @param chatId 群组 ID + * @param uid 群主 UID + * @return + */ + public Single deleteTeam(String chatId, String uid) { + return TeamModel.get().deleteTeam(chatId,uid); + } + + /** + * 管理员或者普通成员退出群组 + * + * @param chatId 群组 ID + * @return + */ + public Single quiteTeam(String chatId) { + return TeamModel.get().quiteTeam(chatId); + } + + /** + * 清空群组的聊天记录(本地的) + * + * @param tid 云信群组 ID + */ + public void clearChattingHistory(String tid) { + TeamModel.get().clearChattingHistory(tid); + } + + /** + * 通过轻寻号搜索群聊成员 + * + * @param chatId 群组 ID + * @param erbanNo 轻寻号 + * @param page 页码 + * @return + */ + public Single> queryErbanNo(String chatId, String erbanNo, int page) { + return TeamModel.get().queryErbanNo(chatId, erbanNo, page); + } + + /** + * 添加成员到群组里 + * + * @param chatId 群组 ID + * @param targetUids 目标用户(被操作者) UID 数组 + * @return + */ + public Single addMemberToTeam(String chatId, String[] targetUids) { + return TeamModel.get().addMemberToTeam(chatId, targetUids); + } + + /** + * 设置群组消息提示方式(是否开启消息免打扰) + * + * @param chatId 群组 ID + * @param uid 用户 UID + * @param wannaMute 是否要开启消息免打扰 + * @return + */ + public Single muteNotification(String chatId, String uid, Boolean wannaMute) { + return TeamModel.get().muteNotification(chatId, uid, wannaMute); + } + + /** + * 查询用户已加入的群组列表 + * + * @return + */ + public Single> queryJoin() { + return TeamModel.get().queryJoin(); + } + + /** + * 更新群资料(更新群头像) + * + * @param chatId 群组 ID + * @param icon 群头像 URL + * @return + */ + public Single updateTeamIcon(String chatId, String icon) { + return TeamModel.get().updateTeamIcon(chatId, icon); + } + + /** + * 更新群资料(更新群名称) + * + * @param chatId 群组 ID + * @param name 群名称 + * @return + */ + public Single updateTeamName(String chatId, String name) { + return TeamModel.get().updateTeamName(chatId, name); + } + + /** + * 更新群资料(更新入群验证方式) + * + * @param chatId 群组 ID + * @param isVerify 群组是否加入身份验证 + * @return + */ + public Single updateTeamJoinAuthMethod(String chatId, Boolean isVerify) { + return TeamModel.get().updateTeamJoinAuthMethod(chatId, isVerify); + } + + /** + * 获取群资料 + * + * @param sessionId 云信群组 ID + * @return + */ + public Single getTeamInfo(String sessionId) { + return TeamModel.get().getTeamInfo(sessionId); + } + + /** + * 禁言/解禁 群组成员 + * + * @param chatId 群组 ID + * @param targetUid 目标用户(被操作者) UID + * @param wannaMute 是否禁言 + * @return + */ + public Single muteTeamMember(String chatId, String targetUid, Boolean wannaMute) { + return TeamModel.get().muteTeamMember(chatId, targetUid, wannaMute); + } + + /** + * 设置/取消设置 群组管理员 + * + * @param chatId 群组 ID + * @param targetUid 目标用户(被操作者) UID + * @param wannaSetManager 是否设置管理员;true 为设置,false 为取消设置 + * @return + */ + public Single setTeamManager(String chatId, String targetUid, boolean wannaSetManager) { + return TeamModel.get().setTeamManager(chatId, targetUid, wannaSetManager); + } + + /** + * 踢出群组成员 + * + * @param chatId 群组 ID + * @param targetUid 目标用户(被操作者) UID + * @return + */ + public Single kickOutTeamMember(String chatId, String targetUid) { + return TeamModel.get().kickOutTeamMember(chatId, targetUid); + } + + /** + * 统计群组人数 + * + * @param chatId 群组 ID + * @return + */ + public Single getTeamMemberCount(String chatId) { + return TeamModel.get().getTeamMemberCount(chatId); + } + + /** + * 查询群统计(群组内一周的交易记录) + * @param chatId 群组 ID + * @param page 页码 + * @return + */ + public Single queryTeamTransactionRecords(String chatId, int page) { + return TeamModel.get().queryTeamTransactionRecords(chatId, page); + } + + /** + * 搜索群统计(群组内一周的交易记录) + * @param chatId 群组 ID + * @param page 页码 + * @return + */ + public Single searchTeamTransactionRecords(String chatId, String erbanNo, int page) { + return TeamModel.get().searchTeamTransactionRecords(chatId, erbanNo, page); + } + + /** + * 群组内发红包 + * + * @param tid 云信群组 ID + * @param amount 红包金额 + * @param count 红包可领取个数 + * @return + */ + public Single sendLuckyMoney(String tid, double amount, int count, String message) { + return TeamModel.get().sendLuckyMoney(tid, amount, count, message); + } + + /** + * 群组内收红包 + * + * @param luckyMoneyId 红包 ID + * @return + */ + public Single> receiveLuckyMoney(String luckyMoneyId) { + return TeamModel.get().receiveLuckyMoney(luckyMoneyId); + } + + /** + * 群组内查看红包的领取情况 + * + * @param luckyMoneyId 红包 ID + * @return + */ + public Single receiveLuckyMoneyRecords(String luckyMoneyId) { + return TeamModel.get().receiveLuckyMoneyRecords(luckyMoneyId); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/AnimFactory.java b/app/src/main/java/com/yizhuan/erban/ui/anim/AnimFactory.java new file mode 100644 index 000000000..114ad29ce --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/AnimFactory.java @@ -0,0 +1,201 @@ +package com.yizhuan.erban.ui.anim; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.ColorDrawable; +import android.util.Log; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_library.threadmgr.ThreadPoolManager; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * @author xiaoyu + * @date 2017/11/30 + */ + +public class AnimFactory { + private static final String TAG = "AnimFactory"; + + private AnimFactory() { + } + + public static Single getFaceAnimation(Context context, int width, int height) { + return Single.create((SingleOnSubscribe) e -> { + long time = System.currentTimeMillis(); + AnimationDrawable drawable = new AnimationDrawable(); + FaceInfo faceInfo = DynamicFaceModel.get().findFaceInfoById(24); + // 如果找不到对应的表情,直接返回null + if (faceInfo == null) { + e.onError(new Throwable("no face")); + return; + } + int startIndex = faceInfo.getAnimationIndexStart(); + int endIndex = faceInfo.getAnimationIndexEnd(); + int duration = (int) ((faceInfo.getAnimationDuration() + 0.F) / (endIndex - startIndex)); + int repeatCount = faceInfo.getRepeatCount(); + while (repeatCount > 0) { + for (int i = startIndex; i <= endIndex; i++) { + // 增加每一帧到drawable中 + OneFaceDrawable face = new OneFaceDrawable(context, faceInfo.getFacePath(i), width, height); + drawable.addFrame(face, duration); + } + repeatCount--; + } + // 如果是普通表情,则直接返回 + if (faceInfo.getResultCount() <= 0) { + drawable.addFrame(new ColorDrawable(Color.TRANSPARENT), 10); + e.onSuccess(drawable); + return; + } + // 如果有结果,增加结果帧 + List resultIndexes = new ArrayList<>(); + resultIndexes.add(14); + resultIndexes.add(15); + resultIndexes.add(16); + resultIndexes.add(17); + resultIndexes.add(18); + duration = faceInfo.getResultDuration(); + // 找出所有结果图片的路径 + List images = new ArrayList<>(); + for (int i = 0; i < resultIndexes.size(); i++) { + LogUtil.e(TAG, faceInfo.getFacePath(resultIndexes.get(i))); + images.add(faceInfo.getFacePath(resultIndexes.get(i))); + } + // 根据显示类型,产生对应的类型的结果图片 + int displayType = faceInfo.getDisplayType(); + if (displayType == FaceInfo.DISPLAY_TYPE_ONE_PIC || images.size() == 1) { + OneFaceDrawable face = new OneFaceDrawable(context, images.get(0), width, height); + drawable.addFrame(face, duration); + } else if (displayType == FaceInfo.DISPLAY_TYPE_FLOW) { + FlowFaceDrawable flowFaceDrawable = new FlowFaceDrawable(context, images, width, height); + flowFaceDrawable.setBounds(0, 0, width, height); + drawable.addFrame(flowFaceDrawable, duration); + } else if (displayType == FaceInfo.DISPLAY_TYPE_OVERLAY) { + OverlayFaceDrawable overlayFaceDrawable = new OverlayFaceDrawable(context, images, width, height); + overlayFaceDrawable.setBounds(0, 0, width, height); + drawable.addFrame(overlayFaceDrawable, duration); + } else { + // 未知类型,不显示动画 + e.onError(new Throwable("未知类型,不显示动画")); + return; + } + + //隐藏drawable + ColorDrawable colorDrawable = new ColorDrawable(Color.TRANSPARENT); + colorDrawable.setBounds(0, 0, width, height); + drawable.addFrame(new ColorDrawable(Color.TRANSPARENT), 10); + Log.e(TAG, "time consumed: " + (System.currentTimeMillis() - time)); + e.onSuccess(drawable); + }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); + } + + /** + * @param needAnim 需要转的动画 + * @param needResult 随机表情是否需要结果 + * @param needGone 动画结束是否需要隐藏 + * @return + */ + public static Single getFaceAnimation(FaceReceiveInfo faceReceiveInfo, Context context, int width, int height,boolean needAnim,boolean needResult,boolean needGone) { + return Single.create((SingleOnSubscribe) e -> { + AnimationDrawable drawable = new AnimationDrawable(); + FaceInfo faceInfo = DynamicFaceModel.get().findFaceInfoById(faceReceiveInfo.getFaceId()); + // 如果找不到对应的表情,直接返回null + if (faceInfo == null) { + e.onError(new Throwable("no face")); + return; + } + int startIndex = faceInfo.getAnimationIndexStart(); + int endIndex = faceInfo.getAnimationIndexEnd(); + int duration = (int) ((faceInfo.getAnimationDuration() + 0.F) / (endIndex - startIndex)); + int repeatCount = faceInfo.getRepeatCount(); + if (needAnim){ + while (repeatCount > 0) { + for (int i = startIndex; i <= endIndex; i++) { + // 增加每一帧到drawable中 + OneFaceDrawable face = new OneFaceDrawable(context, faceInfo.getFacePath(i), width, height); + drawable.addFrame(face, duration); + } + repeatCount--; + } + } + // 如果是普通表情,则直接返回 + if (faceInfo.getResultCount() <= 0) { + drawable.addFrame(new ColorDrawable(Color.TRANSPARENT), 10); + e.onSuccess(drawable); + return; + } + // 如果有结果,增加结果帧 + List resultIndexes = faceReceiveInfo.getResultIndexes(); + duration = faceInfo.getResultDuration(); + if (needResult){ + // 找出所有结果图片的路径 + List images = new ArrayList<>(); + for (int i = 0; i < resultIndexes.size(); i++) { + images.add(faceInfo.getFacePath(resultIndexes.get(i))); + } + // 根据显示类型,产生对应的类型的结果图片 + int displayType = faceInfo.getDisplayType(); + if (displayType == FaceInfo.DISPLAY_TYPE_ONE_PIC || images.size() == 1) { + OneFaceDrawable face = new OneFaceDrawable(context, images.get(0), width, height); + drawable.addFrame(face, duration); + } else if (displayType == FaceInfo.DISPLAY_TYPE_FLOW) { + FlowFaceDrawable flowFaceDrawable = new FlowFaceDrawable(context, images, width, height); + flowFaceDrawable.setBounds(0, 0, width, height); + drawable.addFrame(flowFaceDrawable, duration); + } else if (displayType == FaceInfo.DISPLAY_TYPE_OVERLAY) { + OverlayFaceDrawable overlayFaceDrawable = new OverlayFaceDrawable(context, images, width, height); + overlayFaceDrawable.setBounds(0, 0, width, height); + drawable.addFrame(overlayFaceDrawable, duration); + } else { + // 未知类型,不显示动画 + e.onError(new Throwable("未知类型,不显示动画")); + return; + } + } + if (needGone){ + //隐藏drawable + ColorDrawable colorDrawable = new ColorDrawable(Color.TRANSPARENT); + colorDrawable.setBounds(0, 0, width, height); + drawable.addFrame(new ColorDrawable(Color.TRANSPARENT), 10); + } + e.onSuccess(drawable); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public static Single getSpeakingAnimation(Context context, int maxWidth, int maxHeight, int color, int startRadius) { + return Single.create((SingleOnSubscribe) e -> { + AnimationDrawable drawable = new AnimationDrawable(); + drawable.setOneShot(true); + float frames = 30F; + float halfFrames = frames / 2; + float fixedStep = ((maxWidth - startRadius) / frames); + // 刚开始的透明度(白色刚开始的透明度是200),其他是255 + int startTranslucent = (Color.argb(255, 255, 255, 255) == color) ? 200 : 255; + for (int i = 0; i < frames; i++) { + // int transparent = (255 - i * 5) <= 200 ? 150 : (255 - i * 5); + WavingDrawable wavingDrawable = new WavingDrawable(context, maxWidth, maxHeight, color, + (int) (startRadius + i * fixedStep), 255, ((i + 1) / frames)); + wavingDrawable.setAlpha((i <= halfFrames) ? startTranslucent : (int) ((1 - ((i - halfFrames) / (frames - halfFrames))) * startTranslucent)); + drawable.addFrame(wavingDrawable, 50); + } + drawable.addFrame(new ColorDrawable(Color.TRANSPARENT), 5); + e.onSuccess(drawable); + }) + .subscribeOn(Schedulers.from(ThreadPoolManager.instance().getSpeakExecutor())) + .observeOn(AndroidSchedulers.mainThread()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/FlowFaceDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/anim/FlowFaceDrawable.java new file mode 100644 index 000000000..32bb3be72 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/FlowFaceDrawable.java @@ -0,0 +1,207 @@ +package com.yizhuan.erban.ui.anim; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.bumptech.glide.request.FutureTarget; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用来显示最后一张图片 + * 实现了连贯排列的效果 + * + * @author xiaoyu + * @date 2017/12/1 + */ + +public class FlowFaceDrawable extends Drawable { + + private static final String TAG = "drawable"; + + private class Pair { + private Bitmap bitmap; + private Rect rect; + + Pair(Bitmap bitmap, Rect rect) { + this.bitmap = bitmap; + this.rect = rect; + } + } + + private List images; + private List data; + private Paint mPaint; + private int mWidth; + private int mHeight; + private int mSpaceX; + private int mSpaceY; + private Context mContext; + + FlowFaceDrawable(Context context, List images, int width, int height) { + this.images = images; + this.mWidth = width; + this.mHeight = height; + this.mContext = context; + if (images.size() > 0) { + init(); + } + } + + private static final int RAW_MAX_COUNT = 3; + private static final int COLUMN_MAX_COUNT = 3; + + private void init() { + // 确定每一张图片的位置 + data = new ArrayList<>(); + int size = images.size(); + // 行数 + int rows = size < RAW_MAX_COUNT ? 1 : size < 6 ? 2 : 3; + // 列数 + int columns = size > COLUMN_MAX_COUNT ? COLUMN_MAX_COUNT : size == 1 ? 1 : 2; + int max = Math.max(rows, columns); + float ratio = 1; + + BitmapFactory.Options options = new BitmapFactory.Options(); + for (int i = 0; i < size; i++) { + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(images.get(i), options); + ratio = (max == rows) ? (options.outWidth / (mWidth + 0.F)) * max : (options.outHeight / (mHeight + 0.F)) * max; + int width = (int) (options.outWidth / ratio); + int maxWidth = Utils.dip2px(mContext, 28); + if (width > maxWidth) { + ratio = ratio * (width / (maxWidth + 0.F)); + } + + FutureTarget submit = GlideApp.with(mContext) + .asBitmap() + .dontAnimate() + .dontTransform() + .override(width > maxWidth ? maxWidth : width, (int) (options.outHeight / ratio)) + .load(images.get(i)) + .submit(); + + Bitmap bitmap = null;//Bitmap.createScaledBitmap(originalBitmap, width > maxWidth ? maxWidth : width, (int) (originalBitmap.getHeight() / ratio), true); + try { + bitmap = submit.get(); + } catch (Exception e) { + e.printStackTrace(); + } + Pair pair = new Pair(bitmap, calcRect(bitmap, i)); + data.add(pair); + } + // 留白 + mSpaceX = (mWidth - columns * data.get(0).bitmap.getWidth()) / 2; + mSpaceY = (mHeight - rows * data.get(0).bitmap.getHeight()) / 2; + // 笔 + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); +// LogUtil.e(TAG, "rows: " + rows + " columns: " + columns + ", max: " + max + ", mWidth: " + mWidth + ", mHeight: " + mHeight + +// ", mSpaceX: " + mSpaceX + ", mSpaceY: " + mSpaceY + ", bitmap.getWidth(): " + +// data.get(0).bitmap.getWidth() + ", bitmap.getHeight(): " + data.get(0).bitmap.getHeight() + +// "originalBitmap.getWidth(): " + originalBitmap.getWidth() + ", originalBitmap.getHeight(): " + originalBitmap.getHeight()); + } + + private Rect calcRect(Bitmap bitmap, int pos) { + int size = images.size(); + Rect rect = new Rect(); + switch (size) { + case 1: + rect.left = 0; + rect.top = 0; + rect.right = bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + break; + case 2: + rect.left = pos * bitmap.getWidth(); + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + break; + case 3: + if (pos == 0) { + rect.left = bitmap.getWidth() / 2; + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + } else { + rect.left = (pos - 1) * bitmap.getWidth(); + rect.top = bitmap.getHeight(); + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = rect.top + bitmap.getHeight(); + } + break; + case 4: + if (pos < 2) { + rect.left = pos * bitmap.getWidth(); + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + } else { + rect.left = (pos - 2) * bitmap.getWidth(); + rect.top = bitmap.getHeight(); + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = rect.top + bitmap.getHeight(); + } + break; + case 5: + if (pos < 2) { + rect.left = bitmap.getWidth() / 2 + (pos * bitmap.getWidth()); + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + } else { + rect.left = (pos - 2) * bitmap.getWidth(); + rect.top = bitmap.getHeight(); + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = rect.top + bitmap.getHeight(); + } + break; + default: + } + return rect; + } + + @Override + public void draw(@NonNull Canvas canvas) { + for (int i = 0; i < data.size(); i++) { + canvas.drawBitmap(data.get(i).bitmap, mSpaceX + data.get(i).rect.left, mSpaceY + data.get(i).rect.top, mPaint); + } + } + + @Override + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/FrameAnimation.java b/app/src/main/java/com/yizhuan/erban/ui/anim/FrameAnimation.java new file mode 100644 index 000000000..b2a8b09f7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/FrameAnimation.java @@ -0,0 +1,333 @@ +package com.yizhuan.erban.ui.anim; + +import android.graphics.drawable.Drawable; +import android.widget.ImageView; + +import java.util.List; + +/** + * Created by Ansen on 2015/5/14 23:30. + * + * @E-mail: ansen360@126.com + * @Blog: http://blog.csdn.net/qq_25804863 + * @Github: https://github.com/ansen360 + * @PROJECT_NAME: FrameAnimation + * @PACKAGE_NAME: com.ansen.frameanimation.sample + * @Description: TODO + */ +public class FrameAnimation { + + private boolean mIsRepeat; + + private AnimationListener mAnimationListener; + + private ImageView mImageView; + + private List mFrameRess; + + /** + * 每帧动画的播放间隔数组 + */ + private int[] mDurations; + + /** + * 每帧动画的播放间隔 + */ + private int mDuration; + + /** + * 下一遍动画播放的延迟时间 + */ + private int mDelay; + + private int mLastFrame; + + private boolean mNext; + + private boolean mPause; + + private int mCurrentSelect; + + private int mCurrentFrame; + + private static final int SELECTED_A = 1; + + private static final int SELECTED_B = 2; + + private static final int SELECTED_C = 3; + + private static final int SELECTED_D = 4; + + + /** + * @param iv 播放动画的控件 + * @param frameRes 播放的图片数组 + * @param duration 每帧动画的播放间隔(毫秒) + * @param isRepeat 是否循环播放 + */ + public FrameAnimation(ImageView iv, List frameRes, int duration, boolean isRepeat) { + this.mImageView = iv; + this.mFrameRess = frameRes; + this.mDuration = duration; + this.mLastFrame = frameRes.size() - 1; + this.mIsRepeat = isRepeat; + play(0); + } + + /** + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param durations 每帧动画的播放间隔(毫秒) + * @param isRepeat 是否循环播放 + */ + public FrameAnimation(ImageView iv, List frameRess, int[] durations, boolean isRepeat) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDurations = durations; + this.mLastFrame = frameRess.size() - 1; + this.mIsRepeat = isRepeat; + playByDurations(0); + } + + /** + * 循环播放动画 + * + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param duration 每帧动画的播放间隔(毫秒) + * @param delay 循环播放的时间间隔 + */ + public FrameAnimation(ImageView iv, List frameRess, int duration, int delay) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDuration = duration; + this.mDelay = delay; + this.mLastFrame = frameRess.size() - 1; + playAndDelay(0); + } + + /** + * 循环播放动画 + * + * @param iv 播放动画的控件 + * @param frameRess 播放的图片数组 + * @param durations 每帧动画的播放间隔(毫秒) + * @param delay 循环播放的时间间隔 + */ + public FrameAnimation(ImageView iv, List frameRess, int[] durations, int delay) { + this.mImageView = iv; + this.mFrameRess = frameRess; + this.mDurations = durations; + this.mDelay = delay; + this.mLastFrame = frameRess.size() - 1; + playByDurationsAndDelay(0); + } + + private void playByDurationsAndDelay(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { // 暂停和播放需求 + mCurrentSelect = SELECTED_A; + mCurrentFrame = i; + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackground(mFrameRess.get(i)); + if (i == mLastFrame) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + mNext = true; + playByDurationsAndDelay(0); + } else { + playByDurationsAndDelay(i + 1); + } + } + }, mNext && mDelay > 0 ? mDelay : mDurations[i]); + + } + + private void playAndDelay(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_B; + mCurrentFrame = i; + return; + } + return; + } + mNext = false; + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackground(mFrameRess.get(i)); + if (i == mLastFrame) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + mNext = true; + playAndDelay(0); + } else { + playAndDelay(i + 1); + } + } + }, mNext && mDelay > 0 ? mDelay : mDuration); + + } + + private void playByDurations(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_C; + mCurrentFrame = i; + return; + } + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackground(mFrameRess.get(i)); + if (i == mLastFrame) { + if (mIsRepeat) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + playByDurations(0); + } else { + if (mAnimationListener != null) { + mAnimationListener.onAnimationEnd(); + } + } + } else { + + playByDurations(i + 1); + } + } + }, mDurations[i]); + + } + + private void play(final int i) { + mImageView.postDelayed(new Runnable() { + + @Override + public void run() { + if (mPause) { + if (mPause) { + mCurrentSelect = SELECTED_D; + mCurrentFrame = i; + return; + } + return; + } + if (0 == i) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationStart(); + } + } + mImageView.setBackground(mFrameRess.get(i)); + if (i == mLastFrame) { + + if (mIsRepeat) { + if (mAnimationListener != null) { + mAnimationListener.onAnimationRepeat(); + } + play(0); + } else { + if (mAnimationListener != null) { + mAnimationListener.onAnimationEnd(); + } + } + + } else { + + play(i + 1); + } + } + }, mDuration); + } + + public static interface AnimationListener { + + /** + *

Notifies the start of the animation.

+ */ + void onAnimationStart(); + + /** + *

Notifies the end of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.

+ */ + void onAnimationEnd(); + + /** + *

Notifies the repetition of the animation.

+ */ + void onAnimationRepeat(); + } + + /** + *

Binds an animation listener to this animation. The animation listener + * is notified of animation events such as the end of the animation or the + * repetition of the animation.

+ * + * @param listener the animation listener to be notified + */ + public void setAnimationListener(AnimationListener listener) { + this.mAnimationListener = listener; + } + + public void release() { + pauseAnimation(); + } + + public void pauseAnimation() { + this.mPause = true; + } + + public boolean isPause() { + return this.mPause; + } + + public void restartAnimation() { + if (mPause) { + mPause = false; + switch (mCurrentSelect) { + case SELECTED_A: + playByDurationsAndDelay(mCurrentFrame); + break; + case SELECTED_B: + playAndDelay(mCurrentFrame); + break; + case SELECTED_C: + playByDurations(mCurrentFrame); + break; + case SELECTED_D: + play(mCurrentFrame); + break; + default: + break; + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/OneFaceDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/anim/OneFaceDrawable.java new file mode 100644 index 000000000..070e3360c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/OneFaceDrawable.java @@ -0,0 +1,130 @@ +package com.yizhuan.erban.ui.anim; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import com.bumptech.glide.request.FutureTarget; +import com.netease.nim.uikit.support.glide.GlideApp; + +/** + * 用来显示一张图片 + * + * @author xiaoyu + * @date 2017/12/1 + */ + +public class OneFaceDrawable extends Drawable { + + private static final String TAG = "OneFaceDrawable"; + private float ratio; + + private class Pair { + private Bitmap bitmap; + private Rect rect; + + Pair(Bitmap bitmap, Rect rect) { + this.bitmap = bitmap; + this.rect = rect; + } + } + + private String image; + private Pair pair; + private Paint mPaint; + private int mWidth; + private int mHeight; + private int mSpaceX; + private int mSpaceY; + private Context mContext; + + OneFaceDrawable(Context context, String image, int width, int height) { + this.image = image; + this.mWidth = width; + this.mHeight = height; + this.mContext = context; + if (!TextUtils.isEmpty(image)) { + init(); + } + } + + private void init() { + // 确定一张图片的位置 + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(image, options); + + float ratioX = (mWidth + 0.F) / options.outWidth;//originalBitmap.getWidth(); + float ratioY = (mHeight + 0.F) / options.outHeight;//originalBitmap.getHeight(); + ratio = ratioX > ratioY ? ratioY : ratioX; + FutureTarget submit = GlideApp.with(mContext) + .asBitmap() + .dontTransform() + .dontAnimate() + .override((int) (options.outWidth * ratio), (int) (options.outHeight * ratio)) + .load(image) + .submit(); + Bitmap bitmap = null;//Bitmap.createScaledBitmap(originalBitmap, (int) (originalBitmap.getWidth() * ratio), (int) (originalBitmap.getHeight() * ratio), true); + try { + bitmap = submit.get(); + } catch (Exception e) { + e.printStackTrace(); + } + if (bitmap == null) return; + pair = new Pair(bitmap, calcRect(bitmap)); + // 留白 + mSpaceX = (mWidth - bitmap.getWidth()) / 2; + mSpaceY = (mHeight - bitmap.getHeight()) / 2; + // 笔 + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + + private Rect calcRect(Bitmap bitmap) { + Rect rect = new Rect(); + rect.left = 0; + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + return rect; + } + + @Override + public void draw(@NonNull Canvas canvas) { + if (pair == null || pair.bitmap == null) return; + canvas.drawBitmap(pair.bitmap, mSpaceX + pair.rect.left, mSpaceY + pair.rect.top, mPaint); + } + + @Override + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/OverlayFaceDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/anim/OverlayFaceDrawable.java new file mode 100644 index 000000000..4882b6495 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/OverlayFaceDrawable.java @@ -0,0 +1,155 @@ +package com.yizhuan.erban.ui.anim; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.bumptech.glide.request.FutureTarget; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用来显示最后一张图片 + * 实现了连贯排列的效果 + * + * @author xiaoyu + * @date 2017/12/1 + */ + +public class OverlayFaceDrawable extends Drawable { + + private static final String TAG = "drawable"; + private float ratio; + + private class Pair { + private Bitmap bitmap; + private Rect rect; + + Pair(Bitmap bitmap, Rect rect) { + this.bitmap = bitmap; + this.rect = rect; + } + } + + private List images; + private List data; + private Paint mPaint; + private int mWidth; + private int mHeight; + private int mSpaceX; + private int mSpaceY; + private Context mContext; + + OverlayFaceDrawable(Context context, List images, int width, int height) { + this.images = images; + this.mWidth = width; + this.mHeight = height; + this.mContext = context; + if (images.size() > 1) { + init(); + } + } + + private static final float RATIO_MAX = 0.5F; + + private void init() { + // 确定每一张图片的位置 + data = new ArrayList<>(); + int size = images.size(); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(images.get(0), options); + // 高度最大不超过35dp + int maxHeight = Utils.dip2px(mContext, 35); + int targetHeight = maxHeight > options.outHeight ? options.outHeight : maxHeight; + float scale = targetHeight / (options.outHeight + 0.F); + int targetWidth = (int) (scale * options.outWidth); + ratio = RATIO_MAX; + // 算出overlay为0.5F的时候宽度相当于几张图片的大小 + int count = (int) (size / 2.F + 0.5F); + if (count * targetWidth > mWidth) { + // 如果overlay为0.5F的时候显示的总宽度大于mWidth,则需要计算出他可以显示的overlay的比例 + int canShownWidth = (mWidth - targetWidth) / (size - 1); + ratio = (canShownWidth + 0.F) / targetWidth; + } + for (int i = 0; i < size; i++) { + //originalBitmap = BitmapFactory.decodeFile(images.get(i)); + FutureTarget submit = GlideApp.with(mContext) + .asBitmap() + .dontAnimate() + .dontTransform() + .override(targetWidth, targetHeight) + .load(images.get(i)) + .submit(); + Bitmap bitmap = null;//Bitmap.createScaledBitmap(originalBitmap, targetWidth, targetHeight, true); + try { + bitmap = submit.get(); + } catch (Exception e) { + e.printStackTrace(); + } + Pair pair = new Pair(bitmap, calcRect(bitmap, i)); + data.add(pair); + } + // 留白 + mSpaceX = (int) ((mWidth - (targetWidth * ((size - 1) * ratio + 1))) / 2); + mSpaceY = (mHeight - targetHeight) / 2; + // 笔 + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); +// LogUtil.e(TAG, mWidth + ", mHeight: " + mHeight + ", count: " + count + ", ratio: " + ratio + +// ", mSpaceX: " + mSpaceX + ", mSpaceY: " + mSpaceY + ", bitmap.getWidth(): " + +// data.get(0).bitmap.getWidth() + ", bitmap.getHeight(): " + data.get(0).bitmap.getHeight() + +// ", originalBitmap.getWidth(): " + originalBitmap.getWidth() + ", originalBitmap.getHeight(): " + originalBitmap.getHeight()); + } + + private Rect calcRect(Bitmap bitmap, int pos) { + Rect rect = new Rect(); + rect.left = (int) (pos * ratio * bitmap.getWidth()); + rect.top = 0; + rect.right = rect.left + bitmap.getWidth(); + rect.bottom = bitmap.getHeight(); + return rect; + } + + @Override + public void draw(@NonNull Canvas canvas) { + for (int i = 0; i < data.size(); i++) { + canvas.drawBitmap(data.get(i).bitmap, mSpaceX + data.get(i).rect.left, mSpaceY + data.get(i).rect.top, mPaint); + } + } + + @Override + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/anim/WavingDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/anim/WavingDrawable.java new file mode 100644 index 000000000..46959c1c3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/anim/WavingDrawable.java @@ -0,0 +1,107 @@ +package com.yizhuan.erban.ui.anim; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.ui.widget.marqueeview.Utils; + +/** + * @author xiaoyu + * @date 2018/1/15 + */ + +public class WavingDrawable extends Drawable { + + private final Paint mPaint; + private final Context context; + private RadialGradient mRadialGradient; + private int maxWidth; + private int maxHeight; + private int strokeWidth; + private int color; + private int startRadius; + private int transparent; + private float ratio; + + public WavingDrawable(Context context, int maxWidth, int maxHeight, int color, int startRadius, int transparent, float ratio) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + strokeWidth = Utils.dip2px(context, 2.4F); + mPaint.setStrokeWidth(strokeWidth); + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this.color = color; + this.context = context; + this.startRadius = startRadius / 2; + this.transparent = transparent; + this.ratio = ratio; + } + + @Override + public void draw(@NonNull Canvas canvas) { + if (mRadialGradient == null) { + int x = maxWidth / 2; + int y = maxHeight / 2; + // 内环 + strokeWidth = Utils.dip2px(context, 1.8F); + int startRealColor = Color.argb(200, (color & 0x00FF0000) >> 16, (color & 0x0000FF00) >> 8, color & 0x000000FF); + int endRealColor = Color.argb(255, (color & 0x00FF0000) >> 16, (color & 0x0000FF00) >> 8, color & 0x000000FF); + mPaint.setStyle(Paint.Style.FILL); + mRadialGradient = new RadialGradient(x, y, startRadius, startRealColor, endRealColor, Shader.TileMode.CLAMP); + mPaint.setShader(mRadialGradient); + canvas.drawCircle(x, y, startRadius, mPaint); + // 外环 +// if (ratio <= 0.3F) return; +// strokeWidth = Utils.dip2px(context, 2.4F); +// int realColor = Color.argb(255, (color & 0x00FF0000) >> 16, (color & 0x0000FF00) >> 8, color & 0x000000FF); +// mPaint.setStyle(Paint.Style.FILL); +// mRadialGradient = new RadialGradient(x, y, (ratio - 0.3F) * strokeWidth, realColor, realColor, Shader.TileMode.CLAMP); +// mPaint.setShader(mRadialGradient); +// canvas.drawCircle(x, y, startRadius + (ratio - 0.3F) * strokeWidth > getIntrinsicWidth() / 2 ? +// getIntrinsicWidth() / 2 : startRadius + (ratio - 0.3F) * strokeWidth, mPaint); + } + } + + @Override + public int getIntrinsicWidth() { + return maxWidth; + } + + @Override + public int getIntrinsicHeight() { + return maxHeight; + } + + @Override + public int getMinimumHeight() { + return Utils.dip2px(context, 55F); + } + + @Override + public int getMinimumWidth() { + return Utils.dip2px(context, 55F); + } + + @Override + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/bean/BaseResponse.java b/app/src/main/java/com/yizhuan/erban/ui/bean/BaseResponse.java new file mode 100644 index 000000000..5fd1005cd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/bean/BaseResponse.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.ui.bean; + + +/** + * Created by hyman on 2016/8/2. + */ +public class BaseResponse { + private int code; + private String msg; + + public BaseResponse() { + } + + public BaseResponse(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/bean/Footer.java b/app/src/main/java/com/yizhuan/erban/ui/bean/Footer.java new file mode 100644 index 000000000..0c443bb97 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/bean/Footer.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.ui.bean; + +/** + * Created by zhouxiangfeng on 2017/4/30. + */ + +public class Footer { +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/bean/FooterLoadMoreBean.java b/app/src/main/java/com/yizhuan/erban/ui/bean/FooterLoadMoreBean.java new file mode 100644 index 000000000..fb33cd8c4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/bean/FooterLoadMoreBean.java @@ -0,0 +1,16 @@ +package com.yizhuan.erban.ui.bean; + + + +/** + * Created by wanli on 2016/10/27. + */ + +public class FooterLoadMoreBean { + public int LayId; + public String desc; + + public FooterLoadMoreBean() { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/bean/header.java b/app/src/main/java/com/yizhuan/erban/ui/bean/header.java new file mode 100644 index 000000000..cbaa49edf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/bean/header.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.ui.bean; + +/** + * Created by zhouxiangfeng on 2017/4/30. + */ + +public class header { +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/behavior/FixAppBarBehavior.java b/app/src/main/java/com/yizhuan/erban/ui/behavior/FixAppBarBehavior.java new file mode 100644 index 000000000..51d1f4834 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/behavior/FixAppBarBehavior.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.behavior; + +import android.content.Context; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CoordinatorLayout; +import android.support.v4.view.ViewCompat; +import android.util.AttributeSet; +import android.view.View; + +/** + * 此文件不能删,引用到AppLayout下面的 + * create by lvzebiao @2020/1/7 + */ +public class FixAppBarBehavior extends AppBarLayout.Behavior { + + public FixAppBarBehavior() { + } + + public FixAppBarBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int + dxUnconsumed, int dyUnconsumed, int type) { + super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); + stopNestedScrollIfNeeded(dyUnconsumed, child, target, type); + } + + @Override + public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { + super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); + stopNestedScrollIfNeeded(dy, child, target, type); + } + + + private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) { + if (type == ViewCompat.TYPE_NON_TOUCH) { + final int currOffset = getTopAndBottomOffset(); + if ((dy < 0 && currOffset == 0) + || (dy > 0 && currOffset == -child.getTotalScrollRange())) { + ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH); + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceGVAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceGVAdapter.java new file mode 100644 index 000000000..735a2c07e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceGVAdapter.java @@ -0,0 +1,142 @@ +package com.yizhuan.erban.ui.gift.adapter; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.gift.util.RecyclerViewUtil; +import com.yizhuan.erban.ui.gift.widget.GiftDataInfo; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; + +import java.io.IOException; +import java.util.List; + +public class FaceGVAdapter extends RecyclerView.Adapter { + private List list; + private RecyclerView mRecyclerView; + private Context mContext; + private boolean isNetData; + + private ViewHodler mHolder; + private int clickTemp = -1; + private RecyclerViewUtil recyclerViewUtil; + + //标识选择的Item + public void setSeclection(int position) { + clickTemp = position; + } + + public int getSecletion() { + return clickTemp; + } + + public FaceGVAdapter(RecyclerView recyclerView, List list, Context mContext, boolean isNetData) { + super(); + this.mRecyclerView = recyclerView; + this.list = list; + this.mContext = mContext; + this.isNetData = isNetData; + recyclerViewClickListenter(list, mContext); + } + + private void recyclerViewClickListenter(final List list, Context mContext) { + recyclerViewUtil = new RecyclerViewUtil(mContext, mRecyclerView); + recyclerViewUtil.setOnItemClickListener(new RecyclerViewUtil.OnItemClickListener() { + + private LinearLayout llroot; + + @Override + public void onItemClick(int position, View view) { + if (mOnItemClickListener != null) { + final GiftDataInfo giftDataInfo = list.get(position); + mOnItemClickListener.onItemClick(view, giftDataInfo, position); + if (llroot == null) { + llroot = (LinearLayout) view.findViewById(R.id.ll_gift_root); + } + llroot.setBackgroundResource(R.drawable.shape_gift_chose); + clickTemp = position; + notifyDataSetChanged(); + } + } + }); + } + + public void clear() { + this.mContext = null; + } + + @Override + public ViewHodler onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.face_image, parent, false); + return new ViewHodler(view); + } + + @Override + public void onBindViewHolder(final ViewHodler holder, final int position) { + final GiftDataInfo giftDataInfo = list.get(position); + if (isNetData) { + ImageLoadUtils.loadImage(mContext, giftDataInfo.getGiftPic(), holder.giftImg); + } else { + try { + Bitmap mBitmap = BitmapFactory.decodeStream(mContext.getAssets().open(giftDataInfo.getGiftName())); + holder.giftImg.setImageBitmap(mBitmap); + } catch (IOException e) { + e.printStackTrace(); + } + } + + holder.giftName.setText(giftDataInfo.getGiftName()); + holder.giftPrice.setText(giftDataInfo.getGiftPrice()); + if (clickTemp == position) { + holder.llroot.setBackgroundResource(R.drawable.shape_gift_chose); + mHolder = holder; + } else { + holder.llroot.setBackgroundResource(R.drawable.shape_gift_tran); + } + } + + @Override + public int getItemCount() { + return list.size(); + } + + public void clearSelection() { + if (mHolder != null) { + mHolder.llroot.setBackgroundResource(R.drawable.shape_gift_tran); + mHolder = null; + } + } + + class ViewHodler extends RecyclerView.ViewHolder { + LinearLayout llroot; + ImageView giftImg; + TextView giftName; + TextView giftPrice; + + public ViewHodler(View view) { + super(view); + llroot = (LinearLayout) view.findViewById(R.id.ll_gift_root); + giftImg = (ImageView) view.findViewById(R.id.face_img); + giftName = (TextView) view.findViewById(R.id.face_name); + giftPrice = (TextView) view.findViewById(R.id.face_price); + } + } + + public interface OnItemClickListener { + void onItemClick(View view, GiftDataInfo giftDataInfo, int position); + } + + public OnItemClickListener mOnItemClickListener; + + public void setOnItemClickListener(OnItemClickListener listener) { + mOnItemClickListener = listener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceVPAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceVPAdapter.java new file mode 100644 index 000000000..da459c398 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/adapter/FaceVPAdapter.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.ui.gift.adapter; + +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; + +import java.util.List; + +public class FaceVPAdapter extends PagerAdapter { + + // 界面列表 + private List views; + + public FaceVPAdapter(List views) { + this.views = views; + } + + @Override + public int getCount() { + return views != null ? views.size() : 0; + } + + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + container.addView(views.get(position), 0); + return views.get(position); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView(views.get(position)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/callback/OnGiftDialogBtnClickListenerWrapper.java b/app/src/main/java/com/yizhuan/erban/ui/gift/callback/OnGiftDialogBtnClickListenerWrapper.java new file mode 100644 index 000000000..9815b57f8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/callback/OnGiftDialogBtnClickListenerWrapper.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.ui.gift.callback; + +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; + +import java.util.List; + +public class OnGiftDialogBtnClickListenerWrapper implements GiftDialog.OnGiftDialogBtnClickListener { + @Override + public void onSendGiftBtnClick(GiftInfo giftInfo, List micMemberInfos, int number, String msg, boolean isKnap, boolean isWholeMic, GiftDialog.SenGiftCallback callback) { + + } + + @Override + public void onSendMagicBtnClick(MagicInfo magicInfo, long targetUid, GiftDialog.SenGiftCallback callback) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftGridView.java b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftGridView.java new file mode 100644 index 000000000..4a065c6fd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftGridView.java @@ -0,0 +1,175 @@ +package com.yizhuan.erban.ui.gift.dialog; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.BR; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_library.bindinglist.IItem; +import com.yizhuan.xchat_android_library.bindinglist.MultiTypeAdapter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 在这里统一处理礼物分页展示的逻辑 + * 同时支持礼物和魔法不同的bean,减少代码冗余 + * Created by lvzebiao on 2018/11/20. + */ + +public class GiftGridView extends ViewPager { + + private List> pagerList; + /** + * 一页数据的数量 + */ + private int PAGE_SIZE = 8; + + private OnItemClickListener listener; + + private IItem LastSelectedItem; + + public GiftGridView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public List> getPagerList() { + return pagerList; + } + + public void setPageSize(int pageSize) { + this.PAGE_SIZE = pageSize; + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + + public void setGiftData(Context context, List data, boolean isKnap) { + pagerList = beanTransformVm(context, data, isKnap, PAGE_SIZE); + initView(context); + } + + public void setMagicData(Context context, List data) { + pagerList = beanTransformVm(context, data, false, PAGE_SIZE); + initView(context); + } + + private void initView(final Context context) { + LastSelectedItem = null; + if (ListUtils.isListEmpty(pagerList)) { + return; + } + SparseArray cacheItemView = new SparseArray<>(); + setAdapter(new PagerAdapter() { + @Override + public int getCount() { + return pagerList.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int pagePos) { + RecyclerView recyclerView; + MultiTypeAdapter giftAdapter; + if (cacheItemView.get(pagePos) == null) { + recyclerView = new RecyclerView(context); + recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + recyclerView.setLayoutManager(new GridLayoutManager(context, 4)); + giftAdapter = new MultiTypeAdapter(BR.item, true); + recyclerView.setAdapter(giftAdapter); + cacheItemView.put(pagePos, recyclerView); + } else { + recyclerView = cacheItemView.get(pagePos); + giftAdapter = (MultiTypeAdapter) recyclerView.getAdapter(); + } + giftAdapter.clearAllItem(); + giftAdapter.addData(pagerList.get(pagePos)); + giftAdapter.setOnItemClickListener(item -> { + if (item instanceof GiftInfoVm) { + GiftInfoVm giftInfoVm = (GiftInfoVm) item; + if (LastSelectedItem != null) { + if (LastSelectedItem instanceof GiftInfoVm) { + ((GiftInfoVm) LastSelectedItem).isSelect.set(false); + } + } + giftInfoVm.isSelect.set(true); + LastSelectedItem = item; + } + if (listener != null) { + listener.onClick(item); + } + }); + return recyclerView; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + RecyclerView recyclerView = cacheItemView.get(position); + MultiTypeAdapter adapter = (MultiTypeAdapter) recyclerView.getAdapter(); + adapter.getAllItems().clear(); + container.removeView(recyclerView); + } + }); + } + + public interface OnItemClickListener { + void onClick(IItem item); + } + + public static List> beanTransformVm(Context context, List data, boolean isKnap, int pageSize) { + List> result = new ArrayList<>(); + if (ListUtils.isListEmpty(data)) { + return result; + } + for (int i = 0; i < data.size(); i++) { + IItem item = null; + List page = null; + if (i % pageSize == 0) { + page = new ArrayList<>(); + result.add(page); + } else { + if (result.size() > 0) { + page = result.get(result.size() - 1); + } + } + if (data.get(i) instanceof GiftInfo) { + item = createGiftItem(context, (GiftInfo) data.get(i), i == 0, isKnap); + } else if (data.get(i) instanceof MagicInfo) { + item = createMagicItem(context, (MagicInfo) data.get(i), i == 0); + } + Logger.i("pos:" + i + ", item:" + item + ", page:" + page); + if (item != null && page != null) { + page.add(item); + } + } + return result; + } + + public static GiftInfoVm createGiftItem(Context context, GiftInfo giftInfo, boolean select, boolean isKnap) { + return new GiftInfoVm(context, giftInfo, select, isKnap); + } + + public static MagicInfoVm createMagicItem(Context context, MagicInfo magicInfo, boolean select) { + return new MagicInfoVm(context, magicInfo, select); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftInfoVm.java b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftInfoVm.java new file mode 100644 index 000000000..e27e46bf5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/GiftInfoVm.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.ui.gift.dialog; + +import android.content.Context; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.graphics.drawable.Drawable; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_library.bindinglist.BaseItem; + +/** + * 礼物item + * Created by lvzebiao on 2018/11/19. + */ + +public class GiftInfoVm extends BaseItem { + + public final ObservableBoolean isSelect = new ObservableBoolean(); + + public final ObservableField goldText = new ObservableField<>(); + + public final ObservableBoolean isKnap = new ObservableBoolean(); + + public final ObservableField countText = new ObservableField<>(); + + public Drawable nobleDrawable = null; + + public Drawable radishDrawable = null; + + public Drawable radishDrawableSelected = null; + + /** + * 是否显示新 + */ + public boolean isShowNew = false; + + /** + * 显示限定 + */ + public boolean isShowLimit = false; + + /** + * 显示特定 + */ + public boolean isShowEffect = false; + + /** + * 是否显示专属礼物 + */ + public boolean isExclusive = false; + + @Override + public GiftInfo data() { + return super.data(); + } + + public GiftInfoVm(Context context, GiftInfo data, boolean select, boolean isKnap) { + super(context, data); + this.isSelect.set(select); + if (data.getConsumeType() == GiftInfo.CONSUME_TYPE_GOLD) { + radishDrawable = null; + radishDrawableSelected = null; + goldText.set(context.getResources().getString(R.string.how_much_gold, data.getGoldPrice())); + } else { + radishDrawable = context.getResources().getDrawable(R.drawable.icon_radish_transparent); + radishDrawableSelected = context.getResources().getDrawable(R.drawable.icon_radish_transparent_selected); + goldText.set(String.valueOf(data.getGoldPrice())); +// goldText.set(context.getResources().getString(R.string.how_much_radish, data.getGoldPrice())); + } + this.isKnap.set(isKnap); + updateCount(); + int nobleId = data.getLevel(); + if (nobleId == 0) { + // 普通表情 + nobleDrawable = null; + } else { + int drawableId = nobleId == 1 ? R.drawable.ic_tag_1 : nobleId == 2 ? R.drawable.ic_tag_2 : nobleId == 3 ? + R.drawable.ic_tag_3 : nobleId == 4 ? R.drawable.ic_tag_4 : nobleId == 5 ? R.drawable.ic_tag_5 : nobleId == 6 ? + R.drawable.ic_tag_6 : nobleId == 7 ? R.drawable.ic_tag_7 : 0; + nobleDrawable = context.getResources().getDrawable(drawableId); + } + isShowNew = data.isHasLatest() && nobleId == 0; + isShowLimit = data.isHasTimeLimit() && nobleId == 0; + isShowEffect = data.isHasEffect() && nobleId == 0; + isExclusive = data.isRoomExclude() && nobleId == 0; + } + + @Override + public int getType() { + return R.layout.list_item_dialog_gift; + } + + public void updateCount() { + this.countText.set("x" + data.getCount()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/MagicInfoVm.java b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/MagicInfoVm.java new file mode 100644 index 000000000..e66d0e746 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/MagicInfoVm.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.ui.gift.dialog; + +import android.content.Context; +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_library.bindinglist.BaseItem; + +/** + * 魔法 + * Created by lvzebiao on 2018/11/20. + */ + +public class MagicInfoVm extends BaseItem { + + public final ObservableBoolean isSelect = new ObservableBoolean(); + + public final ObservableField goldText = new ObservableField<>(); + + @Override + public MagicInfo data() { + return super.data(); + } + + public MagicInfoVm(Context context, MagicInfo data, boolean select) { + super(context, data); + this.isSelect.set(select); + this.goldText.set(data.getPrice() + "金币"); + } + + @Override + public int getType() { + return R.layout.list_item_dialog_magic; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/PageIndicatorView.java b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/PageIndicatorView.java new file mode 100644 index 000000000..126517bdf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/dialog/PageIndicatorView.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.ui.gift.dialog; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by shichaohui on 2015/7/10 0010. + *

+ * 页码指示器类,获得此类实例后,可通过{@link PageIndicatorView#initIndicator(int)}方法初始化指示器 + *

+ */ +public class PageIndicatorView extends LinearLayout { + + private Context mContext = null; + private int dotSize = 6; // 指示器的大小(dp) + private int height = 6; // 指示器的大小(dp) + private double margins = 5; // 指示器间距(dp) + private List indicatorViews = null; // 存放指示器 + private int selectRes = R.drawable.shape_indicator_present_visible; + private int noSelectRes = R.drawable.shape_indicator_present_invisible; + + public void setSelectRes(int selectRes) { + this.selectRes = selectRes; + } + + public void setNoSelectRes(int noSelectRes) { + this.noSelectRes = noSelectRes; + } + + public PageIndicatorView(Context context) { + this(context, null); + } + + public PageIndicatorView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PageIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + this.mContext = context; + + setGravity(Gravity.CENTER); + setOrientation(HORIZONTAL); + + dotSize = UIUtil.dip2px(context, dotSize); + height = UIUtil.dip2px(context, height); + margins = UIUtil.dip2px(context, (float) margins); + } + + public void setDotSize(int dotSize) { + this.dotSize = dotSize; + } + + public void setHeight(int height) { + this.height = height; + } + + /** + * 初始化指示器,默认选中第一页 + * + * @param count 指示器数量,即页数 + */ + public void initIndicator(int count) { + if (indicatorViews == null) { + indicatorViews = new ArrayList<>(); + } + indicatorViews.clear(); + removeAllViews(); + View view; + LayoutParams params = new LayoutParams(dotSize, height); + int margins = (int) this.margins; + params.setMargins(margins, margins, margins, margins); + for (int i = 0; i < count; i++) { + view = new View(mContext); + view.setBackgroundResource(noSelectRes); + addView(view, params); + indicatorViews.add(view); + } + if (indicatorViews.size() > 0) { + indicatorViews.get(0).setBackgroundResource(selectRes); + } + } + + /** + * 设置选中页 + * + * @param selected 页下标,从0开始 + */ + public void setSelectedPage(int selected) { + for (int i = 0; i < indicatorViews.size(); i++) { + if (i == selected) { + indicatorViews.get(i).setBackgroundResource(selectRes); + } else { + indicatorViews.get(i).setBackgroundResource(noSelectRes); + } + } + } + + /** + * 设置选中页 + * + * @param selected 页下标,从0开始 + */ + public void setDifSelectedPage(int selected) { + for (int i = 0; i < indicatorViews.size(); i++) { + if (i == selected) { + LayoutParams params = new LayoutParams(dotSize, height); + int margins = (int) this.margins; + params.setMargins(margins, margins, margins, margins); + indicatorViews.get(i).setLayoutParams(params); + indicatorViews.get(i).setBackgroundResource(selectRes); + } else { + LayoutParams params = new LayoutParams(height, height); + indicatorViews.get(i).setLayoutParams(params); + indicatorViews.get(i).setBackgroundResource(noSelectRes); + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedGifDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedGifDrawable.java new file mode 100644 index 000000000..33ec76495 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedGifDrawable.java @@ -0,0 +1,64 @@ +package com.yizhuan.erban.ui.gift.gif; + +import android.graphics.Bitmap; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +import java.io.InputStream; + +public class AnimatedGifDrawable extends AnimationDrawable { + + private int mCurrentIndex = 0; + private UpdateListener mListener; + + public AnimatedGifDrawable(InputStream source, UpdateListener listener) { + mListener = listener; + GifDecoder decoder = new GifDecoder(); + decoder.read(source); + // Iterate through the gif frames, add each as animation frame + for (int i = 0; i < decoder.getFrameCount(); i++) { + Bitmap bitmap = decoder.getFrame(i); + BitmapDrawable drawable = new BitmapDrawable(bitmap); + // Explicitly set the bounds in order for the frames to display + drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); + addFrame(drawable, decoder.getDelay(i)); + if (i == 0) { + // Also set the bounds for this container drawable + setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); + } + } + } + + /** + * Naive method to proceed to next frame. Also notifies listener. + */ + public void nextFrame() { + mCurrentIndex = (mCurrentIndex + 1) % getNumberOfFrames(); + if (mListener != null) + mListener.update(); + } + + /** + * Return display duration for current frame + */ + public int getFrameDuration() { + return getDuration(mCurrentIndex); + } + + /** + * Return drawable for current frame + */ + public Drawable getDrawable() { + return getFrame(mCurrentIndex); + } + + /** + * Interface to notify listener to update/redraw Can't figure out how to + * invalidate the drawable (or span in which it sits) itself to force redraw + */ + public interface UpdateListener { + void update(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedImageSpan.java b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedImageSpan.java new file mode 100644 index 000000000..287990601 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/AnimatedImageSpan.java @@ -0,0 +1,78 @@ +package com.yizhuan.erban.ui.gift.gif; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.text.style.DynamicDrawableSpan; + +public class AnimatedImageSpan extends DynamicDrawableSpan { + + private Drawable mDrawable; + + public AnimatedImageSpan(Drawable d) { + super(); + mDrawable = d; + // Use handler for 'ticks' to proceed to next frame + final Handler mHandler = new Handler(); + mHandler.post(new Runnable() { + public void run() { + ((AnimatedGifDrawable)mDrawable).nextFrame(); + // Set next with a delay depending on the duration for this frame + mHandler.postDelayed(this, ((AnimatedGifDrawable)mDrawable).getFrameDuration()); + } + }); + } + + /* + * Return current frame from animated drawable. Also acts as replacement for super.getCachedDrawable(), + * since we can't cache the 'image' of an animated image. + */ + @Override + public Drawable getDrawable() { + return ((AnimatedGifDrawable)mDrawable).getDrawable(); + } + + /* + * Copy-paste of super.getSize(...) but use getDrawable() to get the image/frame to calculate the size, + * in stead of the cached drawable. + */ + @Override + public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { + Drawable d = getDrawable(); + Rect rect = d.getBounds(); + + if (fm != null) { + fm.ascent = -rect.bottom; + fm.descent = 0; + + fm.top = fm.ascent; + fm.bottom = 0; + } + + return rect.right; + } + + /* + * Copy-paste of super.draw(...) but use getDrawable() to get the image/frame to draw, in stead of + * the cached drawable. + */ + @Override + public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { + Drawable b = getDrawable(); + canvas.save(); + + int transY = bottom - b.getBounds().bottom; + if (mVerticalAlignment == ALIGN_BASELINE) { + transY -= paint.getFontMetricsInt().descent; + } + + canvas.translate(x, transY); + b.draw(canvas); + canvas.restore(); + + } + +} + diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/gif/GifDecoder.java b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/GifDecoder.java new file mode 100644 index 000000000..2480ff1b8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/gif/GifDecoder.java @@ -0,0 +1,625 @@ +package com.yizhuan.erban.ui.gift.gif; + +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; + +import java.io.InputStream; +import java.util.Vector; + +//Handler for read & extract Bitmap from *.gif +public class GifDecoder { + + // to store *.gif data, Bitmap & delay + class GifFrame { + // to access image & delay w/o interface + public Bitmap image; + public int delay; + + public GifFrame(Bitmap im, int del) { + image = im; + delay = del; + } + + } + + // to define some error type + public static final int STATUS_OK = 0; + public static final int STATUS_FORMAT_ERROR = 1; + public static final int STATUS_OPEN_ERROR = 2; + + protected int status; + + protected InputStream in; + + protected int width; // full image width + protected int height; // full image height + protected boolean gctFlag; // global color table used + protected int gctSize; // size of global color table + protected int loopCount = 1; // iterations; 0 = repeat forever + + protected int[] gct; // global color table + protected int[] lct; // local color table + protected int[] act; // active color table + + protected int bgIndex; // background color index + protected int bgColor; // background color + protected int lastBgColor; // previous bg color + protected int pixelAspect; // pixel aspect ratio + + protected boolean lctFlag; // local color table flag + protected boolean interlace; // interlace flag + protected int lctSize; // local color table size + + protected int ix, iy, iw, ih; // current image rectangle + protected int lrx, lry, lrw, lrh; + protected Bitmap image; // current frame + protected Bitmap lastImage; // previous frame + protected int frameindex = 0; + + public int getFrameindex() { + return frameindex; + } + + public void setFrameindex(int frameindex) { + this.frameindex = frameindex; + if (frameindex > frames.size() - 1) { + frameindex = 0; + } + } + + protected byte[] block = new byte[256]; // current data block + protected int blockSize = 0; // block size + + // last graphic control extension info + protected int dispose = 0; + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + protected int lastDispose = 0; + protected boolean transparency = false; // use transparent color + protected int delay = 0; // delay in milliseconds + protected int transIndex; // transparent color index + + protected static final int MaxStackSize = 4096; + // max decoder pixel stack size + + // LZW decoder working arrays + protected short[] prefix; + protected byte[] suffix; + protected byte[] pixelStack; + protected byte[] pixels; + + protected Vector frames; // frames read from current file + protected int frameCount; + + // to get its Width / Height + public int getWidth() { + return width; + } + + public int getHeigh() { + return height; + } + + /** + * Gets display duration for specified frame. + * + * @param n + * int index of frame + * @return delay in milliseconds + */ + public int getDelay(int n) { + delay = -1; + if ((n >= 0) && (n < frameCount)) { + delay = ((GifFrame) frames.elementAt(n)).delay; + } + return delay; + } + + public int getFrameCount() { + return frameCount; + } + + public Bitmap getImage() { + return getFrame(0); + } + + public int getLoopCount() { + return loopCount; + } + + protected void setPixels() { + int[] dest = new int[width * height]; + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) { + if (lastDispose == 3) { + // use image before last + int n = frameCount - 2; + if (n > 0) { + lastImage = getFrame(n - 1); + } else { + lastImage = null; + } + } + if (lastImage != null) { + lastImage.getPixels(dest, 0, width, 0, 0, width, height); + // copy pixels + if (lastDispose == 2) { + // fill last image rect area with background color + int c = 0; + if (!transparency) { + c = lastBgColor; + } + for (int i = 0; i < lrh; i++) { + int n1 = (lry + i) * width + lrx; + int n2 = n1 + lrw; + for (int k = n1; k < n2; k++) { + dest[k] = c; + } + } + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) { + int line = i; + if (interlace) { + if (iline >= ih) { + pass++; + switch (pass) { + case 2: + iline = 4; + break; + case 3: + iline = 2; + inc = 4; + break; + case 4: + iline = 1; + inc = 2; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) { + // map color and insert in destination + int index = ((int) pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) { + dest[dx] = c; + } + dx++; + } + } + } + image = Bitmap.createBitmap(dest, width, height, Config.ARGB_4444); + } + + public Bitmap getFrame(int n) { + Bitmap im = null; + if ((n >= 0) && (n < frameCount)) { + im = ((GifFrame) frames.elementAt(n)).image; + } + return im; + } + + public Bitmap nextBitmap() { + frameindex++; + if (frameindex > frames.size() - 1) { + frameindex = 0; + } + return ((GifFrame) frames.elementAt(frameindex)).image; + } + + public int nextDelay() { + return ((GifFrame) frames.elementAt(frameindex)).delay; + } + + // to read & parse all *.gif stream + public int read(InputStream is) { + init(); + if (is != null) { + in = is; + + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return status; + } + + protected void decodeImageData() { + int NullCode = -1; + int npix = iw * ih; + int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi; + + if ((pixels == null) || (pixels.length < npix)) { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) { + prefix = new short[MaxStackSize]; + } + if (suffix == null) { + suffix = new byte[MaxStackSize]; + } + if (pixelStack == null) { + pixelStack = new byte[MaxStackSize + 1]; + } + // Initialize GIF data stream decoder. + data_size = read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) { + prefix[code] = 0; + suffix[code] = (byte) code; + } + + // Decode GIF pixel stream. + datum = bits = count = first = top = pi = bi = 0; + for (i = 0; i < npix;) { + if (top == 0) { + if (bits < code_size) { + // Load bytes until there are enough bits for a code. + if (count == 0) { + // Read a new data block. + count = readBlock(); + if (count <= 0) { + break; + } + bi = 0; + } + datum += (((int) block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + // Get the next code. + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + if ((code > available) || (code == end_of_information)) { + break; + } + if (code == clear) { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) { + pixelStack[top++] = (byte) first; + code = old_code; + } + while (code > clear) { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = ((int) suffix[code]) & 0xff; + // Add a new string to the string table, + if (available >= MaxStackSize) { + break; + } + pixelStack[top++] = (byte) first; + prefix[available] = (short) old_code; + suffix[available] = (byte) first; + available++; + if (((available & code_mask) == 0) + && (available < MaxStackSize)) { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + for (i = pi; i < npix; i++) { + pixels[i] = 0; // clear missing pixels + } + } + + protected boolean err() { + return status != STATUS_OK; + } + + // to initia variable + public void init() { + status = STATUS_OK; + frameCount = 0; + frames = new Vector(); + gct = null; + lct = null; + } + + protected int read() { + int curByte = 0; + try { + curByte = in.read(); + } catch (Exception e) { + status = STATUS_FORMAT_ERROR; + } + return curByte; + } + + protected int readBlock() { + blockSize = read(); + int n = 0; + if (blockSize > 0) { + try { + int count = 0; + while (n < blockSize) { + count = in.read(block, n, blockSize - n); + if (count == -1) { + break; + } + n += count; + } + } catch (Exception e) { + e.printStackTrace(); + } + if (n < blockSize) { + status = STATUS_FORMAT_ERROR; + } + } + return n; + } + + // Global Color Table + protected int[] readColorTable(int ncolors) { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try { + n = in.read(c); + } catch (Exception e) { + e.printStackTrace(); + } + if (n < nbytes) { + status = STATUS_FORMAT_ERROR; + } else { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) { + int r = ((int) c[j++]) & 0xff; + int g = ((int) c[j++]) & 0xff; + int b = ((int) c[j++]) & 0xff; + tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; + } + } + return tab; + } + + // Image Descriptor + protected void readContents() { + // read GIF file content blocks + boolean done = false; + while (!(done || err())) { + int code = read(); + switch (code) { + case 0x2C: // image separator + readImage(); + break; + case 0x21: // extension + code = read(); + switch (code) { + case 0xf9: // graphics control extension + readGraphicControlExt(); + break; + + case 0xff: // application extension + readBlock(); + String app = ""; + for (int i = 0; i < 11; i++) { + app += (char) block[i]; + } + if (app.equals("NETSCAPE2.0")) { + readNetscapeExt(); + } else { + skip(); // don't care + } + break; + default: // uninteresting extension + skip(); + } + break; + + case 0x3b: // terminator + done = true; + break; + + case 0x00: // bad byte, but keep going and see what happens + break; + default: + status = STATUS_FORMAT_ERROR; + } + } + } + + protected void readGraphicControlExt() { + read(); // block size + int packed = read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = readShort() * 10; // delay in milliseconds + transIndex = read(); // transparent color index + read(); // block terminator + } + + // to get Stream - Head + protected void readHeader() { + String id = ""; + for (int i = 0; i < 6; i++) { + id += (char) read(); + } + if (!id.startsWith("GIF")) { + status = STATUS_FORMAT_ERROR; + return; + } + readLSD(); + if (gctFlag && !err()) { + gct = readColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + protected void readImage() { + // offset of X + ix = readShort(); // (sub)image position & size + // offset of Y + iy = readShort(); + // width of bitmap + iw = readShort(); + // height of bitmap + ih = readShort(); + + // Local Color Table Flag + int packed = read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + + // Interlace Flag, to array with interwoven if ENABLE, with order + // otherwise + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + if (lctFlag) { + lct = readColorTable(lctSize); // read table + act = lct; // make local table active + } else { + act = gct; // make global table active + if (bgIndex == transIndex) { + bgColor = 0; + } + } + int save = 0; + if (transparency) { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + if (act == null) { + status = STATUS_FORMAT_ERROR; // no color table defined + } + if (err()) { + return; + } + decodeImageData(); // decode pixel data + skip(); + if (err()) { + return; + } + frameCount++; + // create new image to receive frame data + image = Bitmap.createBitmap(width, height, Config.ARGB_4444); + // createImage(width, height); + setPixels(); // transfer pixel data to image + frames.addElement(new GifFrame(image, delay)); // add image to frame + // list + if (transparency) { + act[transIndex] = save; + } + resetFrame(); + } + + // Logical Screen Descriptor + protected void readLSD() { + // logical screen size + width = readShort(); + height = readShort(); + // packed fields + int packed = read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + bgIndex = read(); // background color index + pixelAspect = read(); // pixel aspect ratio + } + + protected void readNetscapeExt() { + do { + readBlock(); + if (block[0] == 1) { + // loop count sub-block + int b1 = ((int) block[1]) & 0xff; + int b2 = ((int) block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !err()); + } + + // read 8 bit data + protected int readShort() { + // read 16-bit value, LSB first + return read() | (read() << 8); + } + + protected void resetFrame() { + lastDispose = dispose; + lrx = ix; + lry = iy; + lrw = iw; + lrh = ih; + lastImage = image; + lastBgColor = bgColor; + dispose = 0; + transparency = false; + delay = 0; + lct = null; + } + + /** + * Skips variable length blocks up to and including next zero length block. + */ + protected void skip() { + do { + readBlock(); + } while ((blockSize > 0) && !err()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/ExpressionUtil.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/ExpressionUtil.java new file mode 100644 index 000000000..91617544e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/ExpressionUtil.java @@ -0,0 +1,261 @@ +package com.yizhuan.erban.ui.gift.util; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ImageSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.gift.adapter.FaceGVAdapter; +import com.yizhuan.erban.ui.gift.gif.AnimatedGifDrawable; +import com.yizhuan.erban.ui.gift.gif.AnimatedImageSpan; +import com.yizhuan.erban.ui.gift.widget.GiftDataInfo; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ExpressionUtil { + public static String ASSETS_ROOT = "p/"; + public static String ASSETS_GIF_ROOT = "g/"; + private boolean isNetData = false;//是否来自网络数据 + + public ExpressionUtil(){ + + } + + public ExpressionUtil(boolean isNetData){ + this.isNetData = isNetData; + } + + /** + * 从静态图找到对应的动态图,为了方便此处我动态图和静态图名称保持一致 + * + * @param mContext + * @param gifTextView + * @param content + * @return + */ + public SpannableStringBuilder prase(Context mContext, final TextView gifTextView, String content) { + SpannableStringBuilder sb = new SpannableStringBuilder(content); + String regex = "\\[[^\\]]+\\]"; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(content); + while (m.find()) { + String tempText = m.group(); + try { + String num = tempText.substring(("[" + ASSETS_ROOT).length(), tempText.length() - ".png]".length()); + String gif = ASSETS_GIF_ROOT + num + ".gif"; + /** + * 如果open这里不抛异常说明存在gif,则显示对应的gif + * 否则说明gif找不到,则显示png\\[[^\\]]+\\] + * */ + InputStream is = mContext.getAssets().open(gif); + sb.setSpan( + new AnimatedImageSpan( + new AnimatedGifDrawable(is, new AnimatedGifDrawable.UpdateListener() { + @Override + public void update() { + gifTextView.postInvalidate(); + } + })), + m.start(), + m.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + is.close(); + } catch (Exception e) {//没找到对应的GIF,显示静态图 + String png = tempText.substring("[".length(), tempText.length() - "]".length()); + try { + sb.setSpan( + new ImageSpan(mContext, BitmapFactory.decodeStream(mContext.getAssets().open(png))), + m.start(), + m.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } catch (IOException e1) { + e1.printStackTrace(); + } + e.printStackTrace(); + } + } + return sb; + } + + public SpannableStringBuilder getFace(Context mContext, String content) { + SpannableStringBuilder sb = new SpannableStringBuilder(); + try { + /** + * 经过测试,虽然这里tempText被替换为png显示,但是但我单击发送按钮时,获取到輸入框的内容是tempText的值而不是png + * 所以这里对这个tempText值做特殊处理 + * 格式:[face/png/f_static_000.png],以方便判斷當前圖片是哪一個 + * */ + String tempText = "[" + content + "]"; + sb.append(tempText); + sb.setSpan( + new ImageSpan(mContext, BitmapFactory.decodeStream(mContext.getAssets().open(content))), + sb.length() - tempText.length(), + sb.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + } catch (Exception e) { + e.printStackTrace(); + } + + return sb; + } + + public void setView(Context mContext, final View view, String content) { + if (view != null && view instanceof ImageView) {//图片不显示GIF + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeStream(mContext.getAssets().open(content)); + } catch (IOException e1) { + e1.printStackTrace(); + } + ((ImageView) view).setImageBitmap(bitmap); + } else if (view != null && view instanceof TextView) {//文字可显示GIF + TextView gifTextView = (TextView) view; + String tempText = "[" + content + "]"; + SpannableStringBuilder sb = prase(mContext, gifTextView, tempText); + gifTextView.setText(sb); + } + + } + + /** + * 横屏时显示 + * @param context + * @param recyclerView + *@param staticGiftsList @return + */ + public void giftView(final Context context, RecyclerView recyclerView, List staticGiftsList) { + LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false); + recyclerView.setLayoutManager(layoutManager); + + final FaceGVAdapter mGvAdapter = new FaceGVAdapter(recyclerView, staticGiftsList, context, isNetData); + recyclerView.setAdapter(mGvAdapter); + + // 单击表情执行的操作 + mGvAdapter.setOnItemClickListener(new FaceGVAdapter.OnItemClickListener() { + @Override + public void onItemClick(View view, GiftDataInfo giftDataInfo, int position) { + try { + String giftPic = giftDataInfo.getGiftPic(); + String giftName = giftDataInfo.getGiftName(); + String giftPrice = giftDataInfo.getGiftPrice(); +// mGvAdapter.setSeclection(position); +// mGvAdapter.notifyDataSetChanged(); + if (giftClickListener != null) { + giftClickListener.onClick(position, giftPic, giftName, giftPrice); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * 竖屏时显示,每一页的数据 + * + * @param context + * @param position 第几页 + * @param staticGiftsList 表情集合 + * @param columns 列数 + * @param rows 行数 + * @param showView View + * @return + */ + public View viewPagerItem(final Context context, int position, List staticGiftsList, int columns, int rows, final View showView) { + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View layout = inflater.inflate(R.layout.face_gridview, null);//表情布局 + + RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.chart_face_gv); + GridLayoutManager girdLayoutManager = new GridLayoutManager(context, columns); + recyclerView.setLayoutManager(girdLayoutManager); + + List subList = new ArrayList<>(); + subList.addAll(staticGiftsList + .subList(position * (columns * rows - 0), + (columns * rows - 0) * (position + 1) > staticGiftsList + .size() ? staticGiftsList.size() : (columns * rows - 0) + * (position + 1))); + + final FaceGVAdapter mGvAdapter = new FaceGVAdapter(recyclerView, subList, context, isNetData); + recyclerView.setAdapter(mGvAdapter); + // 单击表情执行的操作 + mGvAdapter.setOnItemClickListener(new FaceGVAdapter.OnItemClickListener() { + @Override + public void onItemClick(View view, GiftDataInfo giftDataInfo, int position) { + try { + String giftPic = giftDataInfo.getGiftPic(); + String pngStr = giftDataInfo.getGiftName(); + String giftPrice = giftDataInfo.getGiftPrice(); + setView(context, showView, pngStr); +// mGvAdapter.setSeclection(position); +// mGvAdapter.notifyDataSetChanged(); + if (giftClickListener != null) { + giftClickListener.onClick(position, giftPic, pngStr, giftPrice); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + return recyclerView; + } + + public interface GiftClickListener { + void onClick(int position, String giftPic, String giftName, String giftPrice); + } + + private GiftClickListener giftClickListener; + + public void setGiftClickListener(GiftClickListener listener) { + giftClickListener = listener; + } + + /** + * 根据表情数量以及GridView设置的行数和列数计算Pager数量 + * + * @return + */ + public int getPagerCount(int listSize, int columns, int rows) { + return listSize % (columns * rows - 0) == 0 ? listSize / (columns * rows - 0) : listSize / (columns * rows - 0) + 1; + } + + /** + * 初始化表情列表staticGiftsList + */ + public List initStaticGifts(Context context) { + List giftsList = null; + try { + giftsList = new ArrayList<>(); + GiftDataInfo giftDataInfo; + String[] gifts = context.getAssets().list(ASSETS_ROOT.substring(0, ASSETS_ROOT.length() - 1)); + //将Assets中的表情名称转为字符串一一添加进staticGiftsList + for (int i = 0; i < gifts.length; i++) { + giftDataInfo = new GiftDataInfo(); + giftDataInfo.setGiftName(ASSETS_ROOT + gifts[i]).setGiftPic("").setGiftPrice(i + 1 + ""); + giftsList.add(giftDataInfo); + } + } catch (Exception e) { + e.printStackTrace(); + } + return giftsList; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/FileUtil.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/FileUtil.java new file mode 100644 index 000000000..dcc7f767a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/FileUtil.java @@ -0,0 +1,336 @@ +package com.yizhuan.erban.ui.gift.util; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.Environment; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.DateFormat; +import java.util.Date; +import java.util.HashSet; + +public class FileUtil { + private static String path=""; + static{ + if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ + path= Environment.getExternalStorageDirectory()+"/QQ"; + }else{ + path= Environment.getDataDirectory().getAbsolutePath()+"/QQ"; + } + } + + public static String getRecentChatPath(){ + File file=new File(path+"/RecentChat/"); + if(!file.exists()){ + file.mkdirs(); + } + return path+"/RecentChat/"; + } + + public static String getWaterPhotoPath(){ + File file=new File(path+"/WaterPhoto/"); + if(!file.exists()){ + file.mkdirs(); + } + return path+"/WaterPhoto/"; + } + + + //////////////////////////////////////////////////////////// + private static String ANDROID_SECURE = "/mnt/sdcard/.android_secure"; + + private static final String LOG_TAG = "Util"; + + public static boolean isSDCardReady() { + return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); + } + + + public static String makePath(String path1, String path2) { + if (path1.endsWith(File.separator)) + return path1 + path2; + + return path1 + File.separator + path2; + } + + public static String getSdDirectory() { + return Environment.getExternalStorageDirectory().getPath(); + } + + public static boolean isNormalFile(String fullName) { + return !fullName.equals(ANDROID_SECURE); + } + + /* + * 采用了新的办法获取APK图标,之前的失败是因为android中存在的一个BUG,通过 + * appInfo.publicSourceDir = apkPath;来修正这个问题,详情参见: + * http://code.google.com/p/android/issues/detail?id=9151 + */ + public static Drawable getApkIcon(Context context, String apkPath) { + PackageManager pm = context.getPackageManager(); + PackageInfo info = pm.getPackageArchiveInfo(apkPath, + PackageManager.GET_ACTIVITIES); + if (info != null) { + ApplicationInfo appInfo = info.applicationInfo; + appInfo.sourceDir = apkPath; + appInfo.publicSourceDir = apkPath; + try { + return appInfo.loadIcon(pm); + } catch (OutOfMemoryError e) { + Log.e(LOG_TAG, e.toString()); + } + } + return null; + } + + public static String getExtFromFilename(String filename) { + int dotPosition = filename.lastIndexOf('.'); + if (dotPosition != -1) { + return filename.substring(dotPosition + 1, filename.length()); + } + return ""; + } + + public static String getNameFromFilename(String filename) { + int dotPosition = filename.lastIndexOf('.'); + if (dotPosition != -1) { + return filename.substring(0, dotPosition); + } + return ""; + } + + public static String getPathFromFilepath(String filepath) { + int pos = filepath.lastIndexOf('/'); + if (pos != -1) { + return filepath.substring(0, pos); + } + return ""; + } + + public static String getNameFromFilepath(String filepath) { + int pos = filepath.lastIndexOf('/'); + if (pos != -1) { + return filepath.substring(pos + 1); + } + return ""; + } + + // return new file path if successful, or return null + public static String copyFile(String src, String dest) { + File file = new File(src); + if (!file.exists() || file.isDirectory()) { + Log.v(LOG_TAG, "copyFile: file not checkExist or is directory, " + src); + return null; + } + FileInputStream fi = null; + FileOutputStream fo = null; + try { + fi = new FileInputStream(file); + File destPlace = new File(dest); + if (!destPlace.exists()) { + if (!destPlace.mkdirs()) + return null; + } + + String destPath = FileUtil.makePath(dest, file.getName()); + File destFile = new File(destPath); + int i = 1; + while (destFile.exists()) { + String destName = FileUtil.getNameFromFilename(file.getName()) + " " + i++ + "." + + FileUtil.getExtFromFilename(file.getName()); + destPath = FileUtil.makePath(dest, destName); + destFile = new File(destPath); + } + + if (!destFile.createNewFile()) + return null; + + fo = new FileOutputStream(destFile); + int count = 102400; + byte[] buffer = new byte[count]; + int read = 0; + while ((read = fi.read(buffer, 0, count)) != -1) { + fo.write(buffer, 0, read); + } + + // TODO: set access privilege + + return destPath; + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "copyFile: file not found, " + src); + e.printStackTrace(); + } catch (IOException e) { + Log.e(LOG_TAG, "copyFile: " + e.toString()); + } finally { + try { + if (fi != null) + fi.close(); + if (fo != null) + fo.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return null; + } + + // does not include sd card folder + private static String[] SysFileDirs = new String[] { + "miren_browser/imagecaches" + }; + + + + /* public static ArrayList getDefaultFavorites(Context context) { + ArrayList list = new ArrayList(); + list.add(new FavoriteItem(context.getString(R.string.favorite_photo), makePath(getSdDirectory(), "DCIM/Camera"))); + list.add(new FavoriteItem(context.getString(R.string.favorite_sdcard), getSdDirectory())); + //list.add(new FavoriteItem(context.getString(R.string.favorite_root), getSdDirectory())); + list.add(new FavoriteItem(context.getString(R.string.favorite_screen_cap), makePath(getSdDirectory(), "MIUI/screen_cap"))); + list.add(new FavoriteItem(context.getString(R.string.favorite_ringtone), makePath(getSdDirectory(), "MIUI/ringtone"))); + return list; + }*/ + + public static boolean setText(View view, int id, String text) { + TextView textView = (TextView) view.findViewById(id); + if (textView == null) + return false; + + textView.setText(text); + return true; + } + + public static boolean setText(View view, int id, int text) { + TextView textView = (TextView) view.findViewById(id); + if (textView == null) + return false; + + textView.setText(text); + return true; + } + + // comma separated number + public static String convertNumber(long number) { + return String.format("%,d", number); + } + + // storage, G M K B + public static String convertStorage(long size) { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + + if (size >= gb) { + return String.format("%.1f GB", (float) size / gb); + } else if (size >= mb) { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } else if (size >= kb) { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } else + return String.format("%d B", size); + } + + public static class SDCardInfo { + public long total; + + public long free; + } + + public static SDCardInfo getSDCardInfo() { + String sDcString = Environment.getExternalStorageState(); + + if (sDcString.equals(Environment.MEDIA_MOUNTED)) { + File pathFile = Environment.getExternalStorageDirectory(); + + try { + android.os.StatFs statfs = new android.os.StatFs(pathFile.getPath()); + + // 获取SDCard上BLOCK总数 + long nTotalBlocks = statfs.getBlockCount(); + + // 获取SDCard上每个block的SIZE + long nBlocSize = statfs.getBlockSize(); + + // 获取可供程序使用的Block的数量 + long nAvailaBlock = statfs.getAvailableBlocks(); + + // 获取剩下的所有Block的数量(包括预留的一般程序无法使用的块) + long nFreeBlock = statfs.getFreeBlocks(); + + SDCardInfo info = new SDCardInfo(); + // 计算SDCard 总容量大小MB + info.total = nTotalBlocks * nBlocSize; + + // 计算 SDCard 剩余大小MB + info.free = nAvailaBlock * nBlocSize; + + return info; + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, e.toString()); + } + } + + return null; + } + + /* public static void showNotification(Context context, Intent intent, String title, String body, int drawableId) { + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification notification = new Notification(drawableId, body, System.currentTimeMillis()); + notification.flags = Notification.FLAG_AUTO_CANCEL; + notification.defaults = Notification.DEFAULT_SOUND; + if (intent == null) { + // FIXEME: category tab is disabled + intent = new Intent(context, FileViewActivity.class); + } + PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); + notification.setLatestEventInfo(context, title, body, contentIntent); + manager.notify(drawableId, notification); + }*/ + + public static String formatDateString(Context context, long time) { + DateFormat dateFormat = android.text.format.DateFormat + .getDateFormat(context); + DateFormat timeFormat = android.text.format.DateFormat + .getTimeFormat(context); + Date date = new Date(time); + return dateFormat.format(date) + " " + timeFormat.format(date); + } + + /*public static void updateActionModeTitle(ActionMode mode, Context context, int selectedNum) { + if (mode != null) { + mode.setTitle(context.getString(R.string.multi_select_title,selectedNum)); + if(selectedNum == 0){ + mode.finish(); + } + } + } +*/ + public static HashSet sDocMimeTypesSet = new HashSet() { + { + add("text/plain"); + add("text/plain"); + add("application/pdf"); + add("application/msword"); + add("application/vnd.ms-excel"); + add("application/vnd.ms-excel"); + } + }; + + public static String sZipFileMimeType = "application/zip"; + + public static int CATEGORY_TAB_INDEX = 0; + public static int SDCARD_TAB_INDEX = 1; +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/GiftPanelControl.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/GiftPanelControl.java new file mode 100644 index 000000000..11f91772f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/GiftPanelControl.java @@ -0,0 +1,220 @@ +package com.yizhuan.erban.ui.gift.util; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.gift.adapter.FaceGVAdapter; +import com.yizhuan.erban.ui.gift.adapter.FaceVPAdapter; +import com.yizhuan.erban.ui.gift.widget.GiftDataInfo; + +import java.util.ArrayList; +import java.util.List; + +import static android.content.Context.LAYOUT_INFLATER_SERVICE; + +/** + * Created by KathLine on 2017/1/12. + */ + +public class GiftPanelControl { + + private int columns = 6; + private int rows = 4; + //每页显示的表情view + private List views = new ArrayList<>(); + private RecyclerView mRecyclerView; + private ExpressionUtil expressionUtil; + private LayoutInflater inflater; + private List mDatas; + private Context mContext; + private LinearLayout mDotsLayout; + private ViewPager mViewpager; + + public interface GiftListener { + void getGiftInfo(String giftPic, String giftName, String giftPrice); + } + + private GiftListener giftListener; + + public void setGiftListener(GiftListener listener) { + giftListener = listener; + } + + /** + * @param context + * @param viewPager 竖屏礼物面板的ViewPager + * @param recyclerView 横屏礼物面板的RecycleView + * @param dotsLayout 竖屏礼物面板的小圆点父布局 + */ + public GiftPanelControl(Context context, ViewPager viewPager, RecyclerView recyclerView, LinearLayout dotsLayout) { + mContext = context; + inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); + mViewpager = viewPager; + mRecyclerView = recyclerView; + mDotsLayout = dotsLayout; +// init(); + } + + /** + * + * @param datas datas为null时加载本地礼物图片 + */ + public void init(List datas) { + mDatas = datas; + initPortraitGift(); + intitLandscapeGift(); + } + + /** + * 初始化礼物面板,横屏时显示 + */ + private void intitLandscapeGift() { + if (expressionUtil == null) { + expressionUtil = new ExpressionUtil(mDatas != null); + } + if (mDatas == null) { + mDatas = expressionUtil.initStaticGifts(mContext); + } + + expressionUtil.giftView(mContext, mRecyclerView, mDatas); + } + + /** + * 初始化礼物面板,竖屏时显示 + */ + private void initPortraitGift() { + if (expressionUtil == null) { + expressionUtil = new ExpressionUtil(mDatas != null); + } + if (mDatas == null) { + mDatas = expressionUtil.initStaticGifts(mContext); + } + int pagesize = expressionUtil.getPagerCount(mDatas.size(), columns, rows); + // 获取页数 + for (int i = 0; i < pagesize; i++) { + views.add(expressionUtil.viewPagerItem(mContext, i, mDatas, columns, rows, null)); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(16, 16); + params.setMargins(10, 0, 10, 0); + if (pagesize > 1) { + mDotsLayout.addView(dotsItem(i), params); + } + } + if (pagesize > 1) { + mDotsLayout.setVisibility(View.VISIBLE); + } else { + mDotsLayout.setVisibility(View.GONE); + } + FaceVPAdapter mVpAdapter = new FaceVPAdapter(views); + mViewpager.setAdapter(mVpAdapter); + mViewpager.setOnPageChangeListener(new PageChangeListener()); + mViewpager.setCurrentItem(0); + if (pagesize > 1) { + mDotsLayout.getChildAt(0).setSelected(true); + } + + expressionUtil.setGiftClickListener(new ExpressionUtil.GiftClickListener() { + @Override + public void onClick(int position, String giftPic, String giftName, String giftPrice) { + if (giftListener != null) { + giftListener.getGiftInfo(giftPic, giftName, giftPrice); + } + } + }); + } + + /** + * 表情页切换时,底部小圆点 + * + * @param position + * @return + */ + private ImageView dotsItem(int position) { + View layout = inflater.inflate(R.layout.dot_image, null); + ImageView iv = (ImageView) layout.findViewById(R.id.face_dot); + iv.setId(position); + return iv; + } + + private boolean isScrolling = false; + private boolean left = false;//从右向左,positionOffset值逐渐增大 + private boolean right = false;//从左向右,positionOffset值逐渐减小 + private int lastValue = -1; + private boolean isClearStatus = true;//是否清除礼物选中的状态在切换页面时 + + /** + * 是否清除礼物选中的状态在切换页面时 + * @param isClearStatus + */ + public void isClearStatus(boolean isClearStatus){ + this.isClearStatus = isClearStatus; + } + + /** + * 表情页改变时,dots效果也要跟着改变 + */ + class PageChangeListener implements ViewPager.OnPageChangeListener { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + //这里的position是当前屏幕可见页面的第一个页面 + if (isScrolling) { + if (lastValue > positionOffsetPixels) { + //递减,向右滑动 + right = true; + left = false; + } else if (lastValue < positionOffsetPixels) { + //递增,向左滑动 + right = false; + left = true; + } else if (lastValue == positionOffsetPixels) { + right = left = false; + } + } +// Log.i("CustormViewPager", "onPageScrolled: positionOffset =>" + positionOffset + "; positionOffsetPixels =>" + positionOffsetPixels); +// Log.i("CustormViewPager", "onPageScrolled: right =>" + right + "; left =>" + left); + lastValue = positionOffsetPixels; + } + + @Override + public void onPageSelected(int position) { + for (int i = 0; i < mDotsLayout.getChildCount(); i++) { + mDotsLayout.getChildAt(i).setSelected(false); + } + mDotsLayout.getChildAt(position).setSelected(true); + for (int i = 0; i < views.size(); i++) {//清除选中,当礼物页面切换到另一个礼物页面 + RecyclerView view = (RecyclerView) views.get(i); + FaceGVAdapter adapter = (FaceGVAdapter) view.getAdapter(); + if (isClearStatus){ + adapter.clearSelection(); + if (giftListener != null) { + giftListener.getGiftInfo("", "", ""); + } + } + + } + } + + @Override + public void onPageScrollStateChanged(int state) { + //ViewPager.SCROLL_STATE_IDLE 空闲状态 0;CustormViewPager.SCROLL_STATE_DRAGGING 正在滑动 1 + //ViewPager.SCROLL_STATE_SETTLING 滑动完毕 2;页面开始滑动时,状态变化(1,2,0) + if (state == ViewPager.SCROLL_STATE_DRAGGING) { + isScrolling = true; + } else { + isScrolling = false; + } + if (state == ViewPager.SCROLL_STATE_SETTLING) { +// Log.i("CustormViewPager", "----------------right =>" + right + "; left =>" + left + "----------------------------"); + right = left = false; +// lastValue = -1; + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/GlideCacheUtil.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/GlideCacheUtil.java new file mode 100644 index 000000000..b92417a64 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/GlideCacheUtil.java @@ -0,0 +1,175 @@ +package com.yizhuan.erban.ui.gift.util; + +import android.content.Context; +import android.os.Looper; +import android.text.TextUtils; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory; +import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; + +import java.io.File; +import java.math.BigDecimal; + +/** + * Glide缓存工具类 + * Created by KathLine on 2017/4/27. + */ + +public class GlideCacheUtil { + private static GlideCacheUtil inst; + + public static GlideCacheUtil getInstance() { + if (inst == null) { + inst = new GlideCacheUtil(); + } + return inst; + } + + /** + * 清除图片磁盘缓存 + */ + public void clearImageDiskCache(final Context context) { + try { + if (Looper.myLooper() == Looper.getMainLooper()) { + new Thread(new Runnable() { + @Override + public void run() { + Glide.get(context).clearDiskCache(); + } + }).start(); + } else { + Glide.get(context).clearDiskCache(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 清除图片内存缓存 + */ + public void clearImageMemoryCache(Context context) { + try { + if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行 + Glide.get(context).clearMemory(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 清除图片所有缓存 + */ + public void clearImageAllCache(Context context) { + clearImageDiskCache(context); + clearImageMemoryCache(context); + String ImageExternalCatchDir = context.getExternalCacheDir() + ExternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR; + deleteFolderFile(ImageExternalCatchDir, true); + } + + /** + * 获取Glide造成的缓存大小 + * + * @return CacheSize + */ + public String getCacheSize(Context context) { + try { + return getFormatSize(getFolderSize(new File(context.getCacheDir() + "/" + InternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR))); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 获取指定文件夹内所有文件大小的和 + * + * @param file file + * @return size + * @throws Exception + */ + private long getFolderSize(File file) throws Exception { + long size = 0; + try { + File[] fileList = file.listFiles(); + for (File aFileList : fileList) { + if (aFileList.isDirectory()) { + size = size + getFolderSize(aFileList); + } else { + size = size + aFileList.length(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return size; + } + + /** + * 删除指定目录下的文件,这里用于缓存的删除 + * + * @param filePath filePath + * @param deleteThisPath deleteThisPath + */ + private void deleteFolderFile(String filePath, boolean deleteThisPath) { + if (!TextUtils.isEmpty(filePath)) { + try { + File file = new File(filePath); + if (file.isDirectory()) { + File files[] = file.listFiles(); + for (File file1 : files) { + deleteFolderFile(file1.getAbsolutePath(), true); + } + } + if (deleteThisPath) { + if (!file.isDirectory()) { + file.delete(); + } else { + if (file.listFiles().length == 0) { + file.delete(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * 格式化单位 + * + * @param size size + * @return size + */ + private static String getFormatSize(double size) { + + double kiloByte = size / 1024; + if (kiloByte < 1) { + return size + "Byte"; + } + + double megaByte = kiloByte / 1024; + if (megaByte < 1) { + BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); + return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB"; + } + + double gigaByte = megaByte / 1024; + if (gigaByte < 1) { + BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); + return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB"; + } + + double teraBytes = gigaByte / 1024; + if (teraBytes < 1) { + BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); + return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"; + } + BigDecimal result4 = new BigDecimal(teraBytes); + + return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/Preconditions.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/Preconditions.java new file mode 100644 index 000000000..b37f96f0b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/Preconditions.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Jake Wharton + * + * 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.yizhuan.erban.ui.gift.util; + +import android.os.Looper; + +public final class Preconditions { + public static void checkArgument(boolean assertion, String message) { + if (!assertion) { + throw new IllegalArgumentException(message); + } + } + + public static T checkNotNull(T value, String message) { + if (value == null) { + throw new NullPointerException(message); + } + return value; + } + + public static void checkUiThread() { + if (Looper.getMainLooper() != Looper.myLooper()) { + throw new IllegalStateException( + "Must be called from the main thread. Was: " + Thread.currentThread()); + } + } + + private Preconditions() { + throw new AssertionError("No instances."); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/util/RecyclerViewUtil.java b/app/src/main/java/com/yizhuan/erban/ui/gift/util/RecyclerViewUtil.java new file mode 100644 index 000000000..7996273f3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/util/RecyclerViewUtil.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.ui.gift.util; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +/** + * Created by KathLine on 2017/4/27. + */ + +public class RecyclerViewUtil { + private RecyclerView mRecyclerView = null; + private GestureDetector mGestureDetector = null; + private RecyclerView.SimpleOnItemTouchListener mSimpleOnItemTouchListener; + private OnItemClickListener mOnItemClickListener = null; + private OnItemLongClickListener mOnItemLongClickListener = null; + private Context context; + + public RecyclerViewUtil(Context context, RecyclerView recyclerView) { + this.context = context; + this.mRecyclerView = recyclerView; + + mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + //长按事件 + @Override + public void onLongPress(MotionEvent e) { + super.onLongPress(e); + if (mOnItemLongClickListener != null) { + View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY()); + if (childView != null) { + int position = mRecyclerView.getChildLayoutPosition(childView); + mOnItemLongClickListener.onItemLongClick(position, childView); + } + } + } + + //单击事件 + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (mOnItemClickListener != null) { + View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY()); + if (childView != null) { + int position = mRecyclerView.getChildLayoutPosition(childView); + mOnItemClickListener.onItemClick(position, childView); + return true; + } + } + + return super.onSingleTapUp(e); + } + }); + + mSimpleOnItemTouchListener = new RecyclerView.SimpleOnItemTouchListener() { + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + if (mGestureDetector.onTouchEvent(e)) { + return true; + } + return false; + } + }; + + mRecyclerView.addOnItemTouchListener(mSimpleOnItemTouchListener); + } + + public void setOnItemClickListener(OnItemClickListener l) { + mOnItemClickListener = l; + } + + public void setOnItemLongClickListener(OnItemLongClickListener l) { + mOnItemLongClickListener = l; + } + + //长按事件接口 + public interface OnItemLongClickListener { + void onItemLongClick(int position, View view); + } + + //单击事件接口 + public interface OnItemClickListener { + void onItemClick(int position, View view); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/CustormAnim.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/CustormAnim.java new file mode 100644 index 000000000..ae67ac3c8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/CustormAnim.java @@ -0,0 +1,90 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.support.annotation.NonNull; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import com.yizhuan.erban.R; + +/** + * @author KathLine + * @date 2017/7/7 + */ + +public class CustormAnim implements ICustormAnim { + + @Override + public AnimatorSet startAnim(final GiftFrameLayout giftFrameLayout, View rootView) { + //礼物飞入 + ObjectAnimator flyFromLtoR2 = GiftAnimationUtil.createFlyFromLtoR(giftFrameLayout, -300, 0, 200, new DecelerateInterpolator()); + flyFromLtoR2.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + giftFrameLayout.initLayoutState(); + } + + @Override + public void onAnimationEnd(Animator animation) { + giftFrameLayout.comboAnimation(); + } + }); + AnimatorSet animSet = new AnimatorSet(); + animSet.play(flyFromLtoR2); + animSet.start(); + return animSet; + } + + @Override + public AnimatorSet comboAnim(final GiftFrameLayout giftFrameLayout, View rootView) { + final StrokeTextView anim_num = (StrokeTextView) rootView.findViewById(R.id.animation_num); + //数量增加 + ObjectAnimator scaleGiftNum = GiftAnimationUtil.scaleGiftNum(anim_num); + scaleGiftNum.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + anim_num.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + giftFrameLayout.comboEndAnim();//这里一定要回调该方法,不然连击不会生效 + } + }); + scaleGiftNum.start(); + return null; + } + + @Override + public AnimatorSet endAnim(final GiftFrameLayout giftFrameLayout, View rootView) { + return testAnim(giftFrameLayout); + } + + @NonNull + private AnimatorSet testAnim(GiftFrameLayout giftFrameLayout) { + PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 0, -50); + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.5f); + ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(giftFrameLayout, translationY, alpha); + animator.setStartDelay(0); + animator.setDuration(1500); + + translationY = PropertyValuesHolder.ofFloat("translationY", -50, -100); + alpha = PropertyValuesHolder.ofFloat("alpha", 0.5f, 0f); + ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(giftFrameLayout, translationY, alpha); + animator1.setStartDelay(0); + animator1.setDuration(1500); + + // 复原 + ObjectAnimator fadeAnimator2 = GiftAnimationUtil.createFadeAnimator(giftFrameLayout, 0, 0, 0, 0); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(animator1).after(animator); + animatorSet.play(fadeAnimator2).after(animator1); + animatorSet.start(); + return animatorSet; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftAnimationUtil.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftAnimationUtil.java new file mode 100644 index 000000000..731455f2f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftAnimationUtil.java @@ -0,0 +1,127 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.TimeInterpolator; +import android.graphics.drawable.AnimationDrawable; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +/** + * Created by KathLine on 2017/1/8. + */ +public class GiftAnimationUtil { + + + /** + * @param target + * @param star 动画起始坐标 + * @param end 动画终止坐标 + * @param duration 持续时间 + * @return 创建一个从左到右的飞入动画 + * 礼物飞入动画 + */ + public static ObjectAnimator createFlyFromLtoR(final View target, float star, float end, int duration, TimeInterpolator interpolator) { + //1.个人信息先飞出来 + ObjectAnimator anim1 = ObjectAnimator.ofFloat(target, "translationX", + star, end); + anim1.setInterpolator(interpolator); + anim1.setDuration(duration); + return anim1; + } + + + /** + * @param target + * @return 播放帧动画 + */ + public static AnimationDrawable startAnimationDrawable(ImageView target) { + AnimationDrawable animationDrawable = (AnimationDrawable) target.getDrawable(); + if (animationDrawable != null) { + target.setVisibility(View.VISIBLE); + animationDrawable.start(); + } + return animationDrawable; + } + + + /** + * @param target + * @param drawable 设置帧动画 + */ + public static void setAnimationDrawable(ImageView target, AnimationDrawable drawable) { + + target.setBackground(drawable); + } + + + /** + * @param target + * @return 送礼数字变化 + */ + public static ObjectAnimator scaleGiftNum(final TextView target) { + PropertyValuesHolder anim4 = PropertyValuesHolder.ofFloat("scaleX", + 1.2f, 0.8f, 1f); + PropertyValuesHolder anim5 = PropertyValuesHolder.ofFloat("scaleY", + 1.2f, 0.8f, 1f); + PropertyValuesHolder anim6 = PropertyValuesHolder.ofFloat("alpha", + 1.0f, 0f, 1f); + ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(target, anim4, anim5, anim6).setDuration(400); + return animator; + + } + + + /** + * @param target + * @param star + * @param end + * @param duration + * @param startDelay + * @return 向上飞 淡出 + */ + public static ObjectAnimator createFadeAnimator(final View target, float star, float end, int duration, int startDelay) { + + PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", star, end); + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0f); + ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(target, translationY, alpha); + animator.setStartDelay(startDelay); + animator.setDuration(duration); + return animator; + } + + /** + * @param animator1 + * @param animator2 + * @return 按顺序播放动画 + */ + public static AnimatorSet startAnimation(ObjectAnimator animator1, ObjectAnimator animator2) { + AnimatorSet animSet = new AnimatorSet(); +// animSet.playSequentially(animators); + animSet.play(animator1).before(animator2); + animSet.start(); + return animSet; + } + + /** + * @param animator1 + * @param animator2 + * @param animator3 + * @param animator4 + * @param animator5 + * @return 按顺序播放动画 + */ + public static AnimatorSet startAnimation(ObjectAnimator animator1, ObjectAnimator animator2, ObjectAnimator animator3, ObjectAnimator animator4, ObjectAnimator animator5) { + AnimatorSet animSet = new AnimatorSet(); +// animSet.playSequentially(animators); + animSet.play(animator1).before(animator2); + animSet.play(animator3).after(animator2); + animSet.play(animator4).after(animator3); + animSet.play(animator5).after(animator4); + animSet.start(); + return animSet; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftControl.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftControl.java new file mode 100644 index 000000000..e21d48631 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftControl.java @@ -0,0 +1,278 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.support.annotation.NonNull; +import android.util.Log; +import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by KathLine on 2017/1/8. + */ + +public class GiftControl implements GiftFrameLayout.LeftGiftAnimationStatusListener { + + private static final String TAG = "GiftControl"; + /** + * 自定义动画 + */ + private ICustormAnim custormAnim; + /** + * 礼物队列 + */ + private ArrayList mGiftQueue; + + /** + * 礼物数量集合 + */ + private SparseArray mGiftLayoutList; + + public GiftControl() { + mGiftQueue = new ArrayList<>(); + } + + public GiftControl setCustormAnim(ICustormAnim anim){ + custormAnim = anim; + + return this; + } + + public GiftControl setGiftLayout(boolean isHideMode, @NonNull SparseArray giftLayoutList){ + mGiftLayoutList = giftLayoutList; + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + giftFrameLayout.setIndex(i); + giftFrameLayout.firstHideLayout(); + giftFrameLayout.setGiftAnimationListener(this); + giftFrameLayout.setHideMode(isHideMode); + } + return this; + } + + public void loadGift(GiftDataInfo gift) { + loadGift(gift, true); + } + + /** + * 加入礼物,具有实时连击效果 + * + * @param gift + * @param supportCombo 是否支持实时连击,如果为true:支持,否则不支持 + */ + public void loadGift(GiftDataInfo gift, boolean supportCombo) { + if (mGiftQueue != null) { + if (supportCombo) { + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + if(giftFrameLayout.isShowing()){ + if (giftFrameLayout.getCurrentGiftId().equals(gift.getGiftId()) + && giftFrameLayout.getCurrentSendUserId().equals(gift.getSendUserId()) + && giftFrameLayout.getCurrentGiftGroup() == gift.getGiftGroup()) { + //连击 + Log.i(TAG, "addGiftQueue: ========giftFrameLayout("+ giftFrameLayout.getIndex()+")连击========礼物:" + gift.getGiftId() + ",连击X" + gift.getGiftCount()); + giftFrameLayout.setGiftCount(gift.getGiftCount()); + giftFrameLayout.setSendGiftTime(gift.getSendGiftTime()); + return; + } + } + } + } + + addGiftQueue(gift, supportCombo); + } + } + + private void addGiftQueue(final GiftDataInfo gift, final boolean supportCombo) { + if (mGiftQueue != null) { + if (mGiftQueue.size() == 0) { + Log.d(TAG, "addGiftQueue---集合个数:" + mGiftQueue.size() + ",礼物:" + gift.getGiftId()); + mGiftQueue.add(gift); + showGift(); + return; + } + } + Log.d(TAG, "addGiftQueue---集合个数:" + mGiftQueue.size() + ",礼物:" + gift.getGiftId()); + if (supportCombo) { + boolean addflag = false; + for (GiftDataInfo model : mGiftQueue) { + if (model.getGiftId().equals(gift.getGiftId()) && model.getSendUserId().equals(gift.getSendUserId()) && model.getGiftGroup() == gift.getGiftGroup()) { + Log.d(TAG, "addGiftQueue: ========已有集合========" + gift.getGiftId() + ",礼物数:" + gift.getGiftCount()); + model.setGiftCount(model.getGiftCount() + gift.getGiftCount()); + addflag = true; + break; + } + } + //如果在现有的集合中不存在同一人发的礼物就加入到现有集合中 + if (!addflag) { + Log.d(TAG, "addGiftQueue: --------新的集合--------" + gift.getGiftId() + ",礼物数:" + gift.getGiftCount()); + mGiftQueue.add(gift); + } + } else { + mGiftQueue.add(gift); + } + + } + + /** + * 显示礼物 + */ + public synchronized void showGift() { + if (isEmpty()) { + return; + } + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + Log.d(TAG, "showGift: begin->集合个数:" + mGiftQueue.size()); + if (!giftFrameLayout.isShowing() && giftFrameLayout.isEnd()) { + boolean hasGift = giftFrameLayout.setGift(getGift()); + if (hasGift) { + giftFrameLayout.startAnimation(custormAnim); + } + } + Log.d(TAG, "showGift: end->集合个数:" + mGiftQueue.size()); + } + } + + /** + * 取出礼物 + * + * @return + */ + private synchronized GiftDataInfo getGift() { + GiftDataInfo gift = null; + if (mGiftQueue.size() != 0) { + gift = mGiftQueue.get(0); + mGiftQueue.remove(0); + Log.i(TAG, "getGift---集合个数:" + mGiftQueue.size() + ",送出礼物---" + gift.getGiftId() + ",礼物数X" + gift.getGiftCount()); + } + return gift; + } + + /** + * 通过获取giftId和getSendUserId当前用户giftId礼物总数 + * @param giftId + * @param userId + * @return + */ + public int getCurGiftCountByUserId(String giftId, String userId) { + int curGiftCount = 0; + GiftFrameLayout giftFrameLayout; + GiftDataInfo giftDataInfo; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + giftDataInfo = giftFrameLayout.getGift(); + if (giftDataInfo != null && giftDataInfo.getGiftId().equals(giftId) && giftDataInfo.getSendUserId().equals(userId)) { + curGiftCount = giftDataInfo.getGiftCount(); + } else {//自己的礼物不正在显示,还在队列中 + Iterator iterator = mGiftQueue.iterator(); + while (iterator.hasNext()){ + giftDataInfo = iterator.next(); + if (giftDataInfo.getGiftId().equals(giftId) && giftDataInfo.getSendUserId().equals(userId)) { + curGiftCount = giftDataInfo.getGiftCount(); + break; + } + } + } + } + return curGiftCount; + } + + /** + * 获取正在展示礼物的个数(即GiftFragmeLayout展示的个数) + * @return + */ + public int getShowingGiftLayoutCount(){ + int count = 0; + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + if(giftFrameLayout.isShowing()){ + count++; + } + } + return count; + } + + /** + * 获取正在展示礼物的个数实例(即GiftFragmeLayout展示的个数实例) + * @return + */ + public List getShowingGiftLayouts(){ + List giftLayoutList = new ArrayList<>(); + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + if(giftFrameLayout.isShowing()){ + giftLayoutList.add(giftFrameLayout); + } + } + return giftLayoutList; + } + + @Override + public void dismiss(int index) { + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + if(giftFrameLayout.getIndex() == index){ + reStartAnimation(giftFrameLayout, giftFrameLayout.getIndex()); + } + } + } + + private void reStartAnimation(final GiftFrameLayout giftFrameLayout, final int index) { + //动画结束,这时不能触发连击动画 + giftFrameLayout.setCurrentShowStatus(false); + Log.d(TAG, "reStartAnimation: 动画结束"); + AnimatorSet animatorSet = giftFrameLayout.endAnmation(custormAnim); + if (animatorSet != null) { + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + Log.i(TAG, "礼物动画dismiss: index = " + index); + //动画完全结束 + giftFrameLayout.CurrentEndStatus(true); + giftFrameLayout.setGiftViewEndVisibility(isEmpty()); + showGift(); + } + }); + } + } + + /** + * 清除所有礼物 + */ + public synchronized void cleanAll() { + if (mGiftQueue != null) { + mGiftQueue.clear(); + } + GiftFrameLayout giftFrameLayout; + for (int i = 0; i < mGiftLayoutList.size(); i++) { + giftFrameLayout = mGiftLayoutList.get(i); + if(giftFrameLayout != null){ + giftFrameLayout.clearHandler(); + } + } + } + + /** + * 礼物是否为空 + * + * @return + */ + public synchronized boolean isEmpty() { + if (mGiftQueue == null || mGiftQueue.size() == 0) { + return true; + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftDataInfo.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftDataInfo.java new file mode 100644 index 000000000..086308aea --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftDataInfo.java @@ -0,0 +1,131 @@ +package com.yizhuan.erban.ui.gift.widget; + +/** + * Created by KathLine on 2017/1/8. + */ +public class GiftDataInfo { + + private String giftId;//礼物的id + private String giftName;//礼物的名字 + private int giftCount;//一次发送礼物的数量 + private int giftGroup;//组数 + private String giftPic;//礼物的图片 + private String giftPrice;//礼物的价格 + private String sendUserId;//发送者的id + private String sendUserName;//发送者的名字 + private String sendUserPic;//发送者的头像 + private int hitCombo;//上一次要连击的礼物数 + private Long sendGiftTime;//发送礼物的时间 + private boolean currentStart;//是否从当前数开始连击 + + public GiftDataInfo() { + } + + public String getGiftId() { + return giftId; + } + + public GiftDataInfo setGiftId(String giftId) { + this.giftId = giftId; + return this; + } + + public String getGiftName() { + return giftName; + } + + public GiftDataInfo setGiftName(String giftName) { + this.giftName = giftName; + return this; + } + + public int getGiftCount() { + return giftCount; + } + + public GiftDataInfo setGiftCount(int giftCount) { + this.giftCount = giftCount; + return this; + } + + public String getSendUserId() { + return sendUserId; + } + + public GiftDataInfo setSendUserId(String sendUserId) { + this.sendUserId = sendUserId; + return this; + } + + public String getSendUserName() { + return sendUserName; + } + + public GiftDataInfo setSendUserName(String sendUserName) { + this.sendUserName = sendUserName; + return this; + } + + public String getSendUserPic() { + return sendUserPic; + } + + public GiftDataInfo setSendUserPic(String sendUserPic) { + this.sendUserPic = sendUserPic; + return this; + } + + public String getGiftPic() { + return giftPic; + } + + public GiftDataInfo setGiftPic(String giftPic) { + this.giftPic = giftPic; + return this; + } + + public String getGiftPrice() { + return giftPrice; + } + + public GiftDataInfo setGiftPrice(String giftPrice) { + this.giftPrice = giftPrice; + return this; + } + + public int getHitCombo() { + return hitCombo; + } + + public GiftDataInfo setHitCombo(int hitCombo) { + this.hitCombo = hitCombo; + return this; + } + + public Long getSendGiftTime() { + return sendGiftTime; + } + + public GiftDataInfo setSendGiftTime(Long sendGiftTime) { + this.sendGiftTime = sendGiftTime; + return this; + } + + public boolean isCurrentStart() { + return currentStart; + } + + public GiftDataInfo setCurrentStart(boolean currentStart) { + this.currentStart = currentStart; + return this; + } + + public int getGiftGroup() { + return giftGroup; + } + + public GiftDataInfo setGiftGroup(int giftGroup) { + this.giftGroup = giftGroup; + return this; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftFrameLayout.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftFrameLayout.java new file mode 100644 index 000000000..bb2bd070b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GiftFrameLayout.java @@ -0,0 +1,494 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.OvershootInterpolator; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CircleCrop; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.io.IOException; + + +/** + * Created by KathLine on 2017/1/8. + */ +public class GiftFrameLayout extends RelativeLayout implements Handler.Callback { + + private static final String TAG = "GiftFrameLayout"; + private Handler mHandler = new Handler(this); + private Handler comboHandler = new Handler(this); + private Runnable runnable; + + private static final int RESTART_GIFT_ANIMATION_CODE = 1002; + /** + * 礼物展示时间 + */ + public static final int GIFT_DISMISS_TIME = 1500; + private static final int INTERVAL = 299; + /** + * 当前动画runnable + */ + private Runnable mCurrentAnimRunnable; + + RelativeLayout anim_rl; + ImageView anim_gift, anim_light, anim_header; + TextView anim_nickname, anim_sign; + StrokeTextView anim_num; + TextView giftGroup; + + private GiftDataInfo mGift; + /** + * item 显示位置 + */ + private int mIndex = 1; + /** + * 礼物连击数 + */ + private int mGiftCount; + /** + * 当前播放连击数 + */ + private int mCombo = 1; + /** + * 礼物动画正在显示,在这期间可触发连击效果 + */ + private boolean isShowing = false; + /** + * 礼物动画结束 + */ + private boolean isEnd = true; + /** + * 自定义动画的接口 + */ + private ICustormAnim anim; + /** + * 是否开启礼物动画隐藏模式(如果两个礼物动画同时显示,并且第一个优先结束,第二个礼物的位置会移动到第一个位置上去) + */ + private boolean isHideMode = false; + + private LeftGiftAnimationStatusListener mGiftAnimationListener; + + public GiftFrameLayout(Context context) { + this(context, null); + } + + public GiftFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + + private void initView(Context context) { + inflate(context, R.layout.item_gift, this); + anim_rl = (RelativeLayout) findViewById(R.id.infoRl); + anim_gift = (ImageView) findViewById(R.id.giftIv); + anim_light = (ImageView) findViewById(R.id.light); + anim_num = (StrokeTextView) findViewById(R.id.animation_num); + anim_header = (ImageView) findViewById(R.id.headIv); + anim_nickname = (TextView) findViewById(R.id.nickNameTv); + anim_sign = (TextView) findViewById(R.id.infoTv); + giftGroup = (TextView) findViewById(R.id.gift_group); + + } + + public ImageView getAnimGift() { + return anim_gift; + } + + public void firstHideLayout() { + setVisibility(GONE); + } + + public void setHideMode(boolean isHideMode) { + this.isHideMode = isHideMode; + } + + public void hideView() { + anim_gift.setVisibility(INVISIBLE); + anim_light.setVisibility(INVISIBLE); + anim_num.setVisibility(INVISIBLE); + } + + public void setGiftViewEndVisibility(boolean hasGift) { + + if (isHideMode && hasGift) { + GiftFrameLayout.this.setVisibility(View.GONE); + } else { + GiftFrameLayout.this.setVisibility(View.INVISIBLE); + } + } + + public boolean setGift(GiftDataInfo gift) { + if (gift == null) { + return false; + } + mGift = gift; + + if (mGift.isCurrentStart()) { + mGiftCount = gift.getGiftCount() + mGift.getHitCombo(); + } else { + mGiftCount = gift.getGiftCount(); + } + if (!TextUtils.isEmpty(gift.getSendUserName())) { + anim_nickname.setText(gift.getSendUserName()); + } + if (!TextUtils.isEmpty(gift.getGiftId())) { + anim_sign.setText(gift.getGiftName()); + } + return true; + } + + public GiftDataInfo getGift() { + return mGift; + } + + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case RESTART_GIFT_ANIMATION_CODE: + mCombo++; + anim_num.setText("x " + (mCombo)); + comboAnimation(); + removeDismissGiftCallback(); + break; + default: + break; + } + return true; + } + + /** + * 显示完连击数与动画时,关闭此Item Layout,并通知外部隐藏自身(供内部调用) + */ + private void dismissGiftLayout() { + removeDismissGiftCallback(); + if (mGiftAnimationListener != null) { + mGiftAnimationListener.dismiss(mIndex); + } + } + + private void removeDismissGiftCallback() { + stopCheckGiftCount(); + if (mCurrentAnimRunnable != null) { + mHandler.removeCallbacks(mCurrentAnimRunnable); + mCurrentAnimRunnable = null; + } + } + + private class GiftNumAnimaRunnable implements Runnable { + + @Override + public void run() { + dismissGiftLayout(); + } + } + + /** + * 设置item显示位置 + * + * @param mIndex + */ + public void setIndex(int mIndex) { + this.mIndex = mIndex; + } + + /** + * 获取ite显示位置 + * + * @return + */ + public int getIndex() { + Log.i(TAG, "index : " + mIndex); + return mIndex; + } + + public interface LeftGiftAnimationStatusListener { + void dismiss(int index); + } + + public void setGiftAnimationListener(LeftGiftAnimationStatusListener giftAnimationListener) { + this.mGiftAnimationListener = giftAnimationListener; + } + + public boolean isShowing() { + return isShowing; + } + + public void setCurrentShowStatus(boolean status) { + mCombo = 1; + isShowing = status; + } + + public boolean isEnd() { + return isEnd; + } + + public void CurrentEndStatus(boolean isEnd) { + this.isEnd = isEnd; + } + + /** + * 获取当前显示礼物发送人id + * + * @return + */ + public String getCurrentSendUserId() { + if (mGift != null) { + return mGift.getSendUserId(); + } + return null; + } + + /** + * 获取当前显示礼物id + * + * @return + */ + public String getCurrentGiftId() { + if (mGift != null) { + return mGift.getGiftId(); + } + return null; + } + + public int getCurrentGiftGroup() { + if (mGift != null) { + return mGift.getGiftGroup(); + } + return 0; + } + + /** + * 增加礼物数量,用于连击效果 + * + * @param count + */ + public synchronized void setGiftCount(int count) { + mGiftCount += count; + mGift.setGiftCount(mGiftCount); + } + + public int getGiftCount() { + return mGiftCount; + } + + public synchronized void setSendGiftTime(long sendGiftTime) { + mGift.setSendGiftTime(sendGiftTime); + } + + public long getSendGiftTime() { + return mGift.getSendGiftTime(); + } + + /** + *
+     * 这里不能GIFT_DISMISS_TIME % INVISIBLE == 0,
+     * 因为余数为0的话,说明在这个时刻即执行了{@link GiftControl#reStartAnimation(GiftFrameLayout, int)}移除动画{@link #endAnmation(ICustormAnim)},也执行了检查监听连击动作。
+     * 这导致就会出现在礼物动画消失的一瞬间,点击连击会出现如下日志出现的情况(已经触发连击了,但是礼物的动画已经结束了):
+     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout D/GiftControl: addGiftQueue---集合个数:0,礼物:p/000.png
+     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout D/GiftControl: showGift: begin->集合个数:1
+     * 02-18 20:45:57.900 9060-9060/org.dync.livegiftlayout I/GiftControl: getGift---集合个数:0,送出礼物---p/000.png,礼物数X1
+     * 02-18 20:45:57.910 9060-9060/org.dync.livegiftlayout D/GiftControl: showGift: end->集合个数:0
+     * 02-18 20:46:01.910 9060-9060/org.dync.livegiftlayout I/GiftControl: addGiftQueue: ========mFirstItemGift连击========礼物:p/000.png,连击X1
+     * 02-18 20:46:01.970 9060-9060/org.dync.livegiftlayout D/GiftControl: reStartAnimation: 动画结束
+     * 02-18 20:46:02.490 9060-9060/org.dync.livegiftlayout I/GiftControl: 礼物动画dismiss: index = 0
+     *
+     * 
+ */ + private void checkGiftCountSubscribe() { + + runnable = new Runnable() { + @Override + public void run() { + if (mGiftCount > mCombo) { + mHandler.sendEmptyMessage(RESTART_GIFT_ANIMATION_CODE); + } + comboHandler.postDelayed(runnable, INTERVAL); + } + }; + comboHandler.postDelayed(runnable, INTERVAL); + } + + public void stopCheckGiftCount() { + comboHandler.removeCallbacksAndMessages(null); + } + + public void clearHandler() { + mHandler.removeCallbacksAndMessages(null); + mHandler = null;//这里要置位null,否则当前页面销毁时,正在执行的礼物动画会造成内存泄漏 + mGiftAnimationListener = null; + + comboHandler.removeCallbacksAndMessages(null); + comboHandler = null;//这里要置位null,否则当前页面销毁时,正在执行的礼物动画会造成内存泄漏 + } + + /** + * 动画开始时回调,使用方法借鉴{@link #startAnimation} + */ + public void initLayoutState() { + this.setVisibility(View.VISIBLE); + this.setAlpha(1f); + isShowing = true; + isEnd = false; + + if (mGift.getSendUserPic().equals("")) { + GlideApp.with(BasicConfig.INSTANCE.getAppContext()) + .load(R.drawable.default_avatar) + .transform(new CircleCrop()) + .into(anim_header); + } else { + GlideApp.with(BasicConfig.INSTANCE.getAppContext()) + .load(mGift.getSendUserPic()) + .transform(new CircleCrop()) + .into(anim_header); + } + + if (mGift.getGiftGroup() == 1) { + giftGroup.setVisibility(GONE); + } else { + giftGroup.setVisibility(VISIBLE); + giftGroup.setText("X" + mGift.getGiftGroup()); + } + + if (mGift.isCurrentStart()) { + mCombo = mGift.getHitCombo(); + } + anim_num.setText("x " + mCombo); + if (!mGift.getGiftPic().equals("")) { + GlideApp.with(BasicConfig.INSTANCE.getAppContext()) + .load(mGift.getGiftPic()) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Drawable drawable, Transition transition) { + anim_gift.setImageDrawable(drawable); + } + }); + } else { + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeStream(getContext().getAssets().open(mGift.getGiftId())); + + } catch (IOException e1) { + e1.printStackTrace(); + } + anim_gift.setImageDrawable(new BitmapDrawable(bitmap)); +// anim_gift.setImageBitmap(bitmap); + } + } + + /** + * 连击结束时回调 + */ + public void comboEndAnim() { + if (mHandler != null) { + if (mGiftCount > mCombo) {//连击 + mHandler.sendEmptyMessage(RESTART_GIFT_ANIMATION_CODE); + } else { + mCurrentAnimRunnable = new GiftNumAnimaRunnable(); + mHandler.postDelayed(mCurrentAnimRunnable, GIFT_DISMISS_TIME); + checkGiftCountSubscribe(); + } + } + } + + public AnimatorSet startAnimation(ICustormAnim anim) { + this.anim = anim; + if (anim == null) { + hideView(); + //布局飞入 + ObjectAnimator flyFromLtoR = GiftAnimationUtil.createFlyFromLtoR(anim_rl, -getWidth(), 0, 400, new OvershootInterpolator()); + flyFromLtoR.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + initLayoutState(); + } + }); + + //礼物飞入 + ObjectAnimator flyFromLtoR2 = GiftAnimationUtil.createFlyFromLtoR(anim_gift, -getWidth(), 0, 400, new DecelerateInterpolator()); + flyFromLtoR2.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + anim_gift.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + GiftAnimationUtil.startAnimationDrawable(anim_light); + anim_num.setVisibility(View.VISIBLE); + comboAnimation(); + } + }); + AnimatorSet animatorSet = GiftAnimationUtil.startAnimation(flyFromLtoR, flyFromLtoR2); + + return animatorSet; + } else { + return anim.startAnim(this, this); + } + } + + public void comboAnimation() { + if (anim == null) { + //数量增加 + ObjectAnimator scaleGiftNum = GiftAnimationUtil.scaleGiftNum(anim_num); + scaleGiftNum.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + anim_num.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + comboEndAnim(); + } + }); + scaleGiftNum.start(); + } else { + anim.comboAnim(this, this); + } + } + + public AnimatorSet endAnmation(ICustormAnim anim) { + if (anim == null) { + //向上渐变消失 + ObjectAnimator fadeAnimator = GiftAnimationUtil.createFadeAnimator(GiftFrameLayout.this, 0, -100, 100, 0); + fadeAnimator.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + anim_num.setVisibility(View.INVISIBLE); + } + }); + // 复原 + ObjectAnimator fadeAnimator2 = GiftAnimationUtil.createFadeAnimator(GiftFrameLayout.this, 100, 0, 0, 0); + + AnimatorSet animatorSet = GiftAnimationUtil.startAnimation(fadeAnimator, fadeAnimator2); + return animatorSet; + } else { + return anim.endAnim(this, this); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GlideCircleTransform.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GlideCircleTransform.java new file mode 100644 index 000000000..8e8f3dc18 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/GlideCircleTransform.java @@ -0,0 +1,63 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +import java.security.MessageDigest; + +/** + * + * + * Created by Skyline on 2016/5/24. + */ +public class GlideCircleTransform extends BitmapTransformation { + public GlideCircleTransform(Context context) { + super(context); + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { + return circleCrop(pool, toTransform); + } + + private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { + if (source == null) return null; + + int size = Math.min(source.getWidth(), source.getHeight()); + int x = (source.getWidth() - size) / 2; + int y = (source.getHeight() - size) / 2; + + // TODO this could be acquired from the pool too + Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); + + Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); + if (result == null) { + result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(result); + Paint paint = new Paint(); + paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); + paint.setAntiAlias(true); + float r = size / 2f; + canvas.drawCircle(r, r, r, paint); + return result; + } + +// @Override +// public String getId() { +// return getClass().getName(); +// } + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + messageDigest.update(getClass().getName().getBytes()); + } +} + diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/ICustormAnim.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/ICustormAnim.java new file mode 100644 index 000000000..cedc931c9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/ICustormAnim.java @@ -0,0 +1,14 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.animation.AnimatorSet; +import android.view.View; + +/** + * Created by KathLine on 2017/7/7. + */ + +public interface ICustormAnim { + AnimatorSet startAnim(GiftFrameLayout giftFrameLayout, View rootView); + AnimatorSet comboAnim(GiftFrameLayout giftFrameLayout, View rootView); + AnimatorSet endAnim(GiftFrameLayout giftFrameLayout, View rootView); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/NumberTextView.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/NumberTextView.java new file mode 100644 index 000000000..b502075ac --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/NumberTextView.java @@ -0,0 +1,92 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; + + +/** + * Created by KathLine on 2017/1/8. + */ +public class NumberTextView extends LinearLayout { + + private LinearLayout mNumberLl; + + private LayoutParams mLayoutParams; + + public NumberTextView(Context context) { + super(context); + init(); + } + + public NumberTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public NumberTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + LayoutInflater.from(getContext()).inflate(R.layout.number_calculator_layout, this); + mNumberLl = (LinearLayout) findViewById(R.id.numberLl); + mLayoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); +// mLayoutParams.leftMargin = -8; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + } + + public void updataNumber(String number) { + mNumberLl.removeAllViews(); + for (int i = 0; i < number.length(); i++) { + mNumberLl.addView(getTimerImage(number.charAt(i))); + } + } + + private ImageView getTimerImage(char number) { + ImageView image = new ImageView(getContext()); + switch (number) { + case '0': + image.setImageResource(R.mipmap.number_0); + break; + case '1': + image.setImageResource(R.mipmap.number_1); + break; + case '2': + image.setImageResource(R.mipmap.number_2); + break; + case '3': + image.setImageResource(R.mipmap.number_3); + break; + case '4': + image.setImageResource(R.mipmap.number_4); + break; + case '5': + image.setImageResource(R.mipmap.number_5); + break; + case '6': + image.setImageResource(R.mipmap.number_6); + break; + case '7': + image.setImageResource(R.mipmap.number_7); + break; + case '8': + image.setImageResource(R.mipmap.number_8); + break; + case '9': + image.setImageResource(R.mipmap.number_9); + break; + } + image.setLayoutParams(mLayoutParams); + return image; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/gift/widget/StrokeTextView.java b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/StrokeTextView.java new file mode 100644 index 000000000..681aba51a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/gift/widget/StrokeTextView.java @@ -0,0 +1,95 @@ +package com.yizhuan.erban.ui.gift.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +import java.lang.reflect.Field; + +/** + * Created by KathLine on 2017/1/8. + */ +public class StrokeTextView extends TextView { + + TextPaint m_TextPaint; + int mInnerColor; + int mOuterColor; + + public StrokeTextView(Context context, int outerColor, int innerColor) { + super(context); + m_TextPaint = this.getPaint(); + this.mInnerColor = innerColor; + this.mOuterColor = outerColor; + + // TODO Auto-generated constructor stub + } + + public StrokeTextView(Context context, AttributeSet attrs) { + super(context, attrs); + m_TextPaint = this.getPaint(); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StrokeTextView); + this.mInnerColor = a.getColor(R.styleable.StrokeTextView_innnerColor,0xffffff); + this.mOuterColor = a.getColor(R.styleable.StrokeTextView_outerColor,0xffffff); + a.recycle(); + + } + + public StrokeTextView(Context context, AttributeSet attrs, int defStyle, int outerColor, int innnerColor) { + super(context, attrs, defStyle); + m_TextPaint = this.getPaint(); + this.mInnerColor = innnerColor; + this.mOuterColor = outerColor; + // TODO Auto-generated constructor stub + } + + private boolean m_bDrawSideLine = true; // 默认采用描边 + + /** + * + */ + @Override + protected void onDraw(Canvas canvas) { + if (m_bDrawSideLine) { + // 描外层 + setTextColorUseReflection(mOuterColor); + m_TextPaint.setStrokeWidth(5); + m_TextPaint.setStyle(Paint.Style.FILL_AND_STROKE); + super.onDraw(canvas); + + // 描内层,恢复原先的画笔 + setTextColorUseReflection(mInnerColor); + m_TextPaint.setStrokeWidth(0); + m_TextPaint.setStyle(Paint.Style.FILL_AND_STROKE); + + } + super.onDraw(canvas); + } + + /** + * 使用反射的方法进行字体颜色的设置 + * @param color + */ + private void setTextColorUseReflection(int color) { + Field textColorField; + try { + textColorField = TextView.class.getDeclaredField("mCurTextColor"); + textColorField.setAccessible(true); + textColorField.set(this, color); + textColorField.setAccessible(false); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + m_TextPaint.setColor(color); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/GreetPresenter.java b/app/src/main/java/com/yizhuan/erban/ui/im/GreetPresenter.java new file mode 100644 index 000000000..4c75ce807 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/GreetPresenter.java @@ -0,0 +1,42 @@ +package com.yizhuan.erban.ui.im; + +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.im.GreetModel; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; + +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.functions.Function; + +public class GreetPresenter { + private static final String IS_GREETED = "is_greeted"; + private GreetModel greetModel; + private String mSessionId; + + public GreetPresenter(String sessionId) { + greetModel = new GreetModel(); + this.mSessionId = sessionId; + } + + public Single greetMsgGetOne(long uid, long toUid) { + return greetModel.greetMsgGetOne(uid, toUid).flatMap(new Function, SingleSource>() { + @Override + public SingleSource apply(ServiceResult stringServiceResult) throws Exception { + if (stringServiceResult.isSuccess()) { + setIsGreeted(mSessionId); + return Single.just(stringServiceResult.getData()); + } else { + return Single.just(""); + } + } + }); + } + + public boolean isCanSendGreet() { + return (boolean) SharedPreferenceUtils.get(mSessionId + IS_GREETED, true); + } + + public void setIsGreeted(String uid) { + SharedPreferenceUtils.put(uid + IS_GREETED, false); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/MessageListPanelEx.java b/app/src/main/java/com/yizhuan/erban/ui/im/MessageListPanelEx.java new file mode 100644 index 000000000..4c95830d6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/MessageListPanelEx.java @@ -0,0 +1,1435 @@ +package com.yizhuan.erban.ui.im; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.CountDownTimer; +import android.os.Handler; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Pair; +import android.view.View; +import android.widget.ImageView; + +import com.netease.nim.uikit.R; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.model.user.UserInfoObserver; +import com.netease.nim.uikit.business.contact.selector.activity.ContactSelectActivity; +import com.netease.nim.uikit.business.preference.UserPreferences; +import com.netease.nim.uikit.business.robot.parser.elements.group.LinkElement; +import com.netease.nim.uikit.business.session.activity.VoiceTrans; +import com.netease.nim.uikit.business.session.audio.MessageAudioControl; +import com.netease.nim.uikit.business.session.event.MessageEvent; +import com.netease.nim.uikit.business.session.helper.MessageHelper; +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.netease.nim.uikit.business.session.module.Container; +import com.netease.nim.uikit.business.session.module.list.IncomingMsgPrompt; +import com.netease.nim.uikit.business.session.module.list.MsgAdapter; +import com.netease.nim.uikit.business.session.viewholder.robot.RobotLinkView; +import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog; +import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialog; +import com.netease.nim.uikit.common.ui.dialog.EasyAlertDialogHelper; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseFetchLoadAdapter; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.IRecyclerView; +import com.netease.nim.uikit.common.ui.recyclerview.listener.OnItemClickListener; +import com.netease.nim.uikit.common.ui.recyclerview.loadmore.MsgListFetchLoadMoreView; +import com.netease.nim.uikit.common.util.media.BitmapDecoder; +import com.netease.nim.uikit.common.util.sys.ClipboardUtil; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.FileAttachment; +import com.netease.nimlib.sdk.msg.constant.AttachStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgDirectionEnum; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.AttachmentProgress; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.msg.model.RevokeMsgNotification; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; +import com.netease.nimlib.sdk.team.constant.TeamMemberType; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; +import com.yizhuan.xchat_android_core.im.game.ImGameInfo; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * 基于RecyclerView的消息收发模块 + * Created by huangjun on 2016/12/27. + */ +public class MessageListPanelEx { + + private static final int REQUEST_CODE_FORWARD_PERSON = 0x01; + private static final int REQUEST_CODE_FORWARD_TEAM = 0x02; + + // container + private Container container; + private View rootView; + + // message list view + private RecyclerView messageListView; + private List items; + private MsgAdapter adapter; + private ImageView listviewBk; + + // 新消息到达提醒 + private IncomingMsgPrompt incomingMsgPrompt; + private Handler uiHandler; + + // 仅显示消息记录,不接收和发送消息 + private boolean recordOnly; + // 从服务器拉取消息记录 + private boolean remote; + + // 语音转文字 + private VoiceTrans voiceTrans; + + // 待转发消息 + private IMMessage forwardMessage; + + // 背景图片缓存 + private static Pair background; + private CountDownTimer countDownTimer; + + public MessageListPanelEx(Container container, View rootView, boolean recordOnly, boolean remote) { + this(container, rootView, null, recordOnly, remote); + } + + public MessageListPanelEx(Container container, View rootView, IMMessage anchor, boolean recordOnly, boolean remote) { + this.container = container; + this.rootView = rootView; + this.recordOnly = recordOnly; + this.remote = remote; + + init(anchor); + } + + public void onResume() { + setEarPhoneMode(UserPreferences.isEarPhoneModeEnable(), false); + } + + public void onPause() { + MessageAudioControl.getInstance(container.activity).stopAudio(); + } + + public void onDestroy() { + registerObservers(false); + if (countDownTimer != null) { + countDownTimer.cancel(); + } + } + + public boolean onBackPressed() { + uiHandler.removeCallbacks(null); + if (countDownTimer != null) { + countDownTimer.cancel(); + } + MessageAudioControl.getInstance(container.activity).stopAudio(); // 界面返回,停止语音播放 + if (voiceTrans != null && voiceTrans.isShow()) { + voiceTrans.hide(); + return true; + } + return false; + } + + public void reload(Container container, IMMessage anchor) { + this.container = container; + if (adapter != null) { + adapter.clearData(); + } + + initFetchLoadListener(anchor); + } + + private void init(IMMessage anchor) { + initListView(anchor); + + this.uiHandler = new Handler(); + if (!recordOnly) { + incomingMsgPrompt = new IncomingMsgPrompt(container.activity, rootView, messageListView, adapter, uiHandler); + } + + registerObservers(true); + } + + private void initListView(IMMessage anchor) { + listviewBk = (ImageView) rootView.findViewById(R.id.message_activity_background); + + // RecyclerView + messageListView = (RecyclerView) rootView.findViewById(R.id.messageListView); + messageListView.setLayoutManager(new LinearLayoutManager(container.activity)); + messageListView.requestDisallowInterceptTouchEvent(true); + messageListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState != RecyclerView.SCROLL_STATE_IDLE) { + container.proxy.shouldCollapseInputPanel(); + } + } + }); + messageListView.setOverScrollMode(View.OVER_SCROLL_NEVER); + + // adapter + items = new ArrayList<>(); + adapter = new MsgAdapter(messageListView, items, container); + adapter.setFetchMoreView(new MsgListFetchLoadMoreView()); + adapter.setLoadMoreView(new MsgListFetchLoadMoreView()); + adapter.setEventListener(new MsgItemEventListener()); + initFetchLoadListener(anchor); + messageListView.setAdapter(adapter); + messageListView.addOnItemTouchListener(listener); + + startCountTime(); + } + + private OnItemClickListener listener = new OnItemClickListener() { + @Override + public void onItemClick(IRecyclerView adapter, View view, int position) { + + } + + @Override + public void onItemLongClick(IRecyclerView adapter, View view, int position) { + } + + @Override + public void onItemChildClick(IRecyclerView adapter2, View view, int position) { + if (isSessionMode() && view != null && view instanceof RobotLinkView) { + RobotLinkView robotLinkView = (RobotLinkView) view; + // robotLinkView.onClick(); + LinkElement element = robotLinkView.getElement(); + if (element != null) { + element.getTarget(); + if (LinkElement.TYPE_URL.equals(element.getType())) { + Intent intent = new Intent(); + intent.setAction("android.intent.action.VIEW"); + Uri content_url = Uri.parse(element.getTarget()); + intent.setData(content_url); + try { + container.activity.startActivity(intent); + } catch (ActivityNotFoundException e) { +// Toast.makeText(container.activity, "路径错误", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("路径错误"); + } + + } else if (LinkElement.TYPE_BLOCK.equals(element.getType())) { + // 发送点击的block + IMMessage message = adapter.getItem(position); + if (message != null) { + String robotAccount = ((RobotAttachment) message.getAttachment()).getFromRobotAccount(); + IMMessage robotMsg = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), robotAccount, + robotLinkView.getShowContent(), RobotMsgType.LINK, "", element.getTarget(), element.getParams()); + container.proxy.sendMessage(robotMsg); + } + } + } + } + } + }; + + public boolean isSessionMode() { + return !recordOnly && !remote; + } + + private void initFetchLoadListener(IMMessage anchor) { + MessageLoader loader = new MessageLoader(anchor, remote); + + if (recordOnly && !remote) { + // 双向Load + adapter.setOnFetchMoreListener(loader); + adapter.setOnLoadMoreListener(loader); + } else { + // 只下来加载old数据 + adapter.setOnFetchMoreListener(loader); + } + } + + // 刷新消息列表 + public void refreshMessageList() { + container.activity.runOnUiThread(new Runnable() { + + @Override + public void run() { + adapter.notifyDataSetChanged(); + } + }); + } + + public void scrollToBottom() { + uiHandler.postDelayed(new Runnable() { + @Override + public void run() { + doScrollToBottom(); + } + }, 200); + } + + private void doScrollToBottom() { + messageListView.scrollToPosition(adapter.getBottomDataPosition()); + } + + public void onIncomingMessage(List messages) { + boolean needScrollToBottom = isLastMessageVisible(); + boolean needRefresh = false; + List addedListItems = new ArrayList<>(messages.size()); + for (IMMessage message : messages) { + + if (isMyMessage(message)) { + if (message.getAttachment() instanceof ImGameAttachment) { + //防止手机时间不对做的兼容 + ImGameAttachment attachment = (ImGameAttachment) message.getAttachment(); + if (Math.abs(attachment.getImGameInfo().getStartTime() - System.currentTimeMillis()) > 1000) { + attachment.getImGameInfo().setStartTime(System.currentTimeMillis()); + NIMClient.getService(MsgService.class).updateIMMessageStatus(message); + } + startCountTime(); + } + + items.add(message); + addedListItems.add(message); + needRefresh = true; + + if (message.getAttachment() instanceof ImTipAttachment) { + if (((ImTipAttachment) message.getAttachment()).getSecond() == CustomAttachment.CUSTOM_MSG_IM_TIP_CANCEL) { + updateGameItemStatus(); + } + } + } + } + if (needRefresh) { + sortMessages(items); + adapter.notifyDataSetChanged(); + } + + adapter.updateShowTimeItem(addedListItems, false, true); + + // incoming messages tip + IMMessage lastMsg = messages.get(messages.size() - 1); + if (isMyMessage(lastMsg)) { + if (needScrollToBottom) { + doScrollToBottom(); + } else if (incomingMsgPrompt != null && lastMsg.getSessionType() != SessionTypeEnum.ChatRoom) { + incomingMsgPrompt.show(lastMsg); + } + } + } + + /** + * 收到约战取消的信息更改状态 + */ + private void updateGameItemStatus() { + int size = items.size(); + for (int i = size - 1; i >= (size > 50 ? size - 50 : 0); i--) { + IMMessage imMessage = items.get(i); + if (imMessage.getAttachment() instanceof ImGameAttachment) { + ImGameInfo imGameInfo = ((ImGameAttachment) imMessage.getAttachment()).getImGameInfo(); + imGameInfo.setStatus(ImGameInfo.INVALID); + ImGameAttachment attachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + attachment.setImGameInfo(imGameInfo); + imMessage.setAttachment(attachment); + NIMClient.getService(MsgService.class).updateIMMessageStatus(imMessage); + adapter.notifyDataItemChanged(i); + } + } + } + + private boolean isLastMessageVisible() { + LinearLayoutManager layoutManager = (LinearLayoutManager) messageListView.getLayoutManager(); + int lastVisiblePosition = layoutManager.findLastCompletelyVisibleItemPosition(); + return lastVisiblePosition >= adapter.getBottomDataPosition(); + } + + // 发送消息后,更新本地消息列表 + public void onMsgSend(IMMessage message) { + List addedListItems = new ArrayList<>(1); + addedListItems.add(message); + adapter.updateShowTimeItem(addedListItems, false, true); + + adapter.appendData(message); + + doScrollToBottom(); + } + + /** + * **************************** 排序 *********************************** + */ + private void sortMessages(List list) { + if (list.size() == 0) { + return; + } + Collections.sort(list, comp); + } + + private static Comparator comp = new Comparator() { + + @Override + public int compare(IMMessage o1, IMMessage o2) { + long time = o1.getTime() - o2.getTime(); + return time == 0 ? 0 : (time < 0 ? -1 : 1); + } + }; + + /** + * ************************* 观察者 ******************************** + */ + + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeMsgStatus(messageStatusObserver, register); + service.observeAttachmentProgress(attachmentProgressObserver, register); + service.observeRevokeMessage(revokeMessageObserver, register); + if (register) { + registerUserInfoObserver(); + } else { + unregisterUserInfoObserver(); + } + + MessageListPanelHelper.getInstance().registerObserver(incomingLocalMessageObserver, register); + } + + /** + * 消息状态变化观察者 + */ + private Observer messageStatusObserver = new Observer() { + @Override + public void onEvent(IMMessage message) { + if (isMyMessage(message)) { + onMessageStatusChange(message); + } + } + }; + + /** + * 消息附件上传/下载进度观察者 + */ + private Observer attachmentProgressObserver = new Observer() { + @Override + public void onEvent(AttachmentProgress progress) { + onAttachmentProgressChange(progress); + } + }; + + /** + * 本地消息接收观察者 + */ + private MessageListPanelHelper.LocalMessageObserver incomingLocalMessageObserver = new MessageListPanelHelper.LocalMessageObserver() { + @Override + public void onAddMessage(IMMessage message) { + if (message == null || !container.account.equals(message.getSessionId())) { + return; + } + + onMsgSend(message); + } + + @Override + public void onClearMessages(String account) { + items.clear(); + refreshMessageList(); + adapter.fetchMoreEnd(null, true); + } + }; + + /** + * 消息撤回观察者 + */ + private Observer revokeMessageObserver = new Observer() { + @Override + public void onEvent(RevokeMsgNotification notification) { + if (notification == null || notification.getMessage() == null) { + return; + } + IMMessage message = notification.getMessage(); + + if (!container.account.equals(message.getSessionId())) { + return; + } + + deleteItem(message, false); + } + }; + + private void onMessageStatusChange(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(message.getStatus()); + item.setAttachStatus(message.getAttachStatus()); + + // 处理语音、音视频通话 + if (item.getMsgType() == MsgTypeEnum.audio || item.getMsgType() == MsgTypeEnum.avchat) { + item.setAttachment(message.getAttachment()); // 附件可能更新了 + } + + // resend的的情况,可能时间已经变化了,这里要重新检查是否要显示时间 + List msgList = new ArrayList<>(1); + msgList.add(message); + adapter.updateShowTimeItem(msgList, false, true); + + refreshViewHolderByIndex(index); + } + } + + private void onAttachmentProgressChange(AttachmentProgress progress) { + int index = getItemIndex(progress.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + float value = (float) progress.getTransferred() / (float) progress.getTotal(); + adapter.putProgress(item, value); + refreshViewHolderByIndex(index); + } + } + + public boolean isMyMessage(IMMessage message) { + return message.getSessionType() == container.sessionType + && message.getSessionId() != null + && message.getSessionId().equals(container.account); + } + + /** + * 刷新单条消息 + */ + public void refreshViewHolderByIndex(final int index) { + container.activity.runOnUiThread(new Runnable() { + + @Override + public void run() { + if (index < 0) { + return; + } + + adapter.notifyDataItemChanged(index); + } + }); + } + + public int getItemIndex(String uuid) { + for (int i = 0; i < items.size(); i++) { + IMMessage message = items.get(i); + if (TextUtils.equals(message.getUuid(), uuid)) { + return i; + } + } + + return -1; + } + + public void setChattingBackground(String uriString, int color) { + if (uriString != null) { + Uri uri = Uri.parse(uriString); + if (uri.getScheme().equalsIgnoreCase("file") && uri.getPath() != null) { + listviewBk.setImageBitmap(getBackground(uri.getPath())); + } else if (uri.getScheme().equalsIgnoreCase("android.resource")) { + List paths = uri.getPathSegments(); + if (paths == null || paths.size() != 2) { + return; + } + String type = paths.get(0); + String name = paths.get(1); + String pkg = uri.getHost(); + int resId = container.activity.getResources().getIdentifier(name, type, pkg); + if (resId != 0) { + listviewBk.setBackgroundResource(resId); + } + } + } else if (color != 0) { + listviewBk.setBackgroundColor(color); + } + } + + /** + * 收到自定义系统通知时更改某条item的状态 + * + * @param imGameInfo + */ + public void receiveCustomNotification(ImGameInfo imGameInfo) { + int size = items.size(); + for (int i = size - 1; i >= 0; i--) { + if (items.get(i).getUuid().equals(imGameInfo.getUuId())) { + IMMessage message = items.get(i); + ImGameAttachment attachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + attachment.setImGameInfo(imGameInfo); + message.setAttachment(attachment); + NIMClient.getService(MsgService.class).updateIMMessageStatus(message); + adapter.notifyDataItemChanged(i); + break; + } + } + + } + + /** + * ***************************************** 数据加载 ********************************************* + */ + + private class MessageLoader implements BaseFetchLoadAdapter.RequestLoadMoreListener, BaseFetchLoadAdapter.RequestFetchMoreListener { + + private int loadMsgCount = NimUIKitImpl.getOptions().messageCountLoadOnce; + + private QueryDirectionEnum direction = null; + + private IMMessage anchor; + private boolean remote; + + private boolean firstLoad = true; + + public MessageLoader(IMMessage anchor, boolean remote) { + this.anchor = anchor; + this.remote = remote; + if (remote) { + loadFromRemote(); + } else { + if (anchor == null) { + loadFromLocal(QueryDirectionEnum.QUERY_OLD); + } else { + loadAnchorContext(); // 加载指定anchor的上下文 + } + } + } + + private RequestCallback> callback = new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List messages, Throwable exception) { + if (code != ResponseCode.RES_SUCCESS || exception != null) { + if (direction == QueryDirectionEnum.QUERY_OLD) { + adapter.fetchMoreFailed(); + } else if (direction == QueryDirectionEnum.QUERY_NEW) { + adapter.loadMoreFail(); + } + + return; + } + + if (messages != null) { + onMessageLoaded(messages); + } + } + }; + + private void loadAnchorContext() { + // query new, auto load old + direction = QueryDirectionEnum.QUERY_NEW; + NIMClient.getService(MsgService.class).queryMessageListEx(anchor(), direction, loadMsgCount, true) + .setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List messages, Throwable exception) { + if (code != ResponseCode.RES_SUCCESS || exception != null) { + return; + } + + onAnchorContextMessageLoaded(messages); + } + }); + } + + private void loadFromLocal(QueryDirectionEnum direction) { + this.direction = direction; + NIMClient.getService(MsgService.class).queryMessageListEx(anchor(), direction, loadMsgCount, true) + .setCallback(callback); + } + + private void loadFromRemote() { + this.direction = QueryDirectionEnum.QUERY_OLD; + NIMClient.getService(MsgService.class).pullMessageHistory(anchor(), loadMsgCount, true) + .setCallback(callback); + } + + private IMMessage anchor() { + if (items.size() == 0) { + return anchor == null ? MessageBuilder.createEmptyMessage(container.account, container.sessionType, 0) : anchor; + } else { + int index = (direction == QueryDirectionEnum.QUERY_NEW ? items.size() - 1 : 0); + return items.get(index); + } + } + + private void onMessageLoaded(List messages) { + if (messages == null) { + return; + } + //服务器加载的时间不对的游戏直接失效 + for (IMMessage message : messages) { + if (message.getAttachment() instanceof ImGameAttachment) { + ImGameAttachment attachment = (ImGameAttachment) message.getAttachment(); + ImGameAttachment imGameAttachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + if (attachment.getImGameInfo().getStartTime() > System.currentTimeMillis()) { + attachment.getImGameInfo().setStatus(ImGameInfo.INVALID) + .setUuId(message.getUuid()); + imGameAttachment.setImGameInfo(attachment.getImGameInfo()); + message.setAttachment(imGameAttachment); + } + } + } + if (onMessageFilterListener != null) { + messages = onMessageFilterListener.filterLoadedMessage(messages); + } + boolean noMoreMessage = messages.size() < loadMsgCount; + + if (remote) { + Collections.reverse(messages); + } + + // 在第一次加载的过程中又收到了新消息,做一下去重 + if (firstLoad && items.size() > 0) { + for (IMMessage message : messages) { + int removeIndex = 0; + for (IMMessage item : items) { + if (item.isTheSame(message)) { + adapter.remove(removeIndex); + break; + } + removeIndex++; + } + } + } + + // 加入anchor + if (firstLoad && anchor != null) { + messages.add(anchor); + } + + // 在更新前,先确定一些标记 + List total = new ArrayList<>(); + total.addAll(items); + boolean isBottomLoad = direction == QueryDirectionEnum.QUERY_NEW; + if (isBottomLoad) { + total.addAll(messages); + } else { + total.addAll(0, messages); + } + adapter.updateShowTimeItem(total, true, firstLoad); // 更新要显示时间的消息 + updateReceipt(total); // 更新已读回执标签 + + // 加载状态修改,刷新界面 + if (isBottomLoad) { + // 底部加载 + if (noMoreMessage) { + adapter.loadMoreEnd(messages, true); + } else { + adapter.loadMoreComplete(messages); + } + } else { + // 顶部加载 + if (noMoreMessage) { + adapter.fetchMoreEnd(messages, true); + } else { + adapter.fetchMoreComplete(messages); + } + } + + // 如果是第一次加载,updateShowTimeItem返回的就是lastShowTimeItem + if (firstLoad) { + doScrollToBottom(); + sendReceipt(); // 发送已读回执 + } + + firstLoad = false; + } + + private void onAnchorContextMessageLoaded(final List messages) { + if (messages == null) { + return; + } + + if (remote) { + Collections.reverse(messages); + } + + int loadCount = messages.size(); + if (firstLoad && anchor != null) { + messages.add(0, anchor); + } + + // 在更新前,先确定一些标记 + adapter.updateShowTimeItem(messages, true, firstLoad); // 更新要显示时间的消息 + updateReceipt(messages); // 更新已读回执标签 + + // new data + if (loadCount < loadMsgCount) { + adapter.loadMoreEnd(messages, true); + } else { + adapter.appendData(messages); + } + + firstLoad = false; + } + + @Override + public void onFetchMoreRequested() { + // 顶部加载历史数据 + if (remote) { + loadFromRemote(); + } else { + loadFromLocal(QueryDirectionEnum.QUERY_OLD); + } + } + + @Override + public void onLoadMoreRequested() { + // 底部加载新数据 + if (!remote) { + loadFromLocal(QueryDirectionEnum.QUERY_NEW); + } + } + } + + private class MsgItemEventListener implements MsgAdapter.ViewHolderEventListener { + + @Override + public void onFailedBtnClick(IMMessage message) { + if (message.getDirect() == MsgDirectionEnum.Out) { + // 发出的消息,如果是发送失败,直接重发,否则有可能是漫游到的多媒体消息,但文件下载 + if (message.getStatus() == MsgStatusEnum.fail) { + resendMessage(message); // 重发 + } else { + if (message.getAttachment() instanceof FileAttachment) { + FileAttachment attachment = (FileAttachment) message.getAttachment(); + if (TextUtils.isEmpty(attachment.getPath()) + && TextUtils.isEmpty(attachment.getThumbPath())) { + showReDownloadConfirmDlg(message); + } + } else { + resendMessage(message); + } + } + } else { + showReDownloadConfirmDlg(message); + } + } + + @Override + public boolean onViewHolderLongClick(View clickView, View viewHolderView, IMMessage item) { + if (container.proxy.isLongClickEnabled()) { + showLongClickAction(item); + } + return true; + } + + @Override + public void onFooterClick(IMMessage message) { + // 与 robot 对话 + container.proxy.onItemFooterClick(message); + } + + // 重新下载(对话框提示) + private void showReDownloadConfirmDlg(final IMMessage message) { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + // 正常情况收到消息后附件会自动下载。如果下载失败,可调用该接口重新下载 + if (message.getAttachment() != null && message.getAttachment() instanceof FileAttachment) + NIMClient.getService(MsgService.class).downloadAttachment(message, true); + } + }; + + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(container.activity, null, + container.activity.getString(R.string.repeat_download_message), true, listener); + dialog.show(); + } + + // 重发消息到服务器 + private void resendMessage(IMMessage message) { + // 重置状态为unsent + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + IMMessage item = items.get(index); + item.setStatus(MsgStatusEnum.sending); + deleteItem(item, true); + onMsgSend(item); + } + + NIMClient.getService(MsgService.class) + .sendMessage(message, true) + .setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, Void result, Throwable exception) { + } + }); + } + + /** + * ****************************** 长按菜单 ******************************** + */ + + // 长按消息Item后弹出菜单控制 + private void showLongClickAction(IMMessage selectedItem) { + onNormalLongClick(selectedItem); + } + + /** + * 长按菜单操作 + * + * @param item + */ + private void onNormalLongClick(IMMessage item) { + CustomAlertDialog alertDialog = new CustomAlertDialog(container.activity); + alertDialog.setCancelable(true); + alertDialog.setCanceledOnTouchOutside(true); + + prepareDialogItems(item, alertDialog); + alertDialog.show(); + } + + // 长按消息item的菜单项准备。如果消息item的MsgViewHolder处理长按事件(MsgViewHolderBase#onItemLongClick),且返回为true, + // 则对应项的长按事件不会调用到此处 + private void prepareDialogItems(final IMMessage selectedItem, CustomAlertDialog alertDialog) { + MsgTypeEnum msgType = selectedItem.getMsgType(); + + MessageAudioControl.getInstance(container.activity).stopAudio(); + + // 0 EarPhoneMode + longClickItemEarPhoneMode(alertDialog, msgType); + // 1 resend + longClickItemResend(selectedItem, alertDialog); + // 2 copy + longClickItemCopy(selectedItem, alertDialog, msgType); + // 3 revoke + if (enableRevokeButton(selectedItem)) { + longClickRevokeMsg(selectedItem, alertDialog); + } + // 4 delete + longClickItemDelete(selectedItem, alertDialog); + // 5 trans + longClickItemVoidToText(selectedItem, alertDialog, msgType); + + if (NimUIKitImpl.getMsgForwardFilter() != null && !NimUIKitImpl.getMsgForwardFilter().shouldIgnore(selectedItem) && !recordOnly) { + // 6 forward to person + longClickItemForwardToPerson(selectedItem, alertDialog); + // 7 forward to team + longClickItemForwardToTeam(selectedItem, alertDialog); + } + } + + private boolean enableRevokeButton(IMMessage selectedItem) { + if (selectedItem.getStatus() == MsgStatusEnum.success + && NimUIKitImpl.getMsgRevokeFilter() != null + && !NimUIKitImpl.getMsgRevokeFilter().shouldIgnore(selectedItem) + && !recordOnly) { + if (selectedItem.getDirect() == MsgDirectionEnum.Out) { + return true; + } else if (NimUIKit.getOptions().enableTeamManagerRevokeMsg && selectedItem.getSessionType() == SessionTypeEnum.Team) { + TeamMember member = NimUIKit.getTeamProvider().getTeamMember(selectedItem.getSessionId(), NimUIKit.getAccount()); + return member != null && member.getType() == TeamMemberType.Owner || member.getType() == TeamMemberType.Manager; + } + } + return false; + } + + // 长按菜单项--重发 + private void longClickItemResend(final IMMessage item, CustomAlertDialog alertDialog) { + if (item.getStatus() != MsgStatusEnum.fail) { + return; + } + alertDialog.addItem(container.activity.getString(R.string.repeat_send_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + onResendMessageItem(item); + } + }); + } + + private void onResendMessageItem(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0) { + showResendConfirm(message, index); // 重发确认 + } + } + + private void showResendConfirm(final IMMessage message, final int index) { + EasyAlertDialogHelper.OnDialogActionListener listener = new EasyAlertDialogHelper.OnDialogActionListener() { + + @Override + public void doCancelAction() { + } + + @Override + public void doOkAction() { + resendMessage(message); + } + }; + final EasyAlertDialog dialog = EasyAlertDialogHelper.createOkCancelDiolag(container.activity, null, + container.activity.getString(R.string.repeat_send_message), true, listener); + dialog.show(); + } + + // 长按菜单项--复制 + private void longClickItemCopy(final IMMessage item, CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType == MsgTypeEnum.text || + (msgType == MsgTypeEnum.robot && item.getAttachment() != null && !((RobotAttachment) item.getAttachment()).isRobotSend())) { + alertDialog.addItem(container.activity.getString(R.string.copy_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + onCopyMessageItem(item); + } + }); + } + } + + private void onCopyMessageItem(IMMessage item) { + ClipboardUtil.clipboardCopyText(container.activity, item.getContent()); + } + + // 长按菜单项--删除 + private void longClickItemDelete(final IMMessage selectedItem, CustomAlertDialog alertDialog) { + if (recordOnly) { + return; + } + alertDialog.addItem(container.activity.getString(R.string.delete_has_blank), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + deleteItem(selectedItem, true); + } + }); + } + + // 长按菜单项 -- 音频转文字 + private void longClickItemVoidToText(final IMMessage item, CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType != MsgTypeEnum.audio) return; + + if (item.getDirect() == MsgDirectionEnum.In + && item.getAttachStatus() != AttachStatusEnum.transferred) + return; + if (item.getDirect() == MsgDirectionEnum.Out + && item.getAttachStatus() != AttachStatusEnum.transferred) + return; + + alertDialog.addItem(container.activity.getString(R.string.voice_to_text), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + onVoiceToText(item); + } + }); + } + + // 语音转文字 + private void onVoiceToText(IMMessage item) { + if (voiceTrans == null) + voiceTrans = new VoiceTrans(container.activity); + voiceTrans.voiceToText(item); + if (item.getDirect() == MsgDirectionEnum.In && item.getStatus() != MsgStatusEnum.read) { + item.setStatus(MsgStatusEnum.read); + NIMClient.getService(MsgService.class).updateIMMessageStatus(item); + adapter.notifyDataSetChanged(); + } + } + + // 长按菜单项 -- 听筒扬声器切换 + private void longClickItemEarPhoneMode(CustomAlertDialog alertDialog, MsgTypeEnum msgType) { + if (msgType != MsgTypeEnum.audio) return; + + String content = UserPreferences.isEarPhoneModeEnable() ? "切换成扬声器播放" : "切换成听筒播放"; + final String finalContent = content; + alertDialog.addItem(content, new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { +// Toast.makeText(container.activity, finalContent, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(finalContent); + setEarPhoneMode(!UserPreferences.isEarPhoneModeEnable(), true); + } + }); + } + + // 长按菜单项 -- 转发到个人 + private void longClickItemForwardToPerson(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.forward_to_person), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + forwardMessage = item; + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "选择转发的人"; + option.type = ContactSelectActivity.ContactSelectType.BUDDY; + option.multi = false; + option.maxSelectNum = 1; + NimUIKit.startContactSelector(container.activity, option, REQUEST_CODE_FORWARD_PERSON); + } + }); + } + + // 长按菜单项 -- 转发到群组 + private void longClickItemForwardToTeam(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.forward_to_team), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + forwardMessage = item; + ContactSelectActivity.Option option = new ContactSelectActivity.Option(); + option.title = "选择转发的群"; + option.type = ContactSelectActivity.ContactSelectType.TEAM; + option.multi = false; + option.maxSelectNum = 1; + NimUIKit.startContactSelector(container.activity, option, REQUEST_CODE_FORWARD_TEAM); + } + }); + } + + // 长按菜单项 -- 撤回消息 + private void longClickRevokeMsg(final IMMessage item, CustomAlertDialog alertDialog) { + alertDialog.addItem(container.activity.getString(R.string.withdrawn_msg), new CustomAlertDialog.onSeparateItemClickListener() { + + @Override + public void onClick() { + if (!NetworkUtil.isNetAvailable(container.activity)) { +// Toast.makeText(container.activity, R.string.network_is_not_available, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.network_is_not_available); + return; + } + NIMClient.getService(MsgService.class).revokeMessage(item).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + deleteItem(item, false); + MessageHelper.getInstance().onRevokeMessage(item, NimUIKit.getAccount()); + } + + @Override + public void onFailed(int code) { + if (code == ResponseCode.RES_OVERDUE) { +// Toast.makeText(container.activity, R.string.revoke_failed, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(R.string.revoke_failed); + } else { +// Toast.makeText(container.activity, "revoke msg failed, code:" + code, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("revoke msg failed, code:" + code); + } + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + }); + } + + } + + private void setEarPhoneMode(boolean earPhoneMode, boolean update) { + if (update) { + UserPreferences.setEarPhoneModeEnable(earPhoneMode); + } + MessageAudioControl.getInstance(container.activity).setEarPhoneModeEnable(earPhoneMode); + } + + private Bitmap getBackground(String path) { + if (background != null && path.equals(background.first) && background.second != null) { + return background.second; + } + + if (background != null && background.second != null) { + background.second.recycle(); + } + + Bitmap bitmap = null; + if (path.startsWith("/android_asset")) { + String asset = path.substring(path.indexOf("/", 1) + 1); + try { + InputStream ais = container.activity.getAssets().open(asset); + bitmap = BitmapDecoder.decodeSampled(ais, ScreenUtil.screenWidth, ScreenUtil.screenHeight); + ais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + bitmap = BitmapDecoder.decodeSampled(path, ScreenUtil.screenWidth, ScreenUtil.screenHeight); + } + background = new Pair<>(path, bitmap); + return bitmap; + } + + private UserInfoObserver uinfoObserver; + + private void registerUserInfoObserver() { + if (uinfoObserver == null) { + uinfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + if (container.sessionType == SessionTypeEnum.P2P) { + if (accounts.contains(container.account) || accounts.contains(NimUIKit.getAccount())) { + adapter.notifyDataSetChanged(); + } + } else { // 群的,简单的全部重刷 + adapter.notifyDataSetChanged(); + } + } + }; + } + + NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, true); + } + + private void unregisterUserInfoObserver() { + if (uinfoObserver != null) { + NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, false); + } + } + + /** + * 收到已读回执(更新VH的已读label) + */ + + public void receiveReceipt() { + updateReceipt(items); + refreshMessageList(); + } + + public void updateReceipt(final List messages) { + for (int i = messages.size() - 1; i >= 0; i--) { + if (receiveReceiptCheck(messages.get(i))) { + adapter.setUuid(messages.get(i).getUuid()); + break; + } + } + } + + private boolean receiveReceiptCheck(final IMMessage msg) { + if (msg != null && msg.getSessionType() == SessionTypeEnum.P2P + && msg.getDirect() == MsgDirectionEnum.Out + && msg.getMsgType() != MsgTypeEnum.tip + && msg.getMsgType() != MsgTypeEnum.notification + && msg.isRemoteRead()) { + return true; + } + + return false; + } + + /** + * 发送已读回执(需要过滤) + */ + + public void sendReceipt() { + // 查询全局已读回执功能开关配置 + if (!NimUIKitImpl.getOptions().shouldHandleReceipt) { + return; + } + + if (container.account == null || container.sessionType != SessionTypeEnum.P2P) { + return; + } + + IMMessage message = getLastReceivedMessage(); + if (!sendReceiptCheck(message)) { + return; + } + + NIMClient.getService(MsgService.class).sendMessageReceipt(container.account, message); + } + + private IMMessage getLastReceivedMessage() { + IMMessage lastMessage = null; + for (int i = items.size() - 1; i >= 0; i--) { + if (sendReceiptCheck(items.get(i))) { + lastMessage = items.get(i); + break; + } + } + + return lastMessage; + } + + private boolean sendReceiptCheck(final IMMessage msg) { + if (msg == null || msg.getDirect() != MsgDirectionEnum.In || + msg.getMsgType() == MsgTypeEnum.tip || msg.getMsgType() == MsgTypeEnum.notification) { + return false; // 非收到的消息,Tip消息和通知类消息,不要发已读回执 + } + + return true; + } + + // 删除消息 + private void deleteItem(IMMessage messageItem, boolean isRelocateTime) { + NIMClient.getService(MsgService.class).deleteChattingHistory(messageItem); + List messages = new ArrayList<>(); + for (IMMessage message : items) { + if (message.getUuid().equals(messageItem.getUuid())) { + continue; + } + messages.add(message); + } + updateReceipt(messages); + adapter.deleteItem(messageItem, isRelocateTime); + } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode != Activity.RESULT_OK) { + return; + } + final ArrayList selected = data.getStringArrayListExtra(ContactSelectActivity.RESULT_DATA); + if (selected != null && !selected.isEmpty()) { + switch (requestCode) { + case REQUEST_CODE_FORWARD_TEAM: + doForwardMessage(selected.get(0), SessionTypeEnum.Team); + break; + case REQUEST_CODE_FORWARD_PERSON: + doForwardMessage(selected.get(0), SessionTypeEnum.P2P); + break; + } + } + } + + // 转发消息 + private void doForwardMessage(final String sessionId, SessionTypeEnum sessionTypeEnum) { + IMMessage message; + if (forwardMessage.getMsgType() == MsgTypeEnum.robot) { + message = buildForwardRobotMessage(sessionId, sessionTypeEnum); + } else { + message = MessageBuilder.createForwardMessage(forwardMessage, sessionId, sessionTypeEnum); + } + + if (message == null) { +// Toast.makeText(container.activity, "该类型不支持转发", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("该类型不支持转发"); + return; + } + + NIMClient.getService(MsgService.class) + .sendMessage(message, false) + .setCallback(new RequestCallbackWrapper() { + @Override + public void onResult(int code, Void result, Throwable exception) { + } + }); + if (container.account.equals(sessionId)) { + onMsgSend(message); + } + } + + private IMMessage buildForwardRobotMessage(final String sessionId, SessionTypeEnum sessionTypeEnum) { + if (forwardMessage.getMsgType() == MsgTypeEnum.robot && forwardMessage.getAttachment() != null) { + RobotAttachment robotAttachment = (RobotAttachment) forwardMessage.getAttachment(); + if (robotAttachment.isRobotSend()) { + return null; // 机器人发的消息不能转发了 + } + + return MessageBuilder.createTextMessage(sessionId, sessionTypeEnum, forwardMessage.getContent()); + } + + return null; + } + + private OnMessageFilterListener onMessageFilterListener; + + public void setOnMessageFilterListener(OnMessageFilterListener onMessageFilterListener) { + this.onMessageFilterListener = onMessageFilterListener; + } + + public interface OnMessageFilterListener { + List filterLoadedMessage(List messages); + } + + /** + * 倒计时 + */ + public void startCountTime() { + if (null == countDownTimer) { + countDownTimer = new CountDownTimer(120 * 1000, 1000) { + @Override + public void onTick(long millisUntilFinished) { + + int size = items.size(); + boolean havaGame = false; + for (int i = size - 1; i >= 0; i--) { + if (items.get(i).getAttachment() instanceof ImGameAttachment) { + ImGameInfo imGameInfo = ((ImGameAttachment) items.get(i).getAttachment()).getImGameInfo(); + if (imGameInfo.getTime() > 0) { + imGameInfo.setTime((int) (imGameInfo.getStartTime() + ImGameMode.TIME * 1000 - System.currentTimeMillis()) / 1000); + } else if (imGameInfo.getStatus() != ImGameInfo.ACCEPTED) { + imGameInfo.setStatus(ImGameInfo.INVALID); + } + adapter.notifyDataItemChanged(i); + } + } +// if (!havaGame) { +// countDownTimer.cancel(); +// countDownTimer = null; +// } + } + + @Override + public void onFinish() { + countDownTimer = null; + boolean isNeedCountTime = false; + int size = items.size(); + for (int i = size - 1; i >= 0; i--) { + if (items.get(i).getAttachment() instanceof ImGameAttachment) { + ImGameInfo imGameInfo = ((ImGameAttachment) items.get(i).getAttachment()).getImGameInfo(); + if (imGameInfo.getStartTime() + ImGameMode.TIME * 1000 > System.currentTimeMillis()) { + isNeedCountTime = true; + break; + } + } + } + if (isNeedCountTime) { + startCountTime(); + } + } + }; + countDownTimer.start(); + } + } + + /** + * 是否有发起中的游戏 + * + * @return + */ + public boolean isGameing() { + boolean isGameing = false; + for (int i = items.size() - 1; i >= (items.size() > 50 ? items.size() - 50 : 0); i--) { + IMMessage imMessage = items.get(i); + if (imMessage.getAttachment() instanceof ImGameAttachment) { + ImGameInfo imGameInfo = ((ImGameAttachment) imMessage.getAttachment()).getImGameInfo(); + if (imGameInfo.getStartTime() + ImGameMode.TIME * 1000 > System.currentTimeMillis() + && imMessage.getFromAccount().equals(AuthModel.get().getCurrentUid() + "") + && imGameInfo.getStatus() == ImGameInfo.TIMEING) { + ImGameAttachment attachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + imGameInfo.setStatus(ImGameInfo.INVALID); + attachment.setImGameInfo(imGameInfo); + imMessage.setAttachment(attachment); + NIMClient.getService(MsgService.class).updateIMMessageStatus(imMessage); + isGameing = true; + ImGameMode.get().cancelGame(imMessage.getUuid()).subscribe(); + } + } + } + return isGameing; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/RouterHandler.java b/app/src/main/java/com/yizhuan/erban/ui/im/RouterHandler.java new file mode 100644 index 000000000..697aa9997 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/RouterHandler.java @@ -0,0 +1,356 @@ +package com.yizhuan.erban.ui.im; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.VoiceMatchActivity; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.recommendcard.MyRecommendCardActivity; +import com.yizhuan.erban.base.DialogManagerInterface; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.decoration.view.MyDecorationActivity; +import com.yizhuan.erban.family.view.activity.FamilyCurrencyActivity; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.home.activity.AllGameActivity; +import com.yizhuan.erban.home.dialog.SexMatchDialog; +import com.yizhuan.erban.miniworld.activity.MiniWorldGuestPageActivity; +import com.yizhuan.erban.miniworld.activity.MiniWorldMainActivity; +import com.yizhuan.erban.module_hall.hall.activity.ModuleHallActivity; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.erban.radish.signin.SignInActivity; +import com.yizhuan.erban.radish.task.activity.TaskCenterActivity; +import com.yizhuan.erban.team.view.NimTeamMessageActivity; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.login.ShowBindPhoneActivity; +import com.yizhuan.erban.ui.patriarch.help.LimitEnterRoomHelper; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.wallet.WalletActivity; +import com.yizhuan.erban.ui.wallet.WalletGoldActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity; +import com.yizhuan.tutu.mentoring_relationship.activity.MentoringRelationshipActivity; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.community.event.SquareTaskEvent; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.RouterType; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.module_hall.hall.HallModel; +import com.yizhuan.xchat_android_core.module_hall.hall.bean.HallInfo; +import com.yizhuan.xchat_android_core.patriarch.exception.PmRoomLimitException; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +/** + * Created by MadisonRong on 08/06/2018. + */ + +public class RouterHandler { + + private static final String IS_FIRST = "isFirst"; + + private static final int TIME_DIFF = 600; + private static long lastClickTime; + + public static boolean handle(Context context, int routerType, String routerValue) { + if (System.currentTimeMillis() - lastClickTime < TIME_DIFF) { + return false; + } + lastClickTime = System.currentTimeMillis(); + DialogManagerInterface dmi; + switch (routerType) { + case RouterType.ROOM: + AVRoomActivity.start(context, JavaUtil.str2long(routerValue)); + break; + case RouterType.H5: + CommonWebViewActivity.start(context, routerValue); + break; + case RouterType.WALLET: + context.startActivity(new Intent(context, WalletGoldActivity.class)); + break; + case RouterType.RED: + WalletActivity.start(context, 2); + break; + case RouterType.RECHARGE: + ChargeActivity.start(context); + break; + case RouterType.PERSON: + UserInfoActivity.Companion.start(context, JavaUtil.str2long(routerValue)); + break; + case RouterType.CAR: + if (JavaUtil.str2int(routerValue) == 0) { + DecorationStoreActivity.start(context, AuthModel.get().getCurrentUid(), DecorationStoreActivity.TAB_CAR); + } else { + MyDecorationActivity.start(context, 1); + } + break; + case RouterType.DECORATION: + if (JavaUtil.str2int(routerValue) == 0) { + DecorationStoreActivity.start(context, AuthModel.get().getCurrentUid()); + } else { + MyDecorationActivity.start(context, 0); + } + break; + + case RouterType.SYS_MSG: + FamilyCurrencyActivity.start(context); + break; + + case RouterType.FAMILY: + FamilyHomeActivity.start(context, routerValue); + break; + + case RouterType.TEAM: + NimTeamMessageActivity.start(context, routerValue); + break; + + case RouterType.PUBLIC_CHAT_HALL: + PublicChatHallHomeActivity.openPublicChatHallPage(context); + break; + + case RouterType.BINDING_ALI_PAY_ACCOUNT: + WithdrawModel.get().getWithdrawUserInfo(AuthModel.get().getCurrentUid()) + .subscribe(withdrawInfo -> { + if (withdrawInfo != null) { + if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) { + Intent intent = new Intent(context, BinderAlipayActivity.class); + Bundle mBundle = new Bundle(); + mBundle.putSerializable("withdrawInfo", withdrawInfo); + intent.putExtras(mBundle); + context.startActivity(intent); + } else { + context.startActivity(new Intent(context, BinderPhoneActivity.class)); + } + } + }); + break; + + case RouterType.BINDING_PHONE: + AuthModel.get().isBindPhone() + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + ShowBindPhoneActivity.start(context); + } + + @Override + public void onError(Throwable e) { + context.startActivity(new Intent(context, BinderPhoneActivity.class)); + } + }); + break; + + case RouterType.SETTING_PAY_PWD: + if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) { + ModifyPwdActivity.start(context, ModifyPwdActivity.PAY_PWD); + } else { + context.startActivity(new Intent(context, BinderPhoneActivity.class)); + } + break; + //推荐卡仓库 + case RouterType.MY_RECOMMEND: + MyRecommendCardActivity.start(context); + break; + case RouterType.MODULE_HALL_HOME: + DialogManager manager = new DialogManager(context); + manager.showProgressDialog(context); + HallModel.get().getHallInfo(AuthModel.get().getCurrentUid(), JavaUtil.str2long(routerValue)) + .compose(RxHelper.bindContext(context)) + .doAfterTerminate(manager::dismissDialog) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + } + + @Override + public void onSuccess(HallInfo hallInfo) { + ModuleHallActivity.start(context); + } + }); + break; + + case RouterType.MENTORING_RELATIONSHIP_HOME: + MentoringRelationshipActivity.start(context); + break; + case RouterType.SIGN_IN: + SignInActivity.start(context); + break; + case RouterType.DO_TASK: + TaskCenterActivity.start(context, TaskCenterActivity.FromPage.FIND); + break; + case RouterType.GAME_LIST: + context.startActivity(new Intent(context, AllGameActivity.class)); + break; + + case RouterType.PERSION_SETTING: + UIHelper.showUserInfoModifyAct(context, JavaUtil.str2long(routerValue)); + break; + case RouterType.MY_VOICE: + UIHelper.showMyVoiceAct(context); + break; + case RouterType.VOICE_BOTTLE_PAGE: + VoiceMatchActivity.start(context); + break; + //嗨聊派对 + case RouterType.CHAT_PARTY: + + if (!(context instanceof DialogManagerInterface) || !(context instanceof RxAppCompatActivity)) { + return false; + } + dmi = (DialogManagerInterface) context; + RxAppCompatActivity rxAppCompatActivity = (RxAppCompatActivity) context; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_hiparty, "嗨聊派对"); + if (AvRoomDataManager.get().isRoomOwner() + && AvRoomDataManager.get().isCpRoom() + && DemoCache.readBoolean(DemoCache.KEY_IS_FIRST_HOME_HIGH_PARTY_DIALOG, true)) { + DemoCache.saveBoolean(DemoCache.KEY_IS_FIRST_HOME_HIGH_PARTY_DIALOG, false); + dmi.getDialogManager().showOkCancelDialog("匹配会退出当前房间并解散用户", true, + () -> getGuildRoomId(context)); + + } else { + getGuildRoomId(context); + + } + break; + //异性匹配 + case RouterType.OPPOSITE_SEX_MATCHING: + if (!(context instanceof DialogManagerInterface) || !(context instanceof RxAppCompatActivity)) { + return false; + } + dmi = (DialogManagerInterface) context; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_matchsex, "异性匹配"); + if (AvRoomDataManager.get().isRoomOwner() + && AvRoomDataManager.get().isCpRoom() + && DemoCache.readBoolean(IS_FIRST, true)) { + DemoCache.saveBoolean(IS_FIRST, false); + dmi.getDialogManager().showOkCancelDialog("匹配会退出当前房间并解散用户", true, + () -> showSexMatchDialog(context)); + } else { + showSexMatchDialog(context); + } + break; + case RouterType.CITY_MATCHING: +// StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_player, "找玩友"); +// context.startActivity(new Intent(context, UserMatchActivity.class)); + + SingleToastUtil.showToast("暂不支持哟!"); + break; + case RouterType.GAME_MATCHING: +// try { +// GameInfo gameInfo = new Gson().fromJson(routerValue, GameInfo.class); +// MatchActivity.start(context, gameInfo); +// } catch (Exception e) { +// return false; +// } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.game_homepage_all_game, "全部游戏"); + context.startActivity(new Intent(context, AllGameActivity.class)); + break; + case RouterType.MINI_WORLD: + MiniWorldMainActivity.start(context); + break; + case RouterType.MINI_WORLD_DETAIL: + MiniWorldGuestPageActivity.start(context, routerValue); + break; + + case RouterType.SQUARE_PUBLISH: + EventBus.getDefault().post(new SquareTaskEvent()); + break; + + default: + SingleToastUtil.showToast("暂不支持哟!"); + return false; + } + return true; + } + + private static void showSexMatchDialog(Context context) { + AvRoomModel.get().exitRoom(new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + } + + @Override + public void onFail(int code, String error) { + } + }); + SexMatchDialog sexMatchDialog = new SexMatchDialog(context); + sexMatchDialog.setTimeOutConsumer(new Consumer() { + @Override + public void accept(String s) throws Exception { + SingleToastUtil.showToast("暂未匹配成功"); + } + }); + sexMatchDialog.openDialog(); + } + + + private static void getGuildRoomId(Context context) { + AvRoomModel.get() + .getPartyRoomList(AuthModel.get().getCurrentUid()) + .doOnError(throwable -> { + if (throwable instanceof PmRoomLimitException) { + new LimitEnterRoomHelper().handleThisContext( + context, throwable.getMessage(), false, null + ); + } + }) + .doOnSuccess(partyRoomResult -> { + if (partyRoomResult != null) { + if (partyRoomResult.getData() != null && partyRoomResult.isSuccess()) { + if (partyRoomResult.getData().size() > 0) { + AvRoomDataManager.get().setRoomUidList(partyRoomResult.getData()); + AVRoomActivity.start(context, true); + }else { + SingleToastUtil.showToastShort("暂无嗨聊房"); + } + }else if (partyRoomResult.getData() != null && !partyRoomResult.isSuccess()){ + SingleToastUtil.showToastShort(partyRoomResult.getError()); + }else { + SingleToastUtil.showToastShort("未知错误"); + } + }else { + SingleToastUtil.showToastShort("暂无嗨聊房"); + } + }) + .subscribe(); + +// HomeModel.get().getGuildRoomId() +// .doOnError(throwable -> { +// if (throwable instanceof PmRoomLimitException) { +// new LimitEnterRoomHelper().handleThisContext( +// context, throwable.getMessage(), false, null +// ); +// } +// }) +// .doOnSuccess(s -> AVRoomActivity.start(context, JavaUtil.str2long(s))) +// .subscribe(); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/ChatterBoxAction.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/ChatterBoxAction.java new file mode 100644 index 000000000..5254fe996 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/ChatterBoxAction.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.ui.im.actions; + +import android.os.Handler; +import android.text.TextUtils; + +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.chatterbox.ChatterBoxHelper; +import com.yizhuan.xchat_android_core.im.chatterbox.ChatterBoxModel; +import com.yizhuan.xchat_android_core.im.chatterbox.HideInputEvent; +import com.yizhuan.xchat_android_core.im.chatterbox.TopicBoxItemInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.ChatterBoxAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; + +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.functions.BiConsumer; + +public class ChatterBoxAction extends BaseAction { + + private long lastClick = 0L; + public static String sessionId; + + public ChatterBoxAction() { + super(R.drawable.chat_icon_say, R.string.chat_action); + } + + @Override + public void onClick() { + long currentClick = System.currentTimeMillis(); + + if (currentClick - lastClick > 1000L) { + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MESSAGE_START_CHATTER_BOX, "消息-发起话匣子"); + + EventBus.getDefault().post(new HideInputEvent()); + lastClick = currentClick; + + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_CHATTER_BOX)) { + new Handler().post(() -> { + TuTuGuideHelper helper = new TuTuGuideHelper(getActivity()); + helper.createHiGuide(() -> helper.createDiceOverLayer()); + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_CHATTER_BOX); + }); + } + ChatterBoxHelper.topicBoxCanSend(); + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/DecorationAction.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/DecorationAction.java new file mode 100644 index 000000000..71ce2a7ff --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/DecorationAction.java @@ -0,0 +1,24 @@ +package com.yizhuan.erban.ui.im.actions; + +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +/** + * Created by huangmeng1 on 2018/5/10. + */ + +public class DecorationAction extends BaseAction { + /** + * 构造函数 + */ + public DecorationAction() { + super(R.drawable.icon_decoration_action, R.string.decoration_action); + } + + @Override + public void onClick() { + DecorationStoreActivity.start(getActivity(), JavaUtil.str2long(getAccount())); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/FamilyGameAction.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/FamilyGameAction.java new file mode 100644 index 000000000..abe70f9d5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/FamilyGameAction.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.ui.im.actions; + +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.yizhuan.erban.R; +import com.yizhuan.erban.family.view.activity.FamilyGameListActivity; + +/** + * Created by MadisonRong on 29/05/2018. + */ + +public class FamilyGameAction extends BaseAction { + + public FamilyGameAction() { + this(R.drawable.icon_family_game_action, R.string.action_family_game); + } + + /** + * 构造函数 + * + * @param iconResId 图标 res id + * @param titleId 图标标题的string res id + */ + protected FamilyGameAction(int iconResId, int titleId) { + super(iconResId, titleId); + } + + @Override + public void onClick() { + FamilyGameListActivity.start(getActivity()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftAction.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftAction.java new file mode 100644 index 000000000..74fdd7b7d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftAction.java @@ -0,0 +1,104 @@ +package com.yizhuan.erban.ui.im.actions; + +import android.annotation.SuppressLint; + +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.GiftDialog; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleDialog; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.toolbox.GiftToolbox; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.magic.bean.MagicReceivedInfo; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +/** + * Created by xiaoyu + * on 2017/10/2. + */ + +public class GiftAction extends BaseAction implements GiftDialog.OnGiftDialogBtnClickListener { + + + public GiftAction() { + super(R.drawable.icon_gift_action, R.string.gift_action); + } + + transient private GiftDialog giftDialog; + + @Override + public void onClick() { + if (giftDialog == null) { + GiftDialog.GIFT_DIALOG_FROM = "私聊"; + + giftDialog = new GiftDialog(getActivity(), Long.valueOf(getAccount()), false, false, true); + giftDialog.setGiftDialogBtnClickListener(this); + giftDialog.setOnDismissListener(dialog -> giftDialog = null); + } + if (!giftDialog.isShowing()) { + giftDialog.show(); + } + } + + @SuppressLint("CheckResult") + @Override + public void onSendGiftBtnClick(GiftInfo giftInfo, List micMemberInfos, int number, String msg, boolean isknap, boolean isWholeMic, GiftDialog.SenGiftCallback callback) { + if (giftInfo == null) return; + boolean canUseNobleGiftOrNot = GiftModel.get().canUseNobleGiftOrNot(giftInfo); + if (canUseNobleGiftOrNot) { + GiftModel.get().sendPersonalGift(giftInfo.getGiftId(), micMemberInfos.get(0).getUid(), number, msg, isknap) + .doOnError(throwable -> { + if (callback != null) { + callback.onFail(); + } + }) + .flatMap(serviceResult -> GiftToolbox.sendGiftPrivateChatMessage(serviceResult.getData())) + .subscribe(imMessage -> { + // 手动更新送礼物的消息 + MessageListPanelHelper.getInstance().notifyAddMessage(imMessage); + if (callback != null) { + callback.onSuccess(); + } + }); + } else { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + int currentLevel = userInfo == null ? 0 : userInfo.getNobleInfo() == null ? 0 : userInfo.getNobleInfo().getLevel(); + new OpenNobleDialog(getActivity(), currentLevel, giftInfo.getLevel(), "送该礼物").show(); + callback.onFail(); + } + } + + @Override + public void onSendMagicBtnClick(MagicInfo magicInfo, long targetUid, GiftDialog.SenGiftCallback callback) { + //赠送魔法的回调 + MagicModel.get().sendMagic(magicInfo.getMagicId(), targetUid) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + if (callback != null) { + callback.onFail(); + } + } + + @Override + public void onSuccess(MagicReceivedInfo info) { + PayModel.get().decreaseLocalGold(magicInfo.getPrice()); + if (callback != null) { + callback.onSuccess(); + } + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftActionEvent.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftActionEvent.java new file mode 100644 index 000000000..72db55549 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/GiftActionEvent.java @@ -0,0 +1,43 @@ +package com.yizhuan.erban.ui.im.actions; + +import java.io.Serializable; + +/** + * Created by chenran on 2017/11/14. + */ + +public class GiftActionEvent implements Serializable { + public GiftActionEvent() { + + } + + public void onGiftActionEvent(long uid) { + + } + +// +// @Override +// public int describeContents() { +// return 0; +// } +// +// @Override +// public void writeToParcel(Parcel dest, int flags) { +// // 序列化过程:必须按成员变量声明的顺序进行封装 +// } +// +// // 反序列过程:必须实现Parcelable.Creator接口,并且对象名必须为CREATOR +// // 读取Parcel里面数据时必须按照成员变量声明的顺序,Parcel数据来源上面writeToParcel方法,读出来的数据供逻辑层使用 +// public static final Parcelable.Creator CREATOR = new Creator() { +// +// @Override +// public GiftActionEvent createFromParcel(Parcel source) { +// return new GiftActionEvent(); +// } +// +// @Override +// public GiftActionEvent[] newArray(int size) { +// return new GiftActionEvent[size]; +// } +// }; +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/actions/LuckyMoneyAction.java b/app/src/main/java/com/yizhuan/erban/ui/im/actions/LuckyMoneyAction.java new file mode 100644 index 000000000..b443f33f5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/actions/LuckyMoneyAction.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.ui.im.actions; + +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.yizhuan.erban.R; +import com.yizhuan.erban.luckymoney.view.LuckyMoneyCreationActivity; + +/** + * Created by MadisonRong on 29/05/2018. + */ + +public class LuckyMoneyAction extends BaseAction { + + public LuckyMoneyAction() { + this(R.drawable.icon_lucky_money_action, R.string.action_red_packet); + } + + /** + * 构造函数 + * + * @param iconResId 图标 res id + * @param titleId 图标标题的string res id + */ + protected LuckyMoneyAction(int iconResId, int titleId) { + super(iconResId, titleId); + } + + @Override + public void onClick() { + LuckyMoneyCreationActivity.start(getActivity()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/audio/ShakeHeartDialogFragment.java b/app/src/main/java/com/yizhuan/erban/ui/im/audio/ShakeHeartDialogFragment.java new file mode 100644 index 000000000..c69fb694e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/audio/ShakeHeartDialogFragment.java @@ -0,0 +1,173 @@ +package com.yizhuan.erban.ui.im.audio; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.view.animation.ScaleAnimation; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +public class ShakeHeartDialogFragment extends DialogFragment { + + public static final String KEY_SHAKE_HEART_HINT = "key_shake_heart"; + private String textHint; + + public static ShakeHeartDialogFragment newInstance(String textHint) { + + Bundle args = new Bundle(); + args.putString(KEY_SHAKE_HEART_HINT, textHint); + ShakeHeartDialogFragment fragment = new ShakeHeartDialogFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (getArguments() != null) { + textHint = getArguments().getString(KEY_SHAKE_HEART_HINT); + } else { + textHint = ""; + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题 + return inflater.inflate(R.layout.fragment_shake_heart, container); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + TextView tvHint = view.findViewById(R.id.tv_heart_hint); + tvHint.setText(textHint); + + ImageView ivHeart = view.findViewById(R.id.iv_heart); + + // 缩放动画 + Animation scaleAnimation1 = new ScaleAnimation(0, 1.2f, 0, 1.2f, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + scaleAnimation1.setInterpolator(new LinearInterpolator()); + scaleAnimation1.setDuration(250); + scaleAnimation1.setFillAfter(true);// 动画播放完毕后,是否会停止在动画结束的状态 + Animation scaleAnimation2 = new ScaleAnimation(1.2f, 1, 1.2f, 1, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + scaleAnimation2.setInterpolator(new LinearInterpolator()); + scaleAnimation2.setStartOffset(250); + scaleAnimation2.setDuration(250); + scaleAnimation2.setFillAfter(true);// 动画播放完毕后,是否会停止在动画结束的状态 + // 晃动动画 + Animation rotateAnimation1 = new RotateAnimation(0, -10, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation1.setInterpolator(new LinearInterpolator()); + rotateAnimation1.setStartOffset(650); + rotateAnimation1.setDuration(300); + rotateAnimation1.setFillAfter(true); + Animation rotateAnimation2 = new RotateAnimation(-10, 20, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation2.setInterpolator(new LinearInterpolator()); + rotateAnimation2.setStartOffset(950); + rotateAnimation2.setDuration(100); + rotateAnimation2.setFillAfter(true); + Animation rotateAnimation3 = new RotateAnimation(10, -20, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation3.setInterpolator(new LinearInterpolator()); + rotateAnimation3.setStartOffset(1050); + rotateAnimation3.setDuration(100); + rotateAnimation3.setFillAfter(true); + Animation rotateAnimation4 = new RotateAnimation(-10, 20, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation4.setInterpolator(new LinearInterpolator()); + rotateAnimation4.setStartOffset(1150); + rotateAnimation4.setDuration(100); + rotateAnimation4.setFillAfter(true); + Animation rotateAnimation5 = new RotateAnimation(10, -10, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation5.setInterpolator(new LinearInterpolator()); + rotateAnimation5.setStartOffset(1250); + rotateAnimation5.setDuration(100); + rotateAnimation5.setFillAfter(true); + Animation alphaAnimation = new AlphaAnimation(1, 0); + alphaAnimation.setInterpolator(new LinearInterpolator()); + alphaAnimation.setStartOffset(1350); + alphaAnimation.setDuration(1000); + alphaAnimation.setFillAfter(true); + // 动画集 + AnimationSet animationSet = new AnimationSet(false); + animationSet.addAnimation(scaleAnimation1); + animationSet.addAnimation(scaleAnimation2); + animationSet.addAnimation(rotateAnimation1); + animationSet.addAnimation(rotateAnimation2); + animationSet.addAnimation(rotateAnimation3); + animationSet.addAnimation(rotateAnimation4); + animationSet.addAnimation(rotateAnimation5); + animationSet.addAnimation(alphaAnimation); + animationSet.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + dismiss(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + ivHeart.startAnimation(animationSet); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NO_TITLE, R.style.FullScreenDialog); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Dialog dialog = super.onCreateDialog(savedInstanceState); + Window window = dialog.getWindow(); + WindowManager.LayoutParams params; + if (window != null) { + params = window.getAttributes(); + params.gravity = Gravity.CENTER; + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + window.setAttributes(params); + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + } + return dialog; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListActivity.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListActivity.java new file mode 100644 index 000000000..dfc2ff2f2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListActivity.java @@ -0,0 +1,152 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.constant.Extras; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.user.IUserModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + + +import java.util.List; + +import io.reactivex.functions.Consumer; + +/** + * @author Administrator + * @date 2018/1/27 + */ +@CreatePresenter(AddBlackListPresenter.class) +public class AddBlackListActivity extends BaseMvpActivity + implements IAddBlackListView, View.OnClickListener { + + private String account; + private RelativeLayout rlContent; + private TextView tvAddBlackList; + private TextView tvTitle; + private TextView tvName; + private ImageView ivBack; + private ImageView ivAvatar; + + public static void start(Context context, String contactId) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, contactId); + intent.setClass(context, AddBlackListActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_nim_add_black_list); + account = getIntent().getStringExtra(Extras.EXTRA_ACCOUNT); + if (TextUtils.isEmpty(account)) account = "0"; + rlContent = (RelativeLayout) findViewById(R.id.rl_content); + tvName = (TextView) findViewById(R.id.tv_name); + tvTitle = (TextView) findViewById(R.id.tv_title); + tvAddBlackList = (TextView) findViewById(R.id.tv_add_black_list); + ivBack = (ImageView) findViewById(R.id.iv_back); + ivAvatar = (ImageView) findViewById(R.id.iv_avatar); + ivBack.setOnClickListener(this); + rlContent.setOnClickListener(this); + tvAddBlackList.setOnClickListener(this); + findViewById(R.id.tv_report).setOnClickListener(this); + List blackListAccount = NimFriendModel.get().getMyBlackListAccount(); + if (blackListAccount != null) + changeText(blackListAccount.contains(account)); + initTarget(); + + } + + void changeText(boolean contains) { + tvAddBlackList.setText(contains ? "移除黑名单" : "加入黑名单"); + tvTitle.setText(contains ? "移除黑名单" : "加入黑名单"); + } + + /** + * 初始化目标的信息 + */ + @SuppressLint("CheckResult") + private void initTarget() { + UserModel.get().getUserInfo(Long.valueOf(account)).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + // 头像 + ImageLoadUtils.loadAvatar(AddBlackListActivity.this, userInfo.getAvatar(), ivAvatar, true); + // 名字 + tvName.setText(RegexUtil.getPrintableString(userInfo.getNick())); + } + }); + + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.rl_content) { + if (!TextUtils.isEmpty(account)) + UserInfoActivity.Companion.start(this, Long.valueOf(account)); + } else if (v.getId() == R.id.tv_add_black_list) { + boolean contains = NimFriendModel.get().getMyBlackListAccount().contains(account); + if (!contains) + ensureAddToBlackList(); + else + ensureRemoveFromBlackList(); + + } else if (v.getId() == R.id.iv_back) { + finish(); + } else if (v.getId() == R.id.tv_report) { + UIHelper.showReportPage(context, JavaUtil.str2long(account), XChatConstants.REPORT_TYPE_CHAT); + } + } + + private void ensureRemoveFromBlackList() { + getDialogManager().showOkCancelDialog("移除黑名单,你将正常收到对方的信息", true, + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + getMvpPresenter().removeFromBlackList(account); + } + }); + } + + private void ensureAddToBlackList() { + getDialogManager().showOkCancelDialog("加入黑名单,你将不再收到对方的信息", true, + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + getMvpPresenter().addToBlackList(account); + } + }); + } + + @Override + public void addToBlackListSuccessOrNot(boolean success) { + changeText(success); + toast(success ? "已经成功将对方加入黑名单" : "加入黑名单失败"); + } + + @Override + public void removeFromBlackListSuccessOrNot(boolean success) { + changeText(!success); + toast(success ? "已经成功将对方移除黑名单" : "移除黑名单失败"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListPresenter.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListPresenter.java new file mode 100644 index 000000000..20845bd1a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/AddBlackListPresenter.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.ui.im.avtivity; + + +import com.yizhuan.erban.base.BaseMvpPresenter; + +/** + * @author Administrator + * @date 2018/1/27 + */ + +public class AddBlackListPresenter extends BaseMvpPresenter { + private NimFriendModel model; + + public AddBlackListPresenter() { + model = NimFriendModel.get(); + } + + void addToBlackList(String targetUid) { + model.addToBlackList(targetUid).subscribe((aBoolean, throwable) -> { + getMvpView().addToBlackListSuccessOrNot(throwable == null); + }); + } + + void removeFromBlackList(String targetUid) { + model.removeFromBlackList(targetUid).subscribe((aBoolean, throwable) -> { + getMvpView().removeFromBlackListSuccessOrNot(throwable == null); + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BaseMessageActivity.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BaseMessageActivity.java new file mode 100644 index 000000000..880666698 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BaseMessageActivity.java @@ -0,0 +1,240 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.Toolbar; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nim.uikit.R; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.business.session.constant.Extras; +import com.netease.nim.uikit.business.session.fragment.MessageFragment; +import com.netease.nim.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.common.activity.UI; +import com.netease.nim.uikit.common.fragment.TFragment; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.netease.nimlib.sdk.NIMSDK; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.model.BroadcastMessage; +import com.orhanobut.logger.Logger; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.BuildConfig; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.monsterhunting.MonsterHuntingActivity; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelOneDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelThreeDialog; +import com.yizhuan.erban.ui.widget.dialog.AllServiceGiftLevelTwoDialog; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleGlobalNoticeDialog; +import com.yizhuan.xchat_android_core.bean.BaseProtocol; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleProtocol; +import com.yizhuan.xchat_android_library.utils.UIUtils; + +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.List; + +import static com.yizhuan.xchat_android_core.Constants.DEBUG_MAX_UID; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_HEAD_NOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_OPENNOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_RENEWNOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_ALL_SERVICE_GIFT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_GIFT; + +/** + * Created by zhoujianghua on 2015/9/10. + */ +public abstract class BaseMessageActivity extends BaseActivity { + + private static final String TAG = "BaseMessageActivity"; + + protected String sessionId; + + private SessionCustomization customization; + + private MessageFragment messageFragment; + + + protected abstract MessageFragment fragment(); + + protected abstract int getContentViewId(); + + protected abstract void initToolBar(); + + private Toolbar toolbar; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getContentViewId()); + initToolBar(); + parseIntent(); + + messageFragment = (MessageFragment) switchContent(fragment()); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void onBackPressed() { + if (messageFragment == null || !messageFragment.onBackPressed()) { + super.onBackPressed(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (messageFragment != null) { + messageFragment.onActivityResult(requestCode, resultCode, data); + } + + if (customization != null) { + customization.onActivityResult(this, requestCode, resultCode, data); + } + } + + private void parseIntent() { + sessionId = getIntent().getStringExtra(Extras.EXTRA_ACCOUNT); + customization = (SessionCustomization) getIntent().getSerializableExtra(Extras.EXTRA_CUSTOMIZATION); + + if (customization != null) { + addRightCustomViewOnActionBar(this, customization.buttons); + } + } + + // 添加action bar的右侧按钮及响应事件 + private void addRightCustomViewOnActionBar(Activity activity, List buttons) { + if (buttons == null || buttons.size() == 0) { + return; + } + + Toolbar toolbar = getToolBar(); + if (toolbar == null) { + return; + } + + LinearLayout view = (LinearLayout) LayoutInflater.from(activity).inflate(R.layout.nim_action_bar_custom_view, null); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + for (final SessionCustomization.OptionsButton button : buttons) { + ImageView imageView = new ImageView(activity); + imageView.setImageResource(button.iconId); + imageView.setBackgroundResource(R.drawable.nim_nim_action_bar_button_selector); + imageView.setPadding(ScreenUtil.dip2px(10), 0, ScreenUtil.dip2px(10), 0); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + button.onClick(BaseMessageActivity.this, v, sessionId); + } + }); + view.addView(imageView, params); + } + + toolbar.addView(view, new Toolbar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.RIGHT | Gravity.CENTER)); + } + + /** + * 当前Activity 是否有效 + */ + protected boolean isValid() { + return !isFinishing() && !isDestroyed(); + } + + public TFragment switchContent(TFragment fragment) { + return switchContent(fragment, false); + } + + protected TFragment switchContent(TFragment fragment, boolean needAddToBackStack) { + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.replace(fragment.getContainerId(), fragment); + if (needAddToBackStack) { + fragmentTransaction.addToBackStack(null); + } + try { + fragmentTransaction.commitAllowingStateLoss(); + } catch (Exception e) { + + } + + return fragment; + } + + public void setToolBar(int toolBarId, ToolBarOptions options) { + toolbar = (Toolbar) findViewById(toolBarId); + if (options.titleId != 0) { + toolbar.setTitle(options.titleId); + } + if (!TextUtils.isEmpty(options.titleString)) { + toolbar.setTitle(options.titleString); + } + if (options.logoId != 0) { + toolbar.setLogo(options.logoId); + } + setSupportActionBar(toolbar); + + if (options.isNeedNavigate) { + toolbar.setNavigationIcon(options.navigateId); + toolbar.setContentInsetStartWithNavigation(0); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } + } + + public void setToolBar(int toolbarId, int titleId, int logoId) { + toolbar = (Toolbar) findViewById(toolbarId); + toolbar.setTitle(titleId); + toolbar.setLogo(logoId); + setSupportActionBar(toolbar); + } + + public Toolbar getToolBar() { + return toolbar; + } + + public void setSubTitle(String subTitle) { + if (toolbar != null) { + toolbar.setSubtitle(subTitle); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListAdapter.java new file mode 100644 index 000000000..d9f6483b6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListAdapter.java @@ -0,0 +1,144 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.support.v7.widget.RecyclerView; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +/** + * @author Administrator + * @date 2018/1/27 + */ + +public class BlackListAdapter extends RecyclerView.Adapter implements View.OnTouchListener { + + private List nimUserInfos; + private RecyclerView recyclerView; + + BlackListAdapter(RecyclerView recyclerView) { + this.recyclerView = recyclerView; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new BlackListHolder(new SwipeRecyclerViewItem(parent.getContext())); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof BlackListHolder) { + ((BlackListHolder) holder).bind(nimUserInfos.get(position)); + } + } + + public void setNewData(List nimUserInfoList) { + this.nimUserInfos = nimUserInfoList; + notifyDataSetChanged(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + @Override + public int getItemCount() { + return nimUserInfos == null ? 0 : nimUserInfos.size(); + } + + /** + * 当用户触碰其他item的时候,需要隐藏已经显示出remove按钮的item + * + * @param v - + * @param event - + * @return - + */ + @Override + public boolean onTouch(View v, MotionEvent event) { + int actionMasked = event.getActionMasked(); + switch (actionMasked) { + case MotionEvent.ACTION_DOWN: + int childCount = recyclerView.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = recyclerView.getChildAt(i); + RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(child); + if (holder instanceof BlackListHolder) { + if (((BlackListHolder) holder).rlContent != v) + ((BlackListHolder) holder).hideRemoveButton(); + } + } + break; + default: + break; + } + return false; + } + + class BlackListHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + private RelativeLayout rlContent; + private ImageView ivAvatar; + private TextView tvName; + private TextView tvRemove; + + BlackListHolder(View itemView) { + super(itemView); + ivAvatar = itemView.findViewById(R.id.iv_avatar); + rlContent = itemView.findViewById(R.id.rl_content); + rlContent.setOnTouchListener(BlackListAdapter.this); + tvName = itemView.findViewById(R.id.tv_name); + tvRemove = itemView.findViewById(R.id.tv_remove); + tvRemove.setOnClickListener(this); + } + + private NimUserInfo userInfo; + + void bind(NimUserInfo nimUserInfo) { + this.userInfo = nimUserInfo; + // 加载头像 + ImageLoadUtils.loadAvatar(itemView.getContext(), nimUserInfo.getAvatar(), ivAvatar, true); + // 名字 + tvName.setText(nimUserInfo.getName()); + // 清除view的translationX + rlContent.setTranslationX(0); + } + + void hideRemoveButton() { + rlContent.animate().setDuration(70).translationX(0).start(); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.tv_remove) { + // 如果没有完全展开也返回 + if (rlContent.getTranslationX() > -tvRemove.getWidth()) return; + if (ListUtils.isListEmpty(nimUserInfos)) return; + if (nimUserInfos.remove(userInfo)) { + notifyItemRemoved(getAdapterPosition()); + // 从云信的黑名单中移除 + NimFriendModel.get().removeFromBlackList(userInfo.getAccount()) + .subscribe((aBoolean, throwable) -> { + if (throwable != null) { +// Toast.makeText(itemView.getContext(), "移除黑名单失败", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("移除黑名单失败"); + } else { +// Toast.makeText(itemView.getContext(), "移除黑名单成功", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("移除黑名单成功"); + } + }); + } + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManageActivity.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManageActivity.java new file mode 100644 index 000000000..c72e5069e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManageActivity.java @@ -0,0 +1,115 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; + +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.List; + +/** + * @description: 黑名单管理页面 + * @author: hewenhao + * @date: 2018/9/4 14:43 + */ +@CreatePresenter(BlackListManagePresenter.class) +public class BlackListManageActivity extends BaseMvpActivity implements + IBlackListManageView, View.OnClickListener { + + private BlackListAdapter mAdapter; + private ImageView ivBack; + private RecyclerView mRecyclerView; + private LinearLayoutManager mLayoutManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_friend_black_list_manage); + initViews(); + } + + private void initViews() { + showLoading(); + ivBack = (ImageView) findViewById(R.id.iv_back); + ivBack.setOnClickListener(this); + // 黑名单 + mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); + mAdapter = new BlackListAdapter(mRecyclerView); + mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setAdapter(mAdapter); + // 获取黑名单用户的数据 + BlackListManagePresenter mvpPresenter = getMvpPresenter(); + if (mvpPresenter != null) { + mvpPresenter.getMyBlackListUsers(); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.iv_back) { + finish(); + } + } + + @Override + public void onGetBlackListInfoSuccess(List nimUserInfos) { + if (ListUtils.isListEmpty(nimUserInfos)) { + showNoData(R.drawable.icon_common_failure, "你的黑名单为空哦!"); + } else { + hideStatus(); + if (mAdapter != null) { + mAdapter.setNewData(nimUserInfos); + } + } + } + + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Override + public void onGetBlackListInfoFail(Throwable throwable) { + showNetworkErr(); + toast("获取黑名单失败"); + } + + @Override + public void onReloadDate() { + super.onReloadDate(); + showLoading(); + BlackListManagePresenter mvpPresenter = getMvpPresenter(); + if (mvpPresenter != null) { + mvpPresenter.getMyBlackListUsers(); + } + } + + public static void start(Context context) { + Intent intent = new Intent(); + intent.setClass(context, BlackListManageActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManagePresenter.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManagePresenter.java new file mode 100644 index 000000000..5b463faad --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/BlackListManagePresenter.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import com.yizhuan.erban.base.BaseMvpPresenter; + +/** + * @author Administrator + * @date 2018/1/27 + */ + +public class BlackListManagePresenter extends BaseMvpPresenter { + private NimFriendModel model; + + public BlackListManagePresenter() { + model = NimFriendModel.get(); + } + + void getMyBlackListUsers() { + model.getMyBlackListInfos().subscribe((nimUserInfos, throwable) -> { + if (throwable != null) { + getMvpView().onGetBlackListInfoFail(throwable); + } else { + getMvpView().onGetBlackListInfoSuccess(nimUserInfos); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IAddBlackListView.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IAddBlackListView.java new file mode 100644 index 000000000..7733eec53 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IAddBlackListView.java @@ -0,0 +1,27 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +/** + *

+ * + * @author xiaoyu + * @date 2017/12/12 + */ +public interface IAddBlackListView extends IMvpBaseView { + + /** + * 加入黑名单失败 + * + * @param success -是否成功 + */ + void addToBlackListSuccessOrNot(boolean success); + + /** + * 移除黑名单失败 + * + * @param success -是否成功 + */ + void removeFromBlackListSuccessOrNot(boolean success); + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IBlackListManageView.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IBlackListManageView.java new file mode 100644 index 000000000..8b12de856 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/IBlackListManageView.java @@ -0,0 +1,29 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

+ * + * @author xiaoyu + * @date 2017/12/12 + */ +public interface IBlackListManageView extends IMvpBaseView { + + /** + * 获取黑名单成功的回调 + * + * @param nimUserInfos 用户信息 + */ + void onGetBlackListInfoSuccess(List nimUserInfos); + + /** + * 获取黑名单失败的回调 + * + * @param throwable - + */ + void onGetBlackListInfoFail(Throwable throwable); +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NewBaseMessageActivity.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NewBaseMessageActivity.java new file mode 100644 index 000000000..27a4141e2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NewBaseMessageActivity.java @@ -0,0 +1,204 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.netease.nim.uikit.R; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.business.session.constant.Extras; +import com.netease.nim.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.common.fragment.TFragment; +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.im.fragment.MessageFragment; + +import java.util.List; + +/** + * Created by zhoujianghua on 2015/9/10. + */ +public abstract class NewBaseMessageActivity extends BaseActivity { + + private static final String TAG = "BaseMessageActivity"; + + protected String sessionId; + + private SessionCustomization customization; + + private MessageFragment messageFragment; + + + protected abstract MessageFragment fragment(); + + protected abstract int getContentViewId(); + + protected abstract void initToolBar(); + + private Toolbar toolbar; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getContentViewId()); + initToolBar(); + parseIntent(); + + messageFragment = (MessageFragment) switchContent(fragment()); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void onBackPressed() { + if (messageFragment == null || !messageFragment.onBackPressed()) { + super.onBackPressed(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (messageFragment != null) { + messageFragment.onActivityResult(requestCode, resultCode, data); + } + + if (customization != null) { + customization.onActivityResult(this, requestCode, resultCode, data); + } + } + + private void parseIntent() { + sessionId = getIntent().getStringExtra(Extras.EXTRA_ACCOUNT); + customization = (SessionCustomization) getIntent().getSerializableExtra(Extras.EXTRA_CUSTOMIZATION); + + if (customization != null) { + addRightCustomViewOnActionBar(this, customization.buttons); + } + } + + // 添加action bar的右侧按钮及响应事件 + private void addRightCustomViewOnActionBar(Activity activity, List buttons) { + if (buttons == null || buttons.size() == 0) { + return; + } + + Toolbar toolbar = getToolBar(); + if (toolbar == null) { + return; + } + + LinearLayout view = (LinearLayout) LayoutInflater.from(activity).inflate(R.layout.nim_action_bar_custom_view, null); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + for (final SessionCustomization.OptionsButton button : buttons) { + ImageView imageView = new ImageView(activity); + imageView.setImageResource(button.iconId); + imageView.setBackgroundResource(R.drawable.nim_nim_action_bar_button_selector); + imageView.setPadding(ScreenUtil.dip2px(10), 0, ScreenUtil.dip2px(10), 0); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + button.onClick(NewBaseMessageActivity.this, v, sessionId); + } + }); + view.addView(imageView, params); + } + + toolbar.addView(view, new Toolbar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.RIGHT | Gravity.CENTER)); + } + + /** + * 当前Activity 是否有效 + */ + protected boolean isValid() { + return !isFinishing() && !isDestroyed(); + } + + public TFragment switchContent(TFragment fragment) { + return switchContent(fragment, false); + } + + protected TFragment switchContent(TFragment fragment, boolean needAddToBackStack) { + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.replace(fragment.getContainerId(), fragment); + if (needAddToBackStack) { + fragmentTransaction.addToBackStack(null); + } + try { + fragmentTransaction.commitAllowingStateLoss(); + } catch (Exception e) { + + } + + return fragment; + } + + public void setToolBar(int toolBarId, ToolBarOptions options) { + toolbar = (Toolbar) findViewById(toolBarId); + if (options.titleId != 0) { + toolbar.setTitle(options.titleId); + } + if (!TextUtils.isEmpty(options.titleString)) { + toolbar.setTitle(options.titleString); + } + if (options.logoId != 0) { + toolbar.setLogo(options.logoId); + } + setSupportActionBar(toolbar); + + if (options.isNeedNavigate) { + toolbar.setNavigationIcon(options.navigateId); + toolbar.setContentInsetStartWithNavigation(0); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } + } + + public void setToolBar(int toolbarId, int titleId, int logoId) { + toolbar = (Toolbar) findViewById(toolbarId); + toolbar.setTitle(titleId); + toolbar.setLogo(logoId); + setSupportActionBar(toolbar); + } + + public Toolbar getToolBar() { + return toolbar; + } + + public void setSubTitle(String subTitle) { + if (toolbar != null) { + toolbar.setSubtitle(subTitle); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimFriendModel.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimFriendModel.java new file mode 100644 index 000000000..a15067176 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimFriendModel.java @@ -0,0 +1,162 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import com.netease.nimlib.sdk.InvocationFuture; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.friend.FriendService; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.netease.nimlib.sdk.util.api.RequestResult; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * @author Administrator + * @date 2018/1/27 + */ + +public class NimFriendModel { + private static final int RESULT_OK = 200; + + private static NimFriendModel sInstance; + + public static NimFriendModel get() { + if (sInstance == null) { + synchronized (NimFriendModel.class) { + if (sInstance == null) { + sInstance = new NimFriendModel(); + } + } + } + return sInstance; + } + + private NimFriendModel() { + + } + + + public Single addToBlackList(String targetUid) { + return Single.create((SingleOnSubscribe) e -> { + InvocationFuture invocationFuture = + NIMClient.getService(FriendService.class).addToBlackList(targetUid); + RequestResult result = NIMClient.syncRequest(invocationFuture); + if (result.exception != null) { + e.onError(result.exception); + } else if (result.code != RESULT_OK) { + e.onError(new Exception("错误码: " + result.code)); + } else { + e.onSuccess(true); + } + }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); + } + + public Single removeFromBlackList(String targetUid) { + return Single.create((SingleOnSubscribe) e -> { + InvocationFuture invocationFuture = + NIMClient.getService(FriendService.class).removeFromBlackList(targetUid); + RequestResult result = NIMClient.syncRequest(invocationFuture); + if (result.exception != null) { + e.onError(result.exception); + } else if (result.code != RESULT_OK) { + e.onError(new Exception("错误码: " + result.code)); + } else { + e.onSuccess(true); + } + }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); + } + + + /** + * 返回我所有的黑名单成员的账号 + * + * @return - + */ + List getMyBlackListAccount() { + return NIMClient.getService(FriendService.class).getBlackList(); + } + + /** + * 返回我所有的黑名单成员的数量 + * + * @return - 数量 + */ + int getMyBlackListSize() { + List blackList = NIMClient.getService(FriendService.class).getBlackList(); + if (ListUtils.isListEmpty(blackList)) return 0; + return blackList.size(); + } + + /** + * 返回该成员是否在我的黑名单中 + * + * @return - + */ + public boolean isInMyBlackList(String account) { + return NIMClient.getService(FriendService.class).isInBlackList(account); + } + + /** + * 获取黑名单所有账号的用户信息 + * + * @return - + */ + public Single> getMyBlackListInfos() { + List myBlackListAccount = getMyBlackListAccount(); + if (ListUtils.isListEmpty(myBlackListAccount)) { + List temp = new ArrayList<>(1); + return Single.just(temp).observeOn(AndroidSchedulers.mainThread()); + } + List users = NIMClient.getService(UserService.class).getUserInfoList(myBlackListAccount); + if (users.size() == myBlackListAccount.size()) + return Single.just(users).observeOn(AndroidSchedulers.mainThread()); + return Single.create((SingleOnSubscribe>) e -> { + + List totalResult = new ArrayList<>(); + List subAccount = new ArrayList<>(); + + for (String sub :myBlackListAccount) { + if (subAccount.size() == 150) { + InvocationFuture> future = + NIMClient.getService(UserService.class).fetchUserInfo(subAccount); + RequestResult> result = NIMClient.syncRequest(future); + if (result.exception != null) { + e.onError(result.exception); + } else if (result.code != RESULT_OK) { + e.onError(new Exception("错误码: " + result.code)); + } else { + totalResult.addAll(result.data); + } + + subAccount.clear(); + } + + subAccount.add(sub); + } + + if (subAccount.size() > 0) { + InvocationFuture> future = + NIMClient.getService(UserService.class).fetchUserInfo(subAccount); + RequestResult> result = NIMClient.syncRequest(future); + if (result.exception != null) { + e.onError(result.exception); + } else if (result.code != RESULT_OK) { + e.onError(new Exception("错误码: " + result.code)); + } else { + totalResult.addAll(result.data); + } + } + + e.onSuccess(totalResult); + + }).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimP2PMessageActivity.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimP2PMessageActivity.java new file mode 100644 index 000000000..8c0bc6e47 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/NimP2PMessageActivity.java @@ -0,0 +1,497 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewStub; +import android.widget.ImageView; +import android.widget.TextView; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.model.contact.ContactChangedObserver; +import com.netease.nim.uikit.api.model.main.OnlineStateChangeObserver; +import com.netease.nim.uikit.api.model.user.UserInfoObserver; +import com.netease.nim.uikit.api.wrapper.NimToolBarOptions; +import com.netease.nim.uikit.business.session.constant.Extras; +import com.netease.nim.uikit.business.uinfo.UserInfoHelper; +import com.netease.nim.uikit.common.activity.ToolBarOptions; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.common.widget.CustomImageSpan; +import com.yizhuan.erban.ui.im.audio.ShakeHeartDialogFragment; +import com.yizhuan.erban.ui.im.fragment.MessageFragment; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.tutu.mentoring_relationship.dialog.BuildMentoringRelationshipSuccessDialog; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.audio.event.VoiceShakeHeartEvent; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.initial.bean.InitInfo; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.MentoringSuccessEvent; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.praise.event.IsLikedEvent; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import io.reactivex.functions.Consumer; + + +/** + * 点对点聊天界面 + *

+ * Created by huangjun on 2015/2/1. + */ +public class NimP2PMessageActivity extends NewBaseMessageActivity { + + private static final String TAG = "NimP2PMessageActivity"; + public static final String IS_BY_MATCH = "isByMatch"; + + private boolean isResume = false; + private ImageView ivAddBlackList; + public static long SYSTEM_MESSAGE_UID = XChatApplication.isDebug() ? + XChatConstants.SYSTEM_MESSAGER_UID_DEBUG : XChatConstants.SYSTEM_MESSAGER_UID; + public static long SECRETARY_UID = XChatApplication.isDebug() ? + XChatConstants.SECRETARY_UID_DEBUG : XChatConstants.SECRETARY_UID; + + private View tipsLayout; + private ImageView closeIcon; + private ImageView ivAttention; + private ViewStub vsGuideView; + private boolean isFromVoiceMatch; + + + public static void start(Context context, String contactId) { + startReal(context, contactId, new Intent()); + } + + public static void start(Context context, String contactId, boolean isFromVoiceMatch) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOUNT, contactId); + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonP2PSessionCustomization); + intent.putExtra("isFromVoiceMatch", isFromVoiceMatch); + intent.setClass(context, NimP2PMessageActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + + context.startActivity(intent); + } + + public static void startByMatch(Context context, String contactId) { + Intent intent = new Intent(); + intent.putExtra(IS_BY_MATCH, true); + startReal(context, contactId, intent); + + } + + public static void start(Context context, String contactId, String gameId) { + Intent intent = new Intent(); + intent.putExtra("gameId", gameId); + startReal(context, contactId, intent); + } + + /** + * 撩一下 + */ + public static void startWithAccost(Context context, String contactId) { + Intent intent = new Intent(); + intent.putExtra(Extras.EXTRA_ACCOST, true); + + startWithChatterBox(context, contactId, intent); + } + + /** + * 话匣子 + */ + public static void startWithChatterBox(Context context, String contactId, Intent intent) { + if (intent == null) + intent = new Intent(); + + intent.putExtra(Extras.EXTRA_CHATTER_BOX, true); + startReal(context, contactId, intent); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_PAGE_PRIVATE, "首页-私聊"); + } + + public static void startReal(Context context, String contactId, Intent intent) { + if (intent == null) + intent = new Intent(); + + intent.putExtra(Extras.EXTRA_ACCOUNT, contactId); + intent.putExtra(Extras.EXTRA_CUSTOMIZATION, NimUIKitImpl.commonP2PSessionCustomization); + intent.setClass(context, NimP2PMessageActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + + context.startActivity(intent); + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // 单聊特例话数据,包括个人信息,黑名单 + addBlackList(); + requestBuddyInfo(); + displayOnlineState(); + registerObservers(true); + registerOnlineStateChangeListener(true); + EventBus.getDefault().register(this); + displayAntiFraudTips(); + + vsGuideView = findViewById(R.id.vs_guide); + if (getIntent() != null) { + isFromVoiceMatch = getIntent().getBooleanExtra("isFromVoiceMatch", false); + } + if (isFromVoiceMatch) { +// showGuide(); + } + } + + private void showGuide() { + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_VOICE_MATCH_SAY_HI)) { + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_VOICE_MATCH_SAY_HI); + View guideView = vsGuideView.inflate(); + guideView.setOnClickListener(view -> guideView.setVisibility(View.GONE)); + } + } + + + private void displayAntiFraudTips() { + tipsLayout = findViewById(R.id.rl_tips); + closeIcon = findViewById(R.id.iv_close_tips); + if (shouldDisplayAntiFraudTips()) { + tipsLayout.setVisibility(View.VISIBLE); + closeIcon.setOnClickListener(view -> { + IMFriendModel.get().addCloseTipsAccount(sessionId); + tipsLayout.setVisibility(View.GONE); + }); + } else { + tipsLayout.setVisibility(View.GONE); + } + } + + private boolean shouldDisplayAntiFraudTips() { + return !IMFriendModel.get().isMyFriend(sessionId) && + (!(Objects.equals(sessionId, String.valueOf(SECRETARY_UID)) || + Objects.equals(sessionId, String.valueOf(SYSTEM_MESSAGE_UID)))) && + !IMFriendModel.get().hasCloseTips(sessionId); + } + + private void addBlackList() { + // 官方小秘书 + if (sessionId.equals(String.valueOf(SECRETARY_UID))) return; + // 系统消息 + if (Objects.equals(sessionId, String.valueOf(SYSTEM_MESSAGE_UID))) return; + ivAddBlackList = findViewById(com.yizhuan.erban.R.id.iv_add_black_list); + ivAddBlackList.setVisibility(View.VISIBLE); + ivAddBlackList.setOnClickListener((view) -> { + // 跳转到加入黑名单 + String account = getIntent().getStringExtra(Extras.EXTRA_ACCOUNT); + AddBlackListActivity.start(NimP2PMessageActivity.this, account); + }); + + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + registerObservers(false); + registerOnlineStateChangeListener(false); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onResume() { + super.onResume(); + isResume = true; + } + + @Override + protected void onStop() { + super.onStop(); + isResume = false; + } + + private void getNickFromSession() { + String userTitleName = UserInfoHelper.getUserTitleName(sessionId, SessionTypeEnum.P2P); + TextView tvToolbarTitle = getToolBar().findViewById(R.id.tv_toolbar_title); + if (tvToolbarTitle != null) { + tvToolbarTitle.setText(userTitleName); + tvToolbarTitle.setVisibility(View.VISIBLE); + } + } + + @SuppressLint("CheckResult") + private void requestBuddyInfo() { + getNickFromSession(); + // 如果有个人信息可以获取 + UserModel.get().getUserInfo(Long.valueOf(sessionId)).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + String badge = ""; + if (userInfo.getNobleInfo() != null) { + badge = NobleUtil.getLocalResourcePath(userInfo.getNobleInfo().getBadge()); + } + Drawable drawable = Drawable.createFromPath(badge); + // 显示自己的textView并且居中 + TextView tvToolbarTitle = getToolBar().findViewById(R.id.tv_toolbar_title); + // 不知道为什么要从云信获取titleName; + String userTitleName = (drawable == null ? "" : " ") + userInfo.getNick(); + SpannableStringBuilder builder = new SpannableStringBuilder(userTitleName); + if (drawable != null) { + int dimension = (int) getResources().getDimension(R.dimen.badge_tab_category_height); + drawable.setBounds(0, 0, dimension, dimension); + CustomImageSpan imageSpan = new CustomImageSpan(drawable); + builder.setSpan(imageSpan, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + tvToolbarTitle.setText(builder); + tvToolbarTitle.setVisibility(View.VISIBLE); + + ivAttention = (ImageView) findViewById(R.id.iv_attention); + if (AuthModel.get().getCurrentUid() != userInfo.getUid()) { + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), userInfo.getUid()).subscribe(); + } + } + }); + + setTitle(""); + // 显示是否 已经加入黑名单 + TextView tvAddBlackTip = getToolBar().findViewById(com.yizhuan.erban.R.id.tv_add_black_tip); + List blackListAccount = NimFriendModel.get().getMyBlackListAccount(); + tvAddBlackTip.setVisibility(View.GONE); + if (!ListUtils.isListEmpty(blackListAccount)) { + boolean contains = blackListAccount.contains(sessionId); + tvAddBlackTip.setVisibility(contains ? View.VISIBLE : View.GONE); + } + } + + private void registerObservers(boolean register) { + if (register) { + registerUserInfoObserver(); + } else { + unregisterUserInfoObserver(); + } + NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(commandObserver, register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + } + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + displayAntiFraudTips(); + } + + @Override + public void onDeletedFriends(List accounts) { + displayAntiFraudTips(); + } + + @Override + public void onAddUserToBlackList(List account) { + displayAntiFraudTips(); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + displayAntiFraudTips(); + } + }; + + private UserInfoObserver uinfoObserver; + + OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { + @Override + public void onlineStateChange(Set accounts) { + // 更新 toolbar + if (accounts.contains(sessionId)) { + // 按照交互来展示 + displayOnlineState(); + } + } + }; + + private void registerOnlineStateChangeListener(boolean register) { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register); + } + + private void displayOnlineState() { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + String detailContent = NimUIKitImpl.getOnlineStateContentProvider().getDetailDisplay(sessionId); + setSubTitle(detailContent); + } + + private void registerUserInfoObserver() { + if (uinfoObserver == null) { + uinfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + if (accounts.contains(sessionId)) { + requestBuddyInfo(); + } + } + }; + } + NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, true); + } + + private void unregisterUserInfoObserver() { + if (uinfoObserver != null) { + NimUIKit.getUserInfoObservable().registerObserver(uinfoObserver, false); + } + } + + /** + * 命令消息接收观察者 + */ + Observer commandObserver = new Observer() { + @Override + public void onEvent(CustomNotification message) { + if (!sessionId.equals(message.getSessionId()) || message.getSessionType() != SessionTypeEnum.P2P) { + return; + } + showCommandMessage(message); + } + }; + + protected void showCommandMessage(CustomNotification message) { + if (!isResume) { + return; + } + + String content = message.getContent(); + try { + JSONObject json = JSON.parseObject(content); + int id = json.getIntValue("id"); + // id 为 2,表示这是师徒里用到的系统通知,不要 toast 出来 + if (id == 2) return; + if (id == 1) { + // 正在输入 + SingleToastUtil.showToast("对方正在输入..."); + } + + } catch (Exception e) { + + } + } + + @Override + protected MessageFragment fragment() { + Bundle arguments = getIntent().getExtras(); + if (arguments == null) { + arguments = new Bundle(); + } + arguments.putSerializable(Extras.EXTRA_TYPE, SessionTypeEnum.P2P); + String gameId = getIntent().getStringExtra("gameId"); + if (!TextUtils.isEmpty(gameId)) { + arguments.putString("gameId", gameId); + } + MessageFragment fragment = new MessageFragment(); + fragment.setArguments(arguments); + fragment.setContainerId(R.id.message_fragment_container); + + // 等级限制:官方小秘书 和 系统消息,不设置等级限制 + if (!Objects.equals(sessionId, String.valueOf(SECRETARY_UID)) && + !Objects.equals(sessionId, String.valueOf(SYSTEM_MESSAGE_UID))) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + UserLevelVo userLevelVo = userInfo.getUserLevelVo(); + if (userLevelVo != null) { + fragment.setCurrentLevel(userLevelVo.experLevelSeq); + } + } + InitInfo initInfo = InitialModel.get().getCacheInitInfo(); + if (initInfo != null) { + fragment.setLimitLevel(initInfo.getPrivateChatLevelNo()); + } + } + return fragment; + } + + @Override + protected int getContentViewId() { + return R.layout.activity_p2p_message; + } + + @Override + protected void initToolBar() { + ToolBarOptions options = new NimToolBarOptions(); + setToolBar(R.id.toolbar, options); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMentoringSuccessEvent(MentoringSuccessEvent event) { + BuildMentoringRelationshipSuccessDialog dialog = new BuildMentoringRelationshipSuccessDialog(); + dialog.show(getSupportFragmentManager()); + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onIsLiked(IsLikedEvent event) { + if (event.isLiked) { + ivAttention.setVisibility(View.GONE); + } else { + ivAttention.setVisibility(View.VISIBLE); + ivAttention.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PraiseModel.get().praise(Long.valueOf(sessionId), true).subscribe(); + } + }); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + if (event.getLikedUid() != Long.valueOf(sessionId) || + Long.valueOf(sessionId) == AuthModel.get().getCurrentUid()) { + return; + } + if (event.isFailed()) { + toast(event.getError()); + return; + } + ivAttention.setVisibility(View.GONE); + ivAttention.setOnClickListener(null); + toast(event.isPraise() ? R.string.attention_success : R.string.cancel_fan_success); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onVoiceShakeHeart(VoiceShakeHeartEvent event) { + // 显示动画 + ShakeHeartDialogFragment shakeHeartDialogFragment = ShakeHeartDialogFragment.newInstance(event.showTextHint); + shakeHeartDialogFragment.show(getSupportFragmentManager(), "shake_heart"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/SwipeRecyclerViewItem.java b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/SwipeRecyclerViewItem.java new file mode 100644 index 000000000..fe816315d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/avtivity/SwipeRecyclerViewItem.java @@ -0,0 +1,148 @@ +package com.yizhuan.erban.ui.im.avtivity; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.animation.LinearOutSlowInInterpolator; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * 一个支持侧滑删除的item + * + * @author Administrator + * @date 2018/1/29 + */ + +public class SwipeRecyclerViewItem extends FrameLayout { + private Context mContext; + private RelativeLayout rlContent; + private TextView tvRemove; + private View root; + + public SwipeRecyclerViewItem(@NonNull Context context) { + this(context, null); + } + + public SwipeRecyclerViewItem(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SwipeRecyclerViewItem(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + mContext = context; + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mMaxFlingVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity(); + mMinFlingVelocity = 600; + root = LayoutInflater.from(context).inflate(R.layout.item_friend_black_list_manage, this, false); + rlContent = root.findViewById(R.id.rl_content); + tvRemove = root.findViewById(R.id.tv_remove); + addView(root); + } + + private int mTouchSlop; + private float mStartX; + private float mStartY; + private float mLastX; + private float mLastY; + private boolean disallowIntercept = false; + private VelocityTracker velocityTracker; + private int mMaxFlingVelocity; + private int mMinFlingVelocity; + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + int actionMasked = event.getActionMasked(); + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + velocityTracker.addMovement(event); + + switch (actionMasked) { + case MotionEvent.ACTION_DOWN: + mStartX = event.getX(); + mStartY = event.getY(); + mLastX = event.getX(); + mLastY = event.getY(); + break; + case MotionEvent.ACTION_MOVE: + float dx = event.getX() - mLastX; + float dy = event.getY() - mLastY; + // 如果没有拦截这个touch事件序列并且总体上是左右滑动的 + // 则要拦截这个事件 + if (!disallowIntercept && + Math.abs(event.getX() - mStartX) > Math.abs(event.getY() - mStartY)) { + // 一定要从左到右滑动 + // 并且横滑的距离要大于最小的touch slop + if (-(event.getX() - mStartX) > mTouchSlop) { + disallowIntercept = true; + } + } + // 只有自己拦截了touch事件才能滑动item + if (disallowIntercept) { + getParent().requestDisallowInterceptTouchEvent(true); + onItemSwipe(dx); + } + mLastX = event.getX(); + mLastY = event.getY(); + break; + case MotionEvent.ACTION_UP: + // 松开手后要根据已经滑动了的距离 + // 确定要自动滑动到哪个方向 + if (disallowIntercept) { + velocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity); + board(velocityTracker.getXVelocity()); + } + break; + default: + break; + } + // perform click + super.dispatchTouchEvent(event); + return true; + } + + /** + * 靠边动画 + */ + private void board(float velocityX) { + float translationX = rlContent.getTranslationX(); + float width = tvRemove.getWidth(); + // 确定要靠边的方向 + boolean overMiddle = Math.abs(-translationX) > width / 2; + // 从右往左滑动 + if (velocityX < 0 && -velocityX > mMinFlingVelocity) { + rlContent.animate().translationX(-width).setDuration(70).setInterpolator(new LinearOutSlowInInterpolator()).start(); + } else if (velocityX > 0 && velocityX > mMinFlingVelocity / 2) { + // 从左往右滑动 + rlContent.animate().translationX(0).setDuration(70).setInterpolator(new LinearOutSlowInInterpolator()).start(); + } else if (overMiddle) { + rlContent.animate().translationX(-width).setDuration(70).setInterpolator(new LinearOutSlowInInterpolator()).start(); + } else { + rlContent.animate().translationX(0).setDuration(70).setInterpolator(new LinearOutSlowInInterpolator()).start(); + } + } + + private void onItemSwipe(float dx) { + float translationX = rlContent.getTranslationX(); + if (dx + translationX < -tvRemove.getWidth()) { + dx = -tvRemove.getWidth() - translationX; + } else if (translationX + dx > 0) { + dx = -translationX; + } + rlContent.setTranslationX(translationX + dx); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxInit.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxInit.java new file mode 100644 index 000000000..0bd67f909 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxInit.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.im.chatterbox.ChatterBoxHelper; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import java.util.HashMap; +import java.util.Map; + +public class MVHChatterBoxInit extends MsgViewHolderBase implements View.OnClickListener { + private static final String LOCAL_CLICKED = "clicked"; + private TextView tvChatterBoxInit; + private Map localExtension; + + public MVHChatterBoxInit(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_chatterbox_init; + } + + @Override + protected void inflateContentView() { + tvChatterBoxInit = findViewById(R.id.tv_chatterbox_init); + localExtension = message.getLocalExtension(); + } + + @Override + protected void bindContentView() { + boolean clicked = false; + if (localExtension != null) { + Object object = localExtension.get(LOCAL_CLICKED); + if (object != null) { + clicked = (boolean) object; + } + } + + tvChatterBoxInit.setEnabled(!clicked); + if (!clicked) { + tvChatterBoxInit.setOnClickListener(this); + tvChatterBoxInit.setTextColor(ContextCompat.getColor(context, R.color.appColor)); + tvChatterBoxInit.setBackgroundResource(R.drawable.bg_chatterbox_init_valid); + } else { + tvChatterBoxInit.setTextColor(ContextCompat.getColor(context, R.color.color_CCCCCC)); + tvChatterBoxInit.setBackgroundResource(R.drawable.bg_chatterbox_init_invalid); + } + } + + @Override + public void onClick(View v) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MESSAGE_HOME_START_CHATTER_BOX, "首页-私聊-点击话匣子"); + + if (localExtension == null) { + localExtension = new HashMap<>(); + } + localExtension.put(LOCAL_CLICKED, true); + message.setLocalExtension(localExtension); + IMNetEaseManager.get().updateMessageToLocal(message); + adapter.notifyDataSetChanged(); + + ChatterBoxHelper.topicBoxCanSend(); + + } + + @Override + protected boolean isMiddleItem() { + return true; + } + + @Override + protected boolean isShowHeadImage() { + return false; + } + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxStart.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxStart.java new file mode 100644 index 000000000..bf450cacb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHChatterBoxStart.java @@ -0,0 +1,175 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.chatterbox.ChatterBoxModel; +import com.yizhuan.xchat_android_core.im.chatterbox.TopicBoxItemInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.ChatterBoxAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.DiceThrowAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.reactivex.functions.BiConsumer; + +public class MVHChatterBoxStart extends MsgViewHolderBase implements View.OnClickListener { + private static final String FLAG_THROW = "throwed"; + private TextView tvThrowDice; + private LinearLayout llChatTaskList; + private String sessionId; + + public static boolean isFromHome = false; + + public MVHChatterBoxStart(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_mvh_chatter_box_start; + } + + @Override + protected void inflateContentView() { + tvThrowDice = findViewById(R.id.tv_throw_dice); + llChatTaskList = findViewById(R.id.ll_chat_task_list); + tvThrowDice.setOnClickListener(this); + + } + + @Override + protected void bindContentView() { + contentContainer.setBackgroundResource(0); + llChatTaskList.removeAllViews(); + ChatterBoxAttachment attachment = (ChatterBoxAttachment) message.getAttachment(); + sessionId = message.getSessionId(); + + long startTime = attachment.startTime; + List taskList = attachment.listArray; + + if (taskList != null && taskList.size() > 0) { + + for (int i = 0; i < taskList.size(); i++) { + if (i == 11) // 最多展示11条数据 2~12 + break; + + View item = LayoutInflater.from(context).inflate(R.layout.item_chat_task, null); + TextView tvNum = item.findViewById(R.id.tv_task_num); + tvNum.setText(String.valueOf(i + 2)); + + TextView tvDescription = item.findViewById(R.id.tv_task_description); + tvDescription.setText("" + taskList.get(i).getContent()); + + llChatTaskList.addView(item); + } + + } + + boolean canClick; + Map map = message.getLocalExtension(); + + if (startTime != 0L && System.currentTimeMillis() - startTime >= 3 * 24 * 60 * 60 * 1000) { + canClick = false; + tvThrowDice.setText("已过期"); + + } else { + + if (map == null) { + canClick = true; + } else { + Object valueObject = map.get(FLAG_THROW); + if (valueObject != null) { + boolean value = (boolean) map.get(FLAG_THROW); + canClick = !value; + } else { + canClick = true; + } + } + + tvThrowDice.setText(canClick ? "抛点数" : "已抛"); + + } + + + tvThrowDice.setBackgroundResource(canClick ? R.drawable.chat_button_say : R.drawable.chat_button_say_unenable); + tvThrowDice.setEnabled(canClick); + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_throw_dice: + + if (tvThrowDice.isEnabled()) { + + if (isFromHome) + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MESSAGE_CHATTER_BOX_POINTS, " 消息-发起话匣子-抛点数"); + else + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_CHAT_NUMBER_OF_POINTS, "首页-私聊-话匣子游戏-抛点数"); + + } + tvThrowDice.setEnabled(false); + + int pointCount = (int) (1 + Math.random() * 6); + Log.i("pointCount", "" + pointCount); + + DiceThrowAttachment diceThrowAttachment = new DiceThrowAttachment(); + diceThrowAttachment.pointCount = pointCount; + CustomMessageConfig customMessageConfig = new CustomMessageConfig(); + customMessageConfig.enablePush = false; + IMMessage imMessage = MessageBuilder.createCustomMessage(sessionId, + SessionTypeEnum.P2P, "", diceThrowAttachment, customMessageConfig); + + // 发送掷骰子自定义消息 + IMNetEaseManager.get().sendMessageSingle(imMessage).subscribe(new BiConsumer() { + @Override + public void accept(IMMessage imMessage, Throwable throwable) throws Exception { + if (imMessage != null) { + MessageListPanelHelper.getInstance().notifyAddMessage(imMessage); + + // 更新消息状态 + Map map = message.getLocalExtension(); + if (map == null) { + map = new HashMap<>(); + map.put(FLAG_THROW, true); + message.setLocalExtension(map); + IMNetEaseManager.get().updateMessageToLocal(message); + adapter.notifyDataSetChanged(); + + } + + topicBoxReport(AuthModel.get().getCurrentUid(), Long.valueOf(imMessage.getSessionId())); + + } else + tvThrowDice.setEnabled(true); + + } + }); + + break; + } + + } + + private void topicBoxReport(long from, long to) { + ChatterBoxModel.get().topicBoxMsgReport(from, to, ChatterBoxModel.FLAG_TYPE_THROW_DICE).subscribe(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHDiceThrow.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHDiceThrow.java new file mode 100644 index 000000000..f38330755 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MVHDiceThrow.java @@ -0,0 +1,64 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.im.custom.bean.DiceThrowAttachment; + +public class MVHDiceThrow extends MsgViewHolderBase { + private ImageView ivDiceCount; + + public MVHDiceThrow(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + + @Override + protected int getContentResId() { + return R.layout.layout_dice_throw; + } + + @Override + protected void inflateContentView() { + ivDiceCount = findViewById(R.id.iv_dice_count); + } + + @Override + protected void bindContentView() { + contentContainer.setBackgroundResource(0); + DiceThrowAttachment attachment = (DiceThrowAttachment) message.getAttachment(); + + if (attachment != null) { + switch (attachment.pointCount) { + case 1: + ivDiceCount.setImageResource(R.drawable.dice_1); + break; + + case 2: + ivDiceCount.setImageResource(R.drawable.dice_2); + break; + + case 3: + ivDiceCount.setImageResource(R.drawable.dice_3); + break; + + case 4: + ivDiceCount.setImageResource(R.drawable.dice_4); + break; + + case 5: + ivDiceCount.setImageResource(R.drawable.dice_5); + break; + + case 6: + ivDiceCount.setImageResource(R.drawable.dice_6); + break; + + } + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderAudioParty.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderAudioParty.java new file mode 100644 index 000000000..f78743bae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderAudioParty.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.miniworld.bean.OpenAudioPartyAttachment; +import com.yizhuan.xchat_android_core.miniworld.model.MiniWorldHelper; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +public class MsgViewHolderAudioParty extends MsgViewHolderBase implements View.OnClickListener { + private ImageView ivIcAudioParty; + private TextView tvLabel; + private View container; + + public MsgViewHolderAudioParty(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.msg_open_audio_party; + } + + @Override + protected void inflateContentView() { + ivIcAudioParty = findViewById(R.id.iv_ic_audio_party); + tvLabel = findViewById(R.id.tv_label_audio_party); + container = findViewById(R.id.layout_container); + } + + @Override + protected void bindContentView() { + OpenAudioPartyAttachment attachment = (OpenAudioPartyAttachment) message.getAttachment(); + + if (message.getFromAccount().equals(String.valueOf(AuthModel.get().getCurrentUid()))) { // 自己 + contentContainer.setBackgroundResource(R.drawable.bg_ap_water_drop_self); + ivIcAudioParty.setImageResource(R.drawable.ic_msg_audio_party_white); + tvLabel.setTextColor(ContextCompat.getColor(tvLabel.getContext(), R.color.white)); + tvLabel.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(tvLabel.getContext(), R.drawable.ic_msg_audio_party_arrow_white), null); + + } else if (attachment.isOwnerFlag()) { // 群主 + contentContainer.setBackgroundResource(R.drawable.bg_ap_water_drop_owner); + ivIcAudioParty.setImageResource(R.drawable.ic_msg_audio_party_white); + tvLabel.setTextColor(ContextCompat.getColor(tvLabel.getContext(), R.color.white)); + tvLabel.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(tvLabel.getContext(), R.drawable.ic_msg_audio_party_arrow_white), null); + + } else { + contentContainer.setBackgroundResource(R.drawable.bg_nim_water_drop_other); + ivIcAudioParty.setImageResource(R.drawable.ic_msg_audio_party_color); + tvLabel.setTextColor(ContextCompat.getColor(tvLabel.getContext(), R.color.color_FE6974)); + tvLabel.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(tvLabel.getContext(), R.drawable.ic_msg_audio_party_arrow), null); + + } + + container.setOnClickListener(this); + + } + + @Override + public void onClick(View v) { + OpenAudioPartyAttachment attachment = (OpenAudioPartyAttachment) message.getAttachment(); + if (attachment == null || attachment.getRoomUid() == 0) { + SingleToastUtil.showToast("无房间信息"); + return; + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_MINI_WORLD_JOIN_PARTY, "世界客态页-群聊-加入语音派对"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_PAGE_ENTER_PARTY, + "加入语音派对:群聊"); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_PAGE_ENTER_PARTY_B, + "加入语音派对:世界id:" + attachment.getWorldId()); + MiniWorldHelper.report(attachment.getWorldId(), MiniWorldHelper.TYPE_AUDIO_PARTY_JOIN); + AVRoomActivity.start(v.getContext(), attachment.getRoomUid()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderContent.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderContent.java new file mode 100644 index 000000000..669bc0330 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderContent.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.im.custom.bean.NoticeAttachment; + +/** + * Created by chenran on 2017/9/21. + */ + +public class MsgViewHolderContent extends MsgViewHolderBase implements View.OnClickListener { + + private ImageView bg; + private TextView title; + private TextView desc; + private LinearLayout container; + + public MsgViewHolderContent(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_content; + } + + @Override + protected void inflateContentView() { + bg = findViewById(R.id.bg_image); + title = findViewById(R.id.title); + desc = findViewById(R.id.desc); + container = findViewById(R.id.layout); + } + + @Override + protected void bindContentView() { + NoticeAttachment attachment = (NoticeAttachment) message.getAttachment(); + if (!StringUtil.isEmpty(attachment.getPicUrl())) { + bg.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(bg.getContext(), attachment.getPicUrl(), bg, R.drawable.default_cover); + } else { + bg.setVisibility(View.GONE); + } + + title.setText(attachment.getTitle()); + desc.setText(attachment.getDesc()); + container.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + NoticeAttachment attachment = (NoticeAttachment) message.getAttachment(); + if (!StringUtil.isEmpty(attachment.getWebUrl())) { + CommonWebViewActivity.start(context, attachment.getWebUrl()); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGame.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGame.java new file mode 100644 index 000000000..48c003070 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGame.java @@ -0,0 +1,157 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.databinding.DataBindingUtil; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.game.PlayGameActivity; +import com.yizhuan.erban.databinding.ItemImGameBinding; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.game.ImGameInfo; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.room.game.GameUrlInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.ServerException; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +public class MsgViewHolderGame extends MsgViewHolderBase { + private ItemImGameBinding mBinding; + + public MsgViewHolderGame(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.item_im_game; + } + + @Override + protected void inflateContentView() { + mBinding = DataBindingUtil.bind(view.findViewById(R.id.root)); + LinearLayout bodyContainer = (LinearLayout) view.findViewById(com.netease.nim.uikit.R.id.message_item_body); + if (isReceivedMessage()) { + setGravity(bodyContainer, Gravity.LEFT); + } else { + setGravity(bodyContainer, Gravity.RIGHT); + } + } + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected void bindContentView() { + + ImGameAttachment attachment = (ImGameAttachment) message.getAttachment(); + if (attachment != null && attachment.getImGameInfo() != null) { + final ImGameInfo imGameInfo = attachment.getImGameInfo(); + ImageLoadUtils.loadImage(context, imGameInfo.getGameInfo().getGamePicture(), mBinding.ivImg); + mBinding.tvName.setText(imGameInfo.getGameInfo().getGameName()); + + if (imGameInfo.getStatus() == ImGameInfo.TIMEING) { + if ((imGameInfo.getStartTime() + ImGameMode.TIME * 1000 > System.currentTimeMillis())) { + mBinding.shade.setVisibility(View.GONE); + mBinding.tvTime.setVisibility(View.VISIBLE); + mBinding.tvTime.setText(imGameInfo.getTime() + ""); + if (isReceivedMessage()) { + mBinding.tvStatus.setText("接受"); + mBinding.tvStatus.setTextColor(context.getResources().getColor(R.color.appColor)); + } else { + mBinding.tvStatus.setText("等待对方接受邀请…"); + mBinding.tvStatus.setTextSize(14); + mBinding.tvStatus.setTextColor(context.getResources().getColor(R.color.color_999999)); + } + } else { + setStatusText("约战已失效"); + } + } else if (imGameInfo.getStatus() == ImGameInfo.ACCEPTED) { + setStatusText("约战已结束"); + } else if (imGameInfo.getStatus() == ImGameInfo.INVALID) { + setStatusText("约战已失效"); + } + + mBinding.tvName.setText(imGameInfo.getGameInfo().getGameName()); + mBinding.tvStatus.setOnClickListener(v -> { + if (isReceivedMessage() && (imGameInfo.getStartTime() + ImGameMode.TIME * 1000 > System.currentTimeMillis())) { + if (mBinding.tvStatus.getText().equals("接受")) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_accept, "私聊接受"); + + ImGameMode.get().getGameUrl( + JavaUtil.str2long(message.getFromAccount()), + message.getFromNick(), + AuthModel.get().getCurrentUid(), + UserModel.get().getCacheLoginUserInfo().getNick(), + imGameInfo.getGameInfo().getGameId(), + imGameInfo.getGameInfo().getGameChannel(), + message.getUuid() + ).doOnError(throwable -> { + if (throwable instanceof ServerException) { + if (((ServerException) throwable).code == 20002) { + setGameInvalid(attachment, new GameUrlInfo()); + } + } + }) + .subscribe(gameUrlInfo -> { + ImGameInfo imGameInfo1 = setGameInvalid(attachment, gameUrlInfo); + + // 发送自定义系统通知通知对方状态改变 + CustomNotification notification = new CustomNotification(); + notification.setSessionId(message.getFromAccount()); + notification.setSessionType(SessionTypeEnum.P2P); + + String jsonStr = new Gson().toJson(imGameInfo1); + JSONObject json = JSONObject.parseObject(jsonStr); + notification.setContent(json.toString()); + + NIMClient.getService(MsgService.class).sendCustomNotification(notification); + + PlayGameActivity.start(context, gameUrlInfo.getReceiveGameUrl(), JavaUtil.str2long(message.getFromAccount()), message.getUuid()); + }); + } + + } + + }); + } + } + + private ImGameInfo setGameInvalid(ImGameAttachment attachment, GameUrlInfo gameUrlInfo) { + ImGameAttachment imGameAttachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + ImGameInfo imGameInfo1 = attachment.getImGameInfo() + .setUuId(message.getUuid()) + .setStatus(ImGameInfo.ACCEPTED) + .setGameUrl(gameUrlInfo.getGameUrl()); + + imGameAttachment.setImGameInfo(imGameInfo1); + message.setAttachment(imGameAttachment); + NIMClient.getService(MsgService.class).updateIMMessageStatus(message); + refreshCurrentItem(); + return imGameInfo1; + } + + private void setStatusText(String text) { + mBinding.tvTime.setVisibility(View.GONE); + mBinding.shade.setVisibility(View.VISIBLE); + mBinding.tvStatus.setText(text); + mBinding.tvStatus.setTextSize(16); + mBinding.tvStatus.setTextColor(context.getResources().getColor(R.color.color_999999)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGift.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGift.java new file mode 100644 index 000000000..3e1212215 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderGift.java @@ -0,0 +1,74 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.im.custom.bean.GiftAttachment; + +/** + * Created by chenran on 2017/10/3. + */ + +public class MsgViewHolderGift extends MsgViewHolderBase { + private ImageView avatar; + private TextView number; + private TextView giftName; + private TextView tvTargetNick; + private LinearLayout container; + private FrameLayout flGiftImg; + + public MsgViewHolderGift(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_gift; + } + + @Override + protected void inflateContentView() { + avatar = findViewById(R.id.avatar); + number = findViewById(R.id.gift_number); + container = findViewById(R.id.layout_container); + giftName = findViewById(R.id.gift_name); + tvTargetNick = findViewById(R.id.tv_target_nick); + flGiftImg = findViewById(R.id.fl_gift_img); + } + + @Override + protected void bindContentView() { + GiftAttachment attachment = (GiftAttachment) message.getAttachment(); + GiftInfo giftInfo = attachment.getGiftReceiveInfo().getGift(); + giftInfo = giftInfo == null ? + GiftModel.get().findGiftInfoById(attachment.getGiftReceiveInfo().getGiftId()) : giftInfo; + + boolean isSelf = attachment.getGiftReceiveInfo().getUid() == AuthModel.get().getCurrentUid(); + giftName.setTextColor(isSelf ? ContextCompat.getColor(context, R.color.white) : ContextCompat.getColor(context, R.color.color_333333)); + number.setTextColor(isSelf ? ContextCompat.getColor(context, R.color.white) : ContextCompat.getColor(context, R.color.color_333333)); + tvTargetNick.setTextColor(isSelf ? ContextCompat.getColor(context, R.color.white_transparent_80) : ContextCompat.getColor(context, R.color.color_999999)); + flGiftImg.setBackgroundResource(isSelf ? R.drawable.bg_msg_gift_img : R.drawable.bg_msg_gift_img_normal); + + if (giftInfo != null) { + ImageLoadUtils.loadImage(avatar.getContext(), giftInfo.getGiftUrl(), avatar); + number.setText("X" + attachment.getGiftReceiveInfo().getGiftNum()); + giftName.setText(giftInfo.getGiftName()); + + String targetNick = attachment.getGiftReceiveInfo().getTargetNick(); + if (!TextUtils.isEmpty(targetNick)) { + tvTargetNick.setText("赠给 " + targetNick); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLevel.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLevel.java new file mode 100644 index 000000000..8d13f9486 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLevel.java @@ -0,0 +1,55 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LevelUpAttachment; + +/** + * Created by chenran on 2017/10/3. + */ + +public class MsgViewHolderLevel extends MsgViewHolderBase { + private ImageView avatar; + private TextView giftName; + private LinearLayout container; + + public MsgViewHolderLevel(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_level; + } + + @Override + protected void inflateContentView() { + avatar = findViewById(R.id.avatar); + container = findViewById(R.id.layout_container); + giftName = findViewById(R.id.gift_name); + } + + @Override + protected void bindContentView() { + LevelUpAttachment attachment = (LevelUpAttachment) message.getAttachment(); + if (attachment.getSecond()== CustomAttachment.CUSTOM_MSG_EXPER_LEVEL_UP){ + avatar.setImageResource(R.drawable.ic_chat_user_level); + giftName.setText("恭喜!您的等级已到达"+attachment.levelName); + container.setOnClickListener(v -> CommonWebViewActivity.start(context, UriProvider.getUserLevelUrl() + "&uid=" + AuthModel.get().getCurrentUid())); + }else if (attachment.getSecond()== CustomAttachment.CUSTOM_MSG_CHARM_LEVEL_UP){ + avatar.setImageResource(R.drawable.ic_chat_charm_level); + giftName.setText("恭喜!您的魅力等级已到达"+attachment.levelName); + container.setOnClickListener(v -> CommonWebViewActivity.start(context, UriProvider.getUserCharmLevelUrl() + "&uid=" + AuthModel.get().getCurrentUid())); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLottery.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLottery.java new file mode 100644 index 000000000..2c4d430f5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderLottery.java @@ -0,0 +1,43 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; + +/** + * Created by chenran on 2018/1/2. + */ + +public class MsgViewHolderLottery extends MsgViewHolderBase implements View.OnClickListener{ + private TextView content; + + public MsgViewHolderLottery(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_lottery; + } + + @Override + protected void inflateContentView() { + content = findViewById(R.id.content); + content.setOnClickListener(this); + } + + @Override + protected void bindContentView() { + + } + + @Override + public void onClick(View v) { + CommonWebViewActivity.start(context, UriProvider.getLotteryActivityPage()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderNoti.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderNoti.java new file mode 100644 index 000000000..707fcec84 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderNoti.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.ui.im.chat; + +/** + * Created by chenran on 2017/9/21. + */ + +public class MsgViewHolderNoti { +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderOnline.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderOnline.java new file mode 100644 index 000000000..32e476f7c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderOnline.java @@ -0,0 +1,68 @@ + +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.uinfo.UserService; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenRoomNotiAttachment; + +/** + * Created by chenran on 2017/9/21. + */ + +public class MsgViewHolderOnline extends MsgViewHolderBase implements View.OnClickListener { + private ImageView avatar; + private TextView nick; + private LinearLayout container; + + public MsgViewHolderOnline(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_online; + } + + @Override + protected void inflateContentView() { + avatar = findViewById(R.id.avatar); + nick = findViewById(R.id.nick); + container = findViewById(R.id.layout_container); + } + + @Override + protected void bindContentView() { + OpenRoomNotiAttachment attachment = (OpenRoomNotiAttachment) message.getAttachment(); + if (attachment != null) { + if (!StringUtil.isEmpty(attachment.getNick())) { + nick.setText(attachment.getNick() + " 上线啦"); + ImageLoadUtils.loadAvatar(avatar.getContext(), attachment.getAvatar(), avatar); + } else { + NimUserInfo nimUserInfo = NIMClient.getService(UserService.class).getUserInfo(attachment.getUid() + ""); + if (nimUserInfo != null) { + nick.setText(nimUserInfo.getName() + " 上线啦"); + ImageLoadUtils.loadAvatar(avatar.getContext(), nimUserInfo.getAvatar(), avatar); + } + } + container.setOnClickListener(this); + } + } + + @Override + public void onClick(View v) { + OpenRoomNotiAttachment attachment = (OpenRoomNotiAttachment) message.getAttachment(); + AVRoomActivity.start(v.getContext(), attachment.getUid()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderRedPacket.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderRedPacket.java new file mode 100644 index 000000000..849c921ca --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderRedPacket.java @@ -0,0 +1,46 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.im.custom.bean.RedPacketAttachment; + +/** + * Created by chenran on 2017/9/21. + */ + +public class MsgViewHolderRedPacket extends MsgViewHolderBase implements View.OnClickListener { + private TextView text; + private LinearLayout container; + + public MsgViewHolderRedPacket(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_red_packet; + } + + @Override + protected void inflateContentView() { + text = findViewById(R.id.tip_text); + container = findViewById(R.id.layout_container); + } + + @Override + protected void bindContentView() { + RedPacketAttachment attachment = (RedPacketAttachment) message.getAttachment(); + text.setText("收到" + attachment.getRedPacketInfo().getPacketName() + "红包,快去看看吧!"); + container.setOnClickListener(this); + } + + @Override + public void onClick(View v) { +// context.startActivity(new Intent(context, RedBagActivity.class)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderText.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderText.java new file mode 100644 index 000000000..ed1deed30 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderText.java @@ -0,0 +1,144 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.text.style.ForegroundColorSpan; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.MyDecorationActivity; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.audio.bean.VoiceBottleSayHiInfo; +import com.yizhuan.xchat_android_core.audio.event.VoiceShakeHeartEvent; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.AssistantAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarveUpGoldThirdLevelAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.VoiceBottleShakeHeartAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; + +import org.greenrobot.eventbus.EventBus; + +import java.util.HashMap; +import java.util.Map; + +import static com.yizhuan.xchat_android_core.UriProvider.IM_SERVER_URL; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_SUB_CAR_EXPIRE; + +/** + *

文字消息holder

+ * + * @author jiahui + * @date 2018/1/10 + */ +public class MsgViewHolderText extends MsgViewHolderBase { + private TextView mTvMsg; + private NobleAttachment mNobleAttachment; + private CarAttachment mCarAttachment; + private AssistantAttachment awardAttachment; + + public MsgViewHolderText(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.im_customer_msg_text; + } + + @Override + protected void inflateContentView() { + mTvMsg = findViewById(R.id.tv_msg); + } + + @Override + protected void bindContentView() { + CharSequence text = ""; + MsgAttachment attachment = message.getAttachment(); + if (attachment instanceof CarAttachment) { + mCarAttachment = (CarAttachment) attachment; + text = mCarAttachment.msg; + } else if (attachment instanceof NobleAttachment) { + mNobleAttachment = (NobleAttachment) attachment; + text = mNobleAttachment.msg; + } else if (attachment instanceof AssistantAttachment) { + awardAttachment = (AssistantAttachment) attachment; + text = awardAttachment.msg; + } else if (attachment instanceof CarveUpGoldThirdLevelAttachment) { + //瓜分金币 三级 + CarveUpGoldThirdLevelAttachment cuAttachment = (CarveUpGoldThirdLevelAttachment) attachment; + int appColor = context.getResources().getColor(R.color.appColor); + SpannableBuilder builder = new SpannableBuilder() + .append("【签到瓜分百万】哇塞,恭喜 ") + .append(cuAttachment.getNick() + " ", new ForegroundColorSpan(appColor)) + .append("签到获得 ") + .append(cuAttachment.getGoldNum() + "金币", new ForegroundColorSpan(appColor)) + .append("!"); + text = builder.build(); + } else if (attachment instanceof VoiceBottleShakeHeartAttachment) { + VoiceBottleShakeHeartAttachment shakeHeartAttachment = (VoiceBottleShakeHeartAttachment) attachment; + VoiceBottleSayHiInfo sayHiInfo = shakeHeartAttachment.getSayHiInfo(); + if (sayHiInfo != null) { + text = sayHiInfo.getMessage(); + } else { + text = context.getString(R.string.voice_im_msg_text); + } + + String heartHint; + if (message.getFromAccount().equals(String.valueOf(AuthModel.get().getCurrentUid()))) { + heartHint = "已向对方发送一颗小心心~"; + } else { + heartHint = "Ta向你发送了一颗小心心~"; + } + Map localExtension = message.getLocalExtension(); + if (localExtension != null && localExtension.containsKey(VoiceBottleShakeHeartAttachment.KEY_VOICE_BOTTLE_NEED_SHAKE_HEART)) { + boolean isNeedShakeHeart = (boolean) localExtension.get(VoiceBottleShakeHeartAttachment.KEY_VOICE_BOTTLE_NEED_SHAKE_HEART); + if (isNeedShakeHeart) { + EventBus.getDefault().post(new VoiceShakeHeartEvent(heartHint));// 爱心动画 + } + } else { + EventBus.getDefault().post(new VoiceShakeHeartEvent(heartHint));// 爱心动画 + } + + if (localExtension == null) { + localExtension = new HashMap<>(); + } + localExtension.put(VoiceBottleShakeHeartAttachment.KEY_VOICE_BOTTLE_NEED_SHAKE_HEART, false); + message.setLocalExtension(localExtension); + IMNetEaseManager.get().updateMessageToLocal(message); + } + mTvMsg.setText(text); + } + + @Override + protected void onItemClick() { + if (mNobleAttachment != null) { + switch (mNobleAttachment.mSecond) { + case CustomAttachment.CUSTOM_MSG_HEADER_TYPE_GOOD_NUMBER_INACTIVE: + CommonWebViewActivity.start(mTvMsg.getContext(), IM_SERVER_URL + "modules/nobles/numApply.html"); + break; + case CustomAttachment.CUSTOM_MSG_HEADER_TYPE_NOBLE_END: + //http://beta.tutuyuyin.com/modules/nobles/order.html?nobleIndex=1 + CommonWebViewActivity.start(mTvMsg.getContext(), IM_SERVER_URL + "modules/nobles/order.html"); + break; + case CustomAttachment.CUSTOM_MESS_SUB_HADEXPIRE: + CommonWebViewActivity.start(mTvMsg.getContext(), UriProvider.getNobleIntro()); + break; + default: + } + + } else if (mCarAttachment != null) { + if (mCarAttachment.mSecond == CUSTOM_MESS_SUB_CAR_EXPIRE) { + MyDecorationActivity.start(mTvMsg.getContext(), 1); + } + } else if (awardAttachment != null) { + RouterHandler.handle(context, awardAttachment.routerType, awardAttachment.routerValue); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderTip.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderTip.java new file mode 100644 index 000000000..e84c63748 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderTip.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.databinding.DataBindingUtil; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.ItemImTipsBinding; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; + +public class MsgViewHolderTip extends MsgViewHolderBase { + + private ItemImTipsBinding mBinding; + + public MsgViewHolderTip(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.item_im_tips; + } + + @Override + protected boolean isMiddleItem() { + return true; + } + + @Override + protected void inflateContentView() { + mBinding = DataBindingUtil.bind(findViewById(R.id.root)); + } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } + + @Override + protected void bindContentView() { + ImTipAttachment attachment = (ImTipAttachment) message.getAttachment(); + if (attachment != null) { + mBinding.tvTips.setText(attachment.getMsg()); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderVoiceBottleSayHi.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderVoiceBottleSayHi.java new file mode 100644 index 000000000..a39bc68ee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/MsgViewHolderVoiceBottleSayHi.java @@ -0,0 +1,136 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.helper.MessageListPanelHelper; +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.audio.bean.VoiceBottleSayHiInfo; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.custom.bean.VoiceBottleSayHiAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.VoiceBottleShakeHeartAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.HashMap; +import java.util.Map; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 声音瓶子打招呼提示信息 + */ +public class MsgViewHolderVoiceBottleSayHi extends MsgViewHolderBase implements View.OnClickListener { + + + private TextView tvSayHi; + private Map localExtension; + private VoiceBottleSayHiInfo sayHiInfo; + + public MsgViewHolderVoiceBottleSayHi(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_voice_bottle_say_hi; + } + + @Override + protected void inflateContentView() { + IMMessage imMessage = IMNetEaseManager.get().queryMessageByUuid(message.getUuid()); + if (imMessage != null) { + localExtension = imMessage.getLocalExtension(); + } + MsgAttachment attachment = message.getAttachment(); + if (attachment instanceof VoiceBottleSayHiAttachment) { + VoiceBottleSayHiAttachment sayHiAttachment = (VoiceBottleSayHiAttachment) attachment; + sayHiInfo = sayHiAttachment.getSayHiInfo(); + } + tvSayHi = findViewById(R.id.tv_voice_say_hi); + } + + @Override + protected void bindContentView() { + if (localExtension != null && localExtension.containsKey(VoiceBottleSayHiAttachment.KEY_VOICE_BOTTLE_HAVE_SAY_HI)) { + boolean haveSayHi = (boolean) localExtension.get(VoiceBottleSayHiAttachment.KEY_VOICE_BOTTLE_HAVE_SAY_HI); + tvSayHi.setEnabled(!haveSayHi); + } else { + tvSayHi.setEnabled(true); + } + tvSayHi.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.tv_voice_say_hi) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_PRIVATE_CHAT_SAY_HELLO, "私聊页-打个招呼"); + // 更新当前打招呼消息 + Map extension = message.getLocalExtension(); + if (extension == null) { + extension = new HashMap<>(); + } + extension.put(VoiceBottleSayHiAttachment.KEY_VOICE_BOTTLE_HAVE_SAY_HI, true); + this.localExtension = extension; + message.setLocalExtension(localExtension); + IMNetEaseManager.get().updateMessageToLocal(message); + tvSayHi.setEnabled(false); + + // 发消息给对方 + IMMessage shakeHeartMessage = MessageBuilder.createCustomMessage( + String.valueOf(message.getSessionId()), + SessionTypeEnum.P2P, new VoiceBottleShakeHeartAttachment(sayHiInfo)); + shakeHeartMessage.setFromAccount(String.valueOf(AuthModel.get().getCurrentUid())); + HashMap localExtension = new HashMap<>(); + localExtension.put(VoiceBottleShakeHeartAttachment.KEY_VOICE_BOTTLE_NEED_SHAKE_HEART, true); + shakeHeartMessage.setLocalExtension(localExtension); + IMNetEaseManager.get().sendMessageSingle(shakeHeartMessage) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(IMMessage imMessage) { + MessageListPanelHelper.getInstance().notifyAddMessage(imMessage);// 手动刷新 UI + } + + @Override + public void onError(Throwable e) { + SingleToastUtil.showToast(e.getMessage()); + } + }); + } + } + + @Override + protected boolean isMiddleItem() { + return true; + } + + @Override + protected boolean isShowHeadImage() { + return false; + } + + @Override + protected boolean isShowBubble() { + return false; + } + + @Override + protected boolean shouldDisplayReceipt() { + return false; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/SignInNoticeMsgViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SignInNoticeMsgViewHolder.java new file mode 100644 index 000000000..a96e0928d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SignInNoticeMsgViewHolder.java @@ -0,0 +1,54 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.view.View; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.radish.signin.SignInActivity; +import com.yizhuan.xchat_android_core.im.custom.bean.OpenSignInAttachment; + +/** + * 签到提醒 + * create by lvzebiao @2019/3/20 + */ +public class SignInNoticeMsgViewHolder extends MsgViewHolderBase { + + private View llSignInContainer; + + private TextView tvContent; + + private TextView tvTitle; + + public SignInNoticeMsgViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_sign_in_notice; + } + + @Override + protected void inflateContentView() { + llSignInContainer = findViewById(R.id.ll_sign_in_container); + tvContent = findViewById(R.id.tv_content); + tvTitle = findViewById(R.id.tv_title); + } + + @Override + protected void bindContentView() { + llSignInContainer.setOnClickListener(v -> SignInActivity.start(context)); + OpenSignInAttachment attachment = (OpenSignInAttachment) message.getAttachment(); + //setData + String title = null; + String content = null; + if (attachment != null && attachment.getImNotice() != null) { + title = attachment.getImNotice().getTitle(); + content = attachment.getImNotice().getContent(); + } + tvTitle.setText(title); + tvContent.setText(content); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgViewHolder.java new file mode 100644 index 000000000..3e7391779 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgViewHolder.java @@ -0,0 +1,311 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.MetricAffectingSpan; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.alibaba.fastjson.JSON; +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.miniworld.activity.MiniWorldGuestPageActivity; +import com.yizhuan.erban.sys.ErbanSysMsgViewModel; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.xchat_android_core.im.custom.bean.SysMsgAttachment; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.msg.sys.ApproveMsgInfo; +import com.yizhuan.xchat_android_core.msg.sys.ErbanSysMsgComponent; +import com.yizhuan.xchat_android_core.msg.sys.ErbanSysMsgInfo; +import com.yizhuan.xchat_android_core.msg.sys.ErbanSysMsgLayout; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_COMMON_SYSTEM_MSG; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEAD_SHIFT_OUT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SHIFT_OUT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_COMMON_SYSTEM_MSG_APPROVAL; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_COMMON_SYSTEM_MSG_TEXT; + +/** + * Created by MadisonRong on 17/06/2018. + */ + +public class SysMsgViewHolder extends MsgViewHolderBase implements View.OnClickListener { + + private View container; + private TextView title; + private TextView timestamp; + private TextView content; + private TextView approvalState; + private TextView tvRejoinMW; + private FrameLayout flRejoin; + private RelativeLayout resultLayout; + private RelativeLayout operationLayout; + private ErbanSysMsgInfo erbanSysMsgInfo; + private ErbanSysMsgViewModel viewModel; + + public SysMsgViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_sys_msg_view_holder; + } + + @Override + protected void inflateContentView() { + container = findViewById(R.id.ll_container); + approvalState = findViewById(R.id.tv_result); + resultLayout = findViewById(R.id.rl_result_layout); + operationLayout = findViewById(R.id.rl_operators); + tvRejoinMW = findViewById(R.id.tv_rejoin_mw); + flRejoin = findViewById(R.id.fl_rejoin); + title = findViewById(R.id.tv_title); + timestamp = findViewById(R.id.tv_timestamp); + content = findViewById(R.id.tv_content); + viewModel = new ErbanSysMsgViewModel(); + container.setOnClickListener(this); + tvRejoinMW.setOnClickListener(this); + findViewById(R.id.btn_reject).setOnClickListener(this); + findViewById(R.id.btn_agree).setOnClickListener(this); + } + + @Override + protected void bindContentView() { + IMMessage sysMsgInfoMessage = IMNetEaseManager.get().queryMessageByUuid(message.getUuid()); + SysMsgAttachment sysMsgAttachment; + if (sysMsgInfoMessage == null) { + sysMsgAttachment = (SysMsgAttachment) message.getAttachment(); + IMNetEaseManager.get().saveMessageToLocal(message); + erbanSysMsgInfo = sysMsgAttachment.getErbanSysMsgInfo(); + message.setLocalExtension(ErbanSysMsgInfo.convertToMap(erbanSysMsgInfo)); + IMNetEaseManager.get().updateErbanSysMsgInfoMessage(message.getUuid(), erbanSysMsgInfo); + } else { + sysMsgAttachment = (SysMsgAttachment) sysMsgInfoMessage.getAttachment(); + if (sysMsgInfoMessage.getLocalExtension() == null) { + erbanSysMsgInfo = sysMsgAttachment.getErbanSysMsgInfo(); + } else { + erbanSysMsgInfo = ErbanSysMsgInfo.convertMapToObject(sysMsgInfoMessage.getLocalExtension()); + } + sysMsgInfoMessage.setLocalExtension(ErbanSysMsgInfo.convertToMap(erbanSysMsgInfo)); + IMNetEaseManager.get().updateErbanSysMsgInfoMessage(sysMsgInfoMessage.getUuid(), erbanSysMsgInfo); + } + + String layout = erbanSysMsgInfo.getLayout(); + ErbanSysMsgLayout erbanSysMsgLayout; + try { + erbanSysMsgLayout = JSON.parseObject(layout, ErbanSysMsgLayout.class); + + } catch (Exception ex) { // json解析出错 + ex.printStackTrace(); + return; + } + + // title + setupView(title, erbanSysMsgLayout.getTitle()); + // timestamp + setupView(timestamp, erbanSysMsgLayout.getTime()); + // content + List erbanSysMsgLayoutContent = erbanSysMsgLayout.getContents(); + if (erbanSysMsgLayoutContent != null) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + for (ErbanSysMsgComponent erbanSysMsgComponent : erbanSysMsgLayoutContent) { + int start = spannableStringBuilder.length(); + String msgBody = erbanSysMsgComponent.getContent(); + if (Objects.equals(msgBody, "/r/n")) { + msgBody = "\r\n"; + spannableStringBuilder.append(msgBody); + continue; + } + spannableStringBuilder.append(msgBody); + if (erbanSysMsgComponent.getFontColor() != null) { + spannableStringBuilder.setSpan(new ForegroundColorSpan(Color.parseColor(erbanSysMsgComponent.getFontColor())), + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + if (erbanSysMsgComponent.getFontSize() > 0) { + spannableStringBuilder.setSpan(new AbsoluteSizeSpan(SizeUtils.sp2px(content.getContext(), erbanSysMsgComponent.getFontSize() + 0.5F)), + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + spannableStringBuilder.setSpan( + new MetricAffectingSpan() { + @Override + public void updateMeasureState(TextPaint p) { + + } + + @Override + public void updateDrawState(TextPaint tp) { + tp.setFakeBoldText(erbanSysMsgComponent.isFontBold()); + } + }, + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + content.setText(spannableStringBuilder); + } + + operationLayout.setVisibility(View.GONE); + resultLayout.setVisibility(View.GONE); + flRejoin.setVisibility(View.GONE); + + if (sysMsgAttachment.getFirst() == CUSTOM_MSG_HEADER_COMMON_SYSTEM_MSG) { + switch (sysMsgAttachment.getSecond()) { + case CUSTOM_MSG_SUB_TYPE_COMMON_SYSTEM_MSG_TEXT: + break; + + case CUSTOM_MSG_SUB_TYPE_COMMON_SYSTEM_MSG_APPROVAL: + operationLayout.setVisibility(View.VISIBLE); + break; + } + + } else if (sysMsgAttachment.getFirst() == CUSTOM_MSG_HEAD_SHIFT_OUT) { + switch (sysMsgAttachment.getSecond()) { + case CUSTOM_MSG_SHIFT_OUT: + flRejoin.setVisibility(View.VISIBLE); + break; + } + } + + // bottom layout + switch (erbanSysMsgInfo.getState()) { + case ErbanSysMsgInfo.STATE_UNTREATED: + break; + + case ErbanSysMsgInfo.STATE_AGREE: + displayAgreedResult(); + break; + + case ErbanSysMsgInfo.STATE_REFUSED: + displayRejectedResult(); + break; + + case ErbanSysMsgInfo.STATE_OUT_DATE: + displayOutDateResult(); + break; + } + } + + public void setupView(TextView view, ErbanSysMsgComponent erbanSysMsgComponent) { + if (erbanSysMsgComponent != null) { + setupComponent(view, erbanSysMsgComponent.getContent(), erbanSysMsgComponent.getFontColor(), erbanSysMsgComponent.getFontSize(), + erbanSysMsgComponent.getRouterType(), erbanSysMsgComponent.getRouterValue()); + } + } + + public void setupComponent(TextView view, String text, String textColor, float fontSize, int routerType, int routerValue) { + view.setText(text); + view.setTextColor(Color.parseColor(textColor)); + view.setTextSize(fontSize); + if (routerType > 0) { + view.setOnClickListener(v -> RouterHandler.handle(context, routerType, String.valueOf(routerValue))); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.ll_container: + if (erbanSysMsgInfo.getRouterType() != 0) + RouterHandler.handle(context, erbanSysMsgInfo.getRouterType(), String.valueOf(erbanSysMsgInfo.getRouterValue())); + break; + + case R.id.btn_reject: + viewModel.requestUrl(erbanSysMsgInfo.getUrl(), 0, erbanSysMsgInfo.getParams()) + .subscribe((approveMsgInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + String tips = throwable.getMessage(); + if (!TextUtils.isEmpty(tips) && !RxHelper.ERROR_TIPS.equals(tips)) + SingleToastUtil.showToast(context, throwable.getMessage(), Toast.LENGTH_SHORT); + } else { + if (approveMsgInfo.getStatus() == ErbanSysMsgInfo.STATE_OUT_DATE) { + displayOutDateResult(); + }else if (approveMsgInfo.getStatus() == ErbanSysMsgInfo.STATE_REFUSED){ + displayRejectedResult(); + } + updateMessageToLocal(approveMsgInfo); + } + }); + break; + + case R.id.btn_agree: + viewModel.requestUrl(erbanSysMsgInfo.getUrl(), 1, erbanSysMsgInfo.getParams()) + .subscribe((approveMsgInfo, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + String tips = throwable.getMessage(); + if (!TextUtils.isEmpty(tips) && !RxHelper.ERROR_TIPS.equals(tips)) + SingleToastUtil.showToast(context, throwable.getMessage(), Toast.LENGTH_SHORT); + } else { + if (approveMsgInfo.getStatus() == ErbanSysMsgInfo.STATE_OUT_DATE) { + displayOutDateResult(); + }else if (approveMsgInfo.getStatus() == ErbanSysMsgInfo.STATE_AGREE){ + displayAgreedResult(); + } + updateMessageToLocal(approveMsgInfo); + } + }); + break; + + case R.id.tv_rejoin_mw: + if (erbanSysMsgInfo != null) { + Map map = erbanSysMsgInfo.getParams(); + if (map != null) { + String worldId = map.get("worldId"); + if (!TextUtils.isEmpty(worldId)) { + MiniWorldGuestPageActivity.start(context, worldId); + } + } + } + break; + } + } + + private void updateMessageToLocal(ApproveMsgInfo approveMsgInfo) { + erbanSysMsgInfo.setState(approveMsgInfo.getStatus()); + IMNetEaseManager.get().updateErbanSysMsgInfoMessage(message.getUuid(), erbanSysMsgInfo); + } + + private void displayAgreedResult() { + resultLayout.setVisibility(View.VISIBLE); + operationLayout.setVisibility(View.GONE); + approvalState.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_state_agreed, 0, 0, 0); + approvalState.setText(R.string.text_erban_sys_msg_state_agreed); + approvalState.setTextColor(ContextCompat.getColor(context, R.color.green_color_light)); + } + + private void displayRejectedResult() { + resultLayout.setVisibility(View.VISIBLE); + operationLayout.setVisibility(View.GONE); + approvalState.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_state_rejected, 0, 0, 0); + approvalState.setText(R.string.text_erban_sys_msg_state_rejected); + approvalState.setTextColor(ContextCompat.getColor(context, R.color.color_ff6565)); + } + + private void displayOutDateResult() { + resultLayout.setVisibility(View.VISIBLE); + operationLayout.setVisibility(View.GONE); + approvalState.setText(R.string.text_erban_sys_msg_state_out_date); + approvalState.setTextColor(ContextCompat.getColor(context, R.color.color_ff6565)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgVoiceViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgVoiceViewHolder.java new file mode 100644 index 000000000..45735ce4c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/chat/SysMsgVoiceViewHolder.java @@ -0,0 +1,70 @@ +package com.yizhuan.erban.ui.im.chat; + +import android.app.Activity; +import android.graphics.Color; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.widget.TextView; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.xchat_android_core.audio.bean.SysMsgVoiceInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.SysMsgVoiceAttachment; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; + +/** + * 声音瓶子,审核结果的系统消息 + */ +public class SysMsgVoiceViewHolder extends MsgViewHolderBase { + + private TextView tvContent, button; + + public SysMsgVoiceViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.layout_msg_view_holder_voice_sys_msg; + } + + @Override + protected void inflateContentView() { + tvContent = findViewById(R.id.tv_msg_view_holder_voice_content); + button = findViewById(R.id.tv_msg_view_holder_voice_button); + } + + @Override + protected void bindContentView() { + MsgAttachment attachment = message.getAttachment(); + if (attachment instanceof SysMsgVoiceAttachment) { + SysMsgVoiceAttachment voiceAttachment = (SysMsgVoiceAttachment) attachment; + SysMsgVoiceInfo voiceInfo = voiceAttachment.getVoiceInfo(); + if (voiceInfo.status == 1) {// 1 审核通过 + tvContent.setText(context.getString(R.string.voice_msg_view_holder_voice_content_pass_verification)); + button.setText("声音匹配"); + } else if (voiceInfo.status == 4) {// 4 审核不通过 + // 原因高亮 + String reason = TextUtils.isEmpty(voiceInfo.reason) ? "" : "“" + voiceInfo.reason + "”"; + SpannableStringBuilder reasonHighLight = new SpannableStringBuilder(reason); + reasonHighLight.setSpan(new ForegroundColorSpan(Color.parseColor("#FFB606")), 0, reason.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + // 拼接提示文案 + SpannableStringBuilder showContent = new SpannableStringBuilder(); + showContent.append("你录制的声音没有通过审核,理由为: ").append(reasonHighLight).append(" 快重新录制一条吧~"); + tvContent.setText(showContent); + button.setText("我的声音"); + } + button.setOnClickListener(view -> { + if (ActivityUtil.isValidContext(context)) { + ((Activity) context).finish(); + } + RouterHandler.handle(context, voiceInfo.routerType, voiceInfo.routerValue); + }); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/fragment/MessageFragment.java b/app/src/main/java/com/yizhuan/erban/ui/im/fragment/MessageFragment.java new file mode 100644 index 000000000..6bdccfa08 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/fragment/MessageFragment.java @@ -0,0 +1,738 @@ +package com.yizhuan.erban.ui.im.fragment; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.media.AudioManager; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.gson.Gson; +import com.netease.nim.uikit.api.UIKitOptions; +import com.netease.nim.uikit.api.model.main.CustomPushContentProvider; +import com.netease.nim.uikit.api.model.session.SessionCustomization; +import com.netease.nim.uikit.business.ait.AitManager; +import com.netease.nim.uikit.business.session.actions.BaseAction; +import com.netease.nim.uikit.business.session.constant.Extras; +import com.netease.nim.uikit.business.session.event.MessageEvent; +import com.netease.nim.uikit.business.session.module.Container; +import com.netease.nim.uikit.business.session.module.ModuleProxy; +import com.netease.nim.uikit.business.session.module.input.InputPanel; +import com.netease.nim.uikit.business.session.module.input.NimAudioChatEvent; +import com.netease.nim.uikit.business.session.module.input.NimImageActionEvent; +import com.netease.nim.uikit.common.fragment.TFragment; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.msg.MessageBuilder; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; +import com.netease.nimlib.sdk.msg.model.CustomNotification; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.MemberPushOption; +import com.netease.nimlib.sdk.msg.model.MessageReceipt; +import com.netease.nimlib.sdk.robot.model.NimRobotInfo; +import com.netease.nimlib.sdk.robot.model.RobotAttachment; +import com.netease.nimlib.sdk.robot.model.RobotMsgType; +import com.tbruyelle.rxpermissions2.RxPermissions; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.game.GameSelectDialog; +import com.yizhuan.erban.avroom.game.PlayGameActivity; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.ui.im.GreetPresenter; +import com.yizhuan.erban.ui.im.MessageListPanelEx; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.im.chat.MVHChatterBoxStart; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.im.GreetModel; +import com.yizhuan.xchat_android_core.im.chatterbox.ChatterBoxHelper; +import com.yizhuan.xchat_android_core.im.chatterbox.HideInputEvent; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImGameAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; +import com.yizhuan.xchat_android_core.im.game.GameResultEvent; +import com.yizhuan.xchat_android_core.im.game.ImGameInfo; +import com.yizhuan.xchat_android_core.im.game.ImGameMode; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.game.ChangeGameEvent; +import com.yizhuan.xchat_android_core.room.game.GameInfo; +import com.yizhuan.xchat_android_core.room.game.GameModel; +import com.yizhuan.xchat_android_core.room.game.GameResultInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +import static com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity.SECRETARY_UID; +import static com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity.SYSTEM_MESSAGE_UID; + +/** + * 聊天界面基类 + *

+ * Created by huangjun on 2015/2/1. + */ +public class MessageFragment extends TFragment implements ModuleProxy, MessageListPanelEx.OnMessageFilterListener { + + private View rootView; + + private SessionCustomization customization; + + protected static final String TAG = "MessageActivity"; + public static final String IN_ROOM = "inRoom"; + + // 聊天对象 + protected String sessionId; // p2p对方Account或者群id + + protected SessionTypeEnum sessionType; + + // modules + protected InputPanel inputPanel; + protected MessageListPanelEx messageListPanel; + + protected AitManager aitManager; + private Disposable disposable; + private Disposable subscribe; + private Disposable greetDisposable; + private boolean inRoom; + private FrameLayout flGame; + private RecyclerView recyclerView; + + private RxPermissions rxPermissions; + + private int limitLevel; + private int currentLevel; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + rxPermissions = new RxPermissions(this); + parseIntent(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + rootView = inflater.inflate(R.layout.nim_msg_fragment, container, false); + EventBus.getDefault().register(this); + initView(); + return rootView; + } + + private void initView() { + if (!ImGameMode.gameSwitch || MarketVerifyModel.get().isMarketChecking()) { + rootView.findViewById(R.id.iv_game).setVisibility(View.GONE); + } + + rootView.findViewById(R.id.iv_game).setOnClickListener(v -> { + inputPanel.hideInputMethod(); + inputPanel.collapse(true); + sponsorGame(); + }); + + //换个游戏 + subscribe = RxBus.get().toFlowable(ChangeGameEvent.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(changeUserEvent -> { + sponsorGame(); + }); + + String gameId = getArguments().getString("gameId"); + if (!TextUtils.isEmpty(gameId)) { + GameModel.get().getGameInfoById(gameId) + .subscribe(gameInfo -> startGame(gameInfo)); + } + + } + + private void initUserLikeGame() { + boolean aBoolean = getArguments().getBoolean(NimP2PMessageActivity.IS_BY_MATCH, false); + if (aBoolean) { + flGame = rootView.findViewById(R.id.fl_game); + flGame.setVisibility(View.VISIBLE); + recyclerView = rootView.findViewById(R.id.recycler_view); + rootView.findViewById(R.id.iv_close).setOnClickListener(v -> flGame.setVisibility(View.GONE)); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false)); + BaseAdapter adapter = new BaseAdapter<>(R.layout.item_im_user_like_game, BR.gameInfo); + recyclerView.setAdapter(adapter); + adapter.setOnItemClickListener((adapt, view, position) -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_favorite, "TA爱玩的游戏"); + + if (ImGameMode.get().getCutTime() == 0) { + startGame(adapter.getItem(position)); + } else { + SingleToastUtil.showToast(ImGameMode.gameFrequency + "秒内只能发起一次哦"); + } + }); + ImGameMode.get().getUserLikeGames(JavaUtil.str2long(sessionId)) + .subscribe(gameInfos -> adapter.setNewData(gameInfos)); + } + } + + private void sponsorGame() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game, "点击游戏面板"); + + GameSelectDialog dialog = new GameSelectDialog(getActivity(), false); + dialog.setOnSelectClick(gameInfo -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.private_chat_game_choice, "点击选择游戏"); + + if (ImGameMode.get().getCutTime() == 0) { + startGame(gameInfo); + } else { + SingleToastUtil.showToast(ImGameMode.gameFrequency + "秒内只能发起一次哦"); + } + }); + dialog.show(); + } + + private void startGame(GameInfo gameInfo) { + ImGameAttachment attachment = new ImGameAttachment(CustomAttachment.CUSTOM_MSG_IM_GAME, CustomAttachment.CUSTOM_MSG_IM_REQUST_GAME); + attachment.setImGameInfo(new ImGameInfo() + .setStartTime(System.currentTimeMillis()) + .setGameInfo(gameInfo) + .setTime(ImGameMode.TIME) + .setStatus(ImGameInfo.TIMEING)); + IMMessage message = MessageBuilder.createCustomMessage(sessionId, SessionTypeEnum.P2P, attachment); + sendMessage(message); + ImGameMode.get().startCountTime(); + messageListPanel.startCountTime(); + } + + /** + * ***************************** life cycle ******************************* + */ + + @Override + public void onPause() { + super.onPause(); + + NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, + SessionTypeEnum.None); + inputPanel.onPause(); + messageListPanel.onPause(); + } + + @Override + public void onResume() { + super.onResume(); + messageListPanel.onResume(); + NIMClient.getService(MsgService.class).setChattingAccount(sessionId, sessionType); + getActivity().setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); // 默认使用听筒播放 + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + messageListPanel.onDestroy(); + registerObservers(false); + if (disposable != null) { + disposable.dispose(); + } + if (subscribe != null) { + subscribe.dispose(); + } + if (greetDisposable != null) { + greetDisposable.dispose(); + } + if (inputPanel != null) { + inputPanel.onDestroy(); + } + if (aitManager != null) { + aitManager.reset(); + } + + if (messageListPanel.isGameing()) { + ImGameMode.get().resetTime(); + sendTipMessage("约战已取消", CustomAttachment.CUSTOM_MSG_IM_TIP_CANCEL); + } + } + + /** + * 发送提示信息 + * + * @param msg + */ + public void sendTipMessage(String msg, int second) { + ImTipAttachment attachment = new ImTipAttachment(CustomAttachment.CUSTOM_MSG_IM_TIP, second); + attachment.setMsg(msg); + IMMessage message = MessageBuilder.createCustomMessage(sessionId, SessionTypeEnum.P2P, attachment); + sendMessage(message); + } + + public boolean onBackPressed() { + if (inputPanel.collapse(true)) { + return true; + } + + if (messageListPanel.onBackPressed()) { + return true; + } + return false; + } + + public void refreshMessageList() { + messageListPanel.refreshMessageList(); + } + + private void parseIntent() { + sessionId = getArguments().getString(Extras.EXTRA_ACCOUNT); + ChatterBoxHelper.reset(); + ChatterBoxHelper.sessionId = sessionId; + sessionType = (SessionTypeEnum) getArguments().getSerializable(Extras.EXTRA_TYPE); + inRoom = getArguments().getBoolean(IN_ROOM, false); + ImGameMode.get().inRoom = inRoom; + if (inRoom || sessionId.equals(String.valueOf(SECRETARY_UID)) + || Objects.equals(sessionId, String.valueOf(SYSTEM_MESSAGE_UID))) { + rootView.findViewById(R.id.iv_game).setVisibility(View.GONE); + } + initUserLikeGame(); + + IMMessage anchor = (IMMessage) getArguments().getSerializable(Extras.EXTRA_ANCHOR); + + customization = (SessionCustomization) getArguments().getSerializable(Extras.EXTRA_CUSTOMIZATION); + Container container = new Container(getActivity(), sessionId, sessionType, this); + + if (messageListPanel == null) { + messageListPanel = new MessageListPanelEx(container, rootView, anchor, false, false); + } else { + messageListPanel.reload(container, anchor); + } + + if (inputPanel == null) { + inputPanel = new InputPanel(container, rootView, getActionList()); + inputPanel.setCustomization(customization); + inputPanel.setLimitLevel(limitLevel, currentLevel); + } else { + inputPanel.reload(container, customization); + } + + initAitManager(); + + inputPanel.switchRobotMode(NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(sessionId) != null); + + registerObservers(true); + + if (customization != null) { + messageListPanel.setChattingBackground(customization.backgroundUri, customization.backgroundColor); + } + + disposable = RxBus.get().toFlowable(GameResultEvent.class) + .subscribe(gameResultEvent -> GameModel.get().getGameInfoById(gameResultEvent.resultBean.getGameId()). + subscribe(gameInfo -> { + if (gameResultEvent.resultBean.getResultType().equals(GameResultInfo.DRAW)) { + String msg = "【" + gameInfo.getGameName() + "】" + + gameResultEvent.resultBean.getUsers().get(0).getName() + + "对战" + + gameResultEvent.resultBean.getUsers().get(1).getName() + + "为平局"; + sendTipMessage(msg, CustomAttachment.CUSTOM_MSG_IM_TIP_RESULT); + } else { + String msg = "【" + gameInfo.getGameName() + "】" + + gameResultEvent.resultBean.getWinners().get(0).getName() + + "战胜" + + gameResultEvent.resultBean.getFailers().get(0).getName(); + sendTipMessage(msg, CustomAttachment.CUSTOM_MSG_IM_TIP_RESULT); + } + + })); + + // 首页进来的直接打开话匣子游戏 + boolean startWithChatterBox = getArguments().getBoolean(Extras.EXTRA_CHATTER_BOX, false); + MVHChatterBoxStart.isFromHome = startWithChatterBox; + if (startWithChatterBox) { +// if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_CHATTER_BOX)) { +// rootView.post(() -> { +// TuTuGuideHelper helper = new TuTuGuideHelper(getActivity()); +// helper.createHiGuide(() -> helper.createDiceOverLayer()); +// TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_CHATTER_BOX); +// }); +// } +// ChatterBoxHelper.topicBoxCanSend(); + ChatterBoxHelper.sendInitTips(sessionId); + } + + boolean accost = getArguments().getBoolean(Extras.EXTRA_ACCOST, false); + if (accost) { + long toUid; + try { + toUid = Long.valueOf(sessionId); + + } catch (Exception ex) { + ex.printStackTrace(); + toUid = 0; + } + if (toUid > 0) { + GreetPresenter greetPresenter = new GreetPresenter(sessionId); + if (greetPresenter.isCanSendGreet()) { + greetDisposable = greetPresenter.greetMsgGetOne(AuthModel.get().getCurrentUid(), toUid) + .subscribe(new Consumer() { + @Override + public void accept(String s) throws Exception { + if (!TextUtils.isEmpty(s)) { + sendMessage(MessageBuilder.createTextMessage(container.account, + container.sessionType, s)); + } + } + }); + } + + } + } + + } + + private void initAitManager() { + UIKitOptions options = NimUIKitImpl.getOptions(); + if (options.aitEnable) { + aitManager = new AitManager(getContext(), options.aitTeamMember && sessionType == SessionTypeEnum.Team ? sessionId : null, options.aitIMRobot); + inputPanel.addAitTextWatcher(aitManager); + aitManager.setTextChangeListener(inputPanel); + } + } + + /** + * ************************* 消息收发 ********************************** + */ + // 是否允许发送消息 + protected boolean isAllowSendMessage(final IMMessage message) { + return true; + } + + /** + * ****************** 观察者 ********************** + */ + + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeReceiveMessage(incomingMessageObserver, register); + service.observeCustomNotification(customObserver, register); + // 已读回执监听 + if (NimUIKitImpl.getOptions().shouldHandleReceipt) { + service.observeMessageReceipt(messageReceiptObserver, register); + } + + } + + /** + * 消息接收观察者 + */ + Observer> incomingMessageObserver = new Observer>() { + @Override + public void onEvent(List messages) { + if (messages == null || messages.isEmpty()) { + return; + } + + messageListPanel.onIncomingMessage(filterLoadedMessage(messages)); + sendMsgReceipt(); // 发送已读回执 + } + }; + /** + * 自定义系统通知观察者,这里用来接收游戏状态更改的回执 + */ + Observer customObserver = new Observer() { + @Override + public void onEvent(CustomNotification messages) { + if (messages != null) { + try { + JSONObject object = JSON.parseObject(messages.getContent()); + ImGameInfo matchInfo = new Gson().fromJson(object.toJSONString(), ImGameInfo.class); + if (matchInfo == null || TextUtils.isEmpty(matchInfo.getGameUrl())) return; + messageListPanel.receiveCustomNotification(matchInfo); + PlayGameActivity.start(getActivity(), matchInfo.getGameUrl(), AuthModel.get().getCurrentUid(), matchInfo.getUuId()); + } catch (Exception e) { + } + } + } + }; + + private Observer> messageReceiptObserver = new Observer>() { + @Override + public void onEvent(List messageReceipts) { + receiveReceipt(); + } + }; + + + /** + * ********************** implements ModuleProxy ********************* + */ + @Override + public boolean sendMessage(IMMessage message) { + if (!isAllowSendMessage(message)) { + return false; + } + + appendTeamMemberPush(message); + message = changeToRobotMsg(message); + final IMMessage msg = message; + appendPushConfig(message); + // send message to server and save to db + IMMessage finalMessage = message; + NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { + } + + @Override + public void onFailed(int code) { + sendFailWithBlackList(code, msg); + } + + @Override + public void onException(Throwable exception) { + + } + }); + + messageListPanel.onMsgSend(message); + + if (aitManager != null) { + aitManager.reset(); + } + return true; + } + + // 被对方拉入黑名单后,发消息失败的交互处理 + private void sendFailWithBlackList(int code, IMMessage msg) { + if (code == ResponseCode.RES_IN_BLACK_LIST) { + // 如果被对方拉入黑名单,发送的消息前不显示重发红点 + msg.setStatus(MsgStatusEnum.success); + NIMClient.getService(MsgService.class).updateIMMessageStatus(msg); + messageListPanel.refreshMessageList(); + // 同时,本地插入被对方拒收的tip消息 + IMMessage tip = MessageBuilder.createTipMessage(msg.getSessionId(), msg.getSessionType()); + tip.setContent(BasicConfig.INSTANCE.getAppContext().getString(R.string.black_list_send_tip)); + tip.setStatus(MsgStatusEnum.success); + CustomMessageConfig config = new CustomMessageConfig(); + config.enableUnreadCount = false; + tip.setConfig(config); + NIMClient.getService(MsgService.class).saveMessageToLocal(tip, true); + } + } + + private void appendTeamMemberPush(IMMessage message) { + if (aitManager == null) { + return; + } + if (sessionType == SessionTypeEnum.Team) { + List pushList = aitManager.getAitTeamMember(); + if (pushList == null || pushList.isEmpty()) { + return; + } + MemberPushOption memberPushOption = new MemberPushOption(); + memberPushOption.setForcePush(true); + memberPushOption.setForcePushContent(message.getContent()); + memberPushOption.setForcePushList(pushList); + message.setMemberPushOption(memberPushOption); + } + } + + private IMMessage changeToRobotMsg(IMMessage message) { + if (aitManager == null) { + return message; + } + if (message.getMsgType() == MsgTypeEnum.robot) { + return message; + } + if (isChatWithRobot()) { + if (message.getMsgType() == MsgTypeEnum.text && message.getContent() != null) { + String content = message.getContent().equals("") ? " " : message.getContent(); + message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), message.getSessionId(), content, RobotMsgType.TEXT, content, null, null); + } + } else { + String robotAccount = aitManager.getAitRobot(); + if (TextUtils.isEmpty(robotAccount)) { + return message; + } + String text = message.getContent(); + String content = aitManager.removeRobotAitString(text, robotAccount); + content = content.equals("") ? " " : content; + message = MessageBuilder.createRobotMessage(message.getSessionId(), message.getSessionType(), robotAccount, text, RobotMsgType.TEXT, content, null, null); + + } + return message; + } + + private boolean isChatWithRobot() { + return NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(sessionId) != null; + } + + private void appendPushConfig(IMMessage message) { + CustomPushContentProvider customConfig = NimUIKitImpl.getCustomPushContentProvider(); + if (customConfig != null) { + String content = customConfig.getPushContent(message); + Map payload = customConfig.getPushPayload(message); + if (!TextUtils.isEmpty(content)) { + message.setPushContent(content); + } + if (payload != null) { + message.setPushPayload(payload); + } + } + } + + @Override + public void onInputPanelExpand() { + messageListPanel.scrollToBottom(); + } + + @Override + public void shouldCollapseInputPanel() { + inputPanel.collapse(false); + } + + @Override + public boolean isLongClickEnabled() { + return !inputPanel.isRecording(); + } + + @Override + public void onItemFooterClick(IMMessage message) { + if (aitManager == null) { + return; + } + if (messageListPanel.isSessionMode()) { + RobotAttachment attachment = (RobotAttachment) message.getAttachment(); + NimRobotInfo robot = NimUIKitImpl.getRobotInfoProvider().getRobotByAccount(attachment.getFromRobotAccount()); + aitManager.insertAitRobot(robot.getAccount(), robot.getName(), inputPanel.getEditSelectionStart()); + } + } + + @Override + public List filterLoadedMessage(List messageList) { + return filterMessage(messageList); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (aitManager != null) { + aitManager.onActivityResult(requestCode, resultCode, data); + } + inputPanel.onActivityResult(requestCode, resultCode, data); + messageListPanel.onActivityResult(requestCode, resultCode, data); + } + + // 操作面板集合 + protected List getActionList() { + List actions = new ArrayList<>(); +// actions.add(new ImageAction()); +// actions.add(new VideoAction()); +// actions.add(new LocationAction()); + + if (customization != null && customization.actions != null) { + actions.addAll(customization.actions); + } + return actions; + } + + /** + * 发送已读回执 + */ + private void sendMsgReceipt() { + messageListPanel.sendReceipt(); + } + + /** + * 收到已读回执 + */ + public void receiveReceipt() { + messageListPanel.receiveReceipt(); + } + + /** + * 重新加载 输入面板 + * + * @param sessionCustomization + */ + public void reloadInputPanel(SessionCustomization sessionCustomization) { + this.customization = sessionCustomization; + Container container = new Container(getActivity(), sessionId, sessionType, this); + inputPanel.reload(container, customization); + inputPanel.reloadActions(sessionCustomization.actions); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onHideInput(HideInputEvent event) { + if (inputPanel != null) { + inputPanel.hideInputMethod(); + inputPanel.collapse(true); + } + } + + @SuppressLint("CheckResult") + public Observable checkPermission(String... mPerms) { + return rxPermissions.request(mPerms); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressLint("CheckResult") + public void onNimAudioChatEvent(NimAudioChatEvent event) { + checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO) + .subscribe(result -> { + if (result) { + event.getSuccess().accept(result); + } else { + SingleToastUtil.showToast(getString(R.string.ask_again)); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + @SuppressLint("CheckResult") + public void onNimImageActionEvent(NimImageActionEvent event) { + checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA) + .subscribe(result -> { + if (result) { + event.getSuccess().accept(result); + } else { + SingleToastUtil.showToast(getString(R.string.ask_again)); + } + }); + } + + public void setLimitLevel(int limitLevel) { + this.limitLevel = limitLevel; + } + + public void setCurrentLevel(int currentLevel) { + this.currentLevel = currentLevel; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/friend/ActFriendList.java b/app/src/main/java/com/yizhuan/erban/ui/im/friend/ActFriendList.java new file mode 100644 index 000000000..b988b1b86 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/friend/ActFriendList.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.ui.im.friend; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.home.fragment.ContactsListFragment; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; + +@CreatePresenter(BaseMvpPresenter.class) +public class ActFriendList extends BaseMvpActivity> implements IMvpBaseView{ + + public static void start(Context context) { + Intent starter = new Intent(context, ActFriendList.class); + context.startActivity(starter); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.act_friend_list); + initTitleBar(getString(R.string.message_contact)); + Fragment fragment = ContactsListFragment.newInstance(); + FragmentManager manager = getSupportFragmentManager(); + manager.beginTransaction().add(R.id.fl_friend_list, fragment).commit(); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListAdapter.java new file mode 100644 index 000000000..762c4b898 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListAdapter.java @@ -0,0 +1,148 @@ +package com.yizhuan.erban.ui.im.friend; + +import android.app.Activity; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.tutu.room_chat.activity.NimRoomP2PMessageActivity; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + * @author chenran + * @date 2017/10/3 + */ + +public class FriendListAdapter extends BaseQuickAdapter { + + private Activity context; + private int type = AbstractSelectFriendAction.TYPE_NORMAL; + + public FriendListAdapter(Activity context) { + super(R.layout.list_item_friend_new); + this.context = context; + } + + private OnItemClickListener onItemClickListener; + + public void setType(int type) { + this.type = type; + } + + public interface OnItemClickListener { + void sendListener(UserInfo attentionInfo); + } + + public void setRylListener(OnItemClickListener onClickListener) { + onItemClickListener = onClickListener; + } + + @Override + protected void convert(BaseViewHolder helper, UserInfo item) { + if (item == null) return; + + helper.setText(R.id.tv_userName, item.getNick()) + .setText(R.id.tv_user_desc, item.getUserDesc() != null ? + item.getUserDesc() + : helper.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) +// .setVisible(R.id.view_line, helper.getLayoutPosition() != getItemCount() - 1) +// .setVisible(R.id.tv_find_him, attentionInfo.getUserInRoom() != null && type == AbstractSelectFriendAction.TYPE_NORMAL) +// .setVisible(R.id.tv_send, isSend) + ; + + NobleAvatarView nobleAvatarView = helper.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(55, 75, 15); + nobleAvatarView.setData(item.getAvatar(), item.getNobleUsers()); + nobleAvatarView.setOnClickListener(v -> { + if (type == AbstractSelectFriendAction.TYPE_NORMAL) { + UserInfoActivity.Companion.start(context, item.getUid()); + } + }); + + AppCompatImageView ivGender = helper.getView(R.id.iv_gender); + if (item.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + // 官字 icon + helper.getView(R.id.iv_user_official).setVisibility(item.isOfficial() ? View.VISIBLE : View.GONE); + + AppCompatImageView ivNobleLevel = helper.getView(R.id.iv_noble_level); + if (item.getNobleUsers() != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(item.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + AppCompatImageView ivUserLevel = helper.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = helper.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (item.getUserLevelVo() != null && !TextUtils.isEmpty(item.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, item.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + + helper.getView(R.id.container).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + switch (type) { + case AbstractSelectFriendAction.TYPE_NORMAL: + String account = String.valueOf(item.getUid()); + NimP2PMessageActivity.start(context, account); + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + if (onItemClickListener != null) { + onItemClickListener.sendListener(item); + } + break; + + case AbstractSelectFriendAction.ROOM_MSG: + NimRoomP2PMessageActivity.start(context, String.valueOf(item.getUid())); + break; + } + } + }); + + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + case AbstractSelectFriendAction.TYPE_WEAR: + helper.getView(R.id.tv_send).setVisibility(View.VISIBLE); + helper.getView(R.id.tv_send).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (onItemClickListener != null) { + onItemClickListener.sendListener(item); + } + } + }); + break; + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragment.java b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragment.java new file mode 100644 index 000000000..0965ee35d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragment.java @@ -0,0 +1,252 @@ +package com.yizhuan.erban.ui.im.friend; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.tutu.room_chat.activity.NimRoomP2PMessageActivity; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RelationShipEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; + +import static com.yizhuan.erban.friend.action.AbstractSelectFriendAction.ROOM_MSG; +import static com.yizhuan.xchat_android_core.Constants.IS_SEND; +import static com.yizhuan.xchat_android_core.web.bean.WebJsBeanInfo.SHARE; + +/** + * @description: 好友列表界面 + * @author: hewenhao + * @date: 2018/9/6 14:57 + */ +public class FriendListFragment extends BaseFragment { + + private FriendListAdapter adapter = null; + private SelectFriendActivity selectFriendActivity; + private int type = AbstractSelectFriendAction.TYPE_NORMAL; + private SwipeRefreshLayout mSwipeRefresh; + private RecyclerView mRecyclerView; + private List infoList; + private boolean send; + + public static FriendListFragment newInstance(boolean b, int type) { + FriendListFragment friendListFragment = new FriendListFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean(IS_SEND, b); + bundle.putInt(AbstractSelectFriendAction.KEY_TYPE, type); + friendListFragment.setArguments(bundle); + return friendListFragment; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof SelectFriendActivity) { + selectFriendActivity = (SelectFriendActivity) activity; + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + mSwipeRefresh = mView.findViewById(R.id.swipe_refresh); + mRecyclerView = mView.findViewById(R.id.recycler_view); + } + + @Override + public void onSetListener() { + } + + @Override + public void initiate() { + mSwipeRefresh.setOnRefreshListener(() -> { + loadFriends(); + }); + + adapter = new FriendListAdapter(getActivity()); + if (getArguments() != null) { + send = getArguments().getBoolean(IS_SEND); + adapter.setType(getArguments().getInt(AbstractSelectFriendAction.KEY_TYPE, + AbstractSelectFriendAction.TYPE_NORMAL)); + } + adapter.setRylListener((attentionInfo)->{ + if (selectFriendActivity != null && attentionInfo != null) { + selectFriendActivity.showSureDialog(String.valueOf(attentionInfo.getUid()), attentionInfo.getAvatar(), attentionInfo.getNick()); + } + }); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + mRecyclerView.setAdapter(adapter); + + loadFriends(); + + Disposable d = IMNetEaseManager.get().getRelationShipEventObservable().subscribe(this::onGetRelationShipEvent); + mCompositeDisposable.add(d); + } + + private void onGetRelationShipEvent(RelationShipEvent event) { + if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) { + onFriendListUpdate(event.accounts); + } + } + + private void loadFriends() { + mSwipeRefresh.setRefreshing(true); + onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_fans_list; + } + + private void onFriendListUpdate(List accounts) { + if (ListUtils.isListEmpty(accounts)) { + mSwipeRefresh.setRefreshing(false); + if (adapter != null) { + infoList = new ArrayList<>(); + adapter.setNewData(infoList); + } + showNoData(R.drawable.icon_common_failure, getString(R.string.no_frenids_text)); + return; + } + + UserModel.get().loadUserInfoByUids(accounts) + .compose(bindToLifecycle()) + .map(new Function, LinkedHashMap>() { + @Override + public LinkedHashMap apply(List userInfos) throws Exception { + LinkedHashMap userInfoLinkedHashMap = new LinkedHashMap<>(); + for (UserInfo userInfo : userInfos) { + userInfoLinkedHashMap.put(userInfo.getUid(), userInfo); + } + return userInfoLinkedHashMap; + } + }) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(LinkedHashMap longUserInfoLinkedHashMap) { + onRequestUserInfoMap(longUserInfoLinkedHashMap); + mSwipeRefresh.setRefreshing(false); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + showNetworkErr(); + mSwipeRefresh.setRefreshing(false); + } + }); + } + + private void setData(List userInfos) { + if (userInfos != null && !userInfos.isEmpty()) { + infoList = userInfos; + hideStatus(); + adapter.setNewData(userInfos); + } else { + infoList = new ArrayList<>(); + adapter.setNewData(infoList); + showNoData(R.drawable.icon_common_failure, getString(R.string.no_frenids_text)); + } + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.frg_no_data_large_iv_transparent, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + mRecyclerView.postDelayed(() -> { + if (getActivity() == null || getActivity().isFinishing()) { + Logger.i("界面已销毁"); + return; + } + FriendListFragment.this.onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()); + }, 250); + } + + public void onRequestUserInfoMap(LinkedHashMap userInfoLinkedHashMap) { + hideStatus(); + List userInfos = null; + if (adapter != null) { + userInfos = adapter.getData(); + } + int size = userInfoLinkedHashMap.size(); + if (size > 0) { + userInfos = new ArrayList(size); + Set> entries = userInfoLinkedHashMap.entrySet(); + for (Map.Entry entry : entries) { + userInfos.add(entry.getValue()); + } + } + setData(userInfos); + } + + @Override + public void onReloadData() { + super.onReloadData(); + hideStatus(); + showLoading(); + loadFriends(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragmentKotlin.kt b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragmentKotlin.kt new file mode 100644 index 000000000..cc8cd7a27 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/friend/FriendListFragmentKotlin.kt @@ -0,0 +1,157 @@ +//package com.yizhuan.erban.ui.im.friend +// +//import android.app.Activity +//import android.os.Bundle +//import android.support.v7.widget.LinearLayoutManager +//import com.yizhuan.erban.R +//import com.yizhuan.erban.base.BaseFragment +//import com.yizhuan.erban.friend.action.AbstractSelectFriendAction +//import com.yizhuan.erban.friend.view.SelectFriendActivity +//import com.yizhuan.xchat_android_core.Constants.IS_SEND +//import com.yizhuan.xchat_android_core.im.friend.IMFriendModel +//import com.yizhuan.xchat_android_core.manager.IMNetEaseManager +//import com.yizhuan.xchat_android_core.manager.RelationShipEvent +//import com.yizhuan.xchat_android_core.user.UserModel +//import com.yizhuan.xchat_android_core.user.bean.UserInfo +//import com.yizhuan.xchat_android_library.utils.ListUtils +//import kotlinx.android.synthetic.main.fragment_fans_list.* +//import org.greenrobot.eventbus.EventBus +//import org.greenrobot.eventbus.Subscribe +//import org.greenrobot.eventbus.ThreadMode +//import java.util.* +// +///** +// * 好友列表界面 +// * +// * @author chenran +// * @date 2017/9/18 +// */ +//class FriendListFragmentKotlin : BaseFragment() { +// private var adapter: PublicChatHallFriendListAdapter? = null +// private var selectFriendActivity: SelectFriendActivity? = null +// private var type: Int = AbstractSelectFriendAction.TYPE_NORMAL +// +// companion object { +// fun newInstance(boolean: Boolean, type: Int): FriendListFragmentKotlin { +// val friendListFragment = FriendListFragmentKotlin() +// var bundle = Bundle() +// bundle.putBoolean(IS_SEND, boolean) +// bundle.putInt(AbstractSelectFriendAction.KEY_TYPE, type) +// friendListFragment.setArguments(bundle) +// return friendListFragment +// } +// } +// +// override fun onAttach(activity: Activity?) { +// super.onAttach(activity) +// if (activity is SelectFriendActivity) { +// selectFriendActivity = activity +// } +// } +// +// override fun onCreate(savedInstanceState: Bundle?) { +// super.onCreate(savedInstanceState) +// EventBus.getDefault().register(this) +// } +// +// override fun onDestroy() { +// super.onDestroy() +// EventBus.getDefault().unregister(this) +// } +// +// override fun onFindViews() { +// } +// +// override fun onSetListener() { +// +// } +// +// override fun initiate() { +// +// +// swipe_refresh!!.setOnRefreshListener { +// swipe_refresh!!.isRefreshing = true +// loadFriends() +// swipe_refresh!!.isRefreshing = false +// } +// +// adapter = PublicChatHallFriendListAdapter(activity) +// if (arguments != null) { +// adapter!!.setType(arguments?.getInt(AbstractSelectFriendAction.KEY_TYPE, +// AbstractSelectFriendAction.TYPE_NORMAL)!!) +// } +// adapter!!.setRylListener(object : PublicChatHallFriendListAdapter.OnItemClickListener { +// override fun sendListener(attentionInfo: UserInfo?) { +// if (selectFriendActivity != null) { +// selectFriendActivity!!.showSureDialog(attentionInfo!!.uid.toString(), attentionInfo!!.avatar, attentionInfo!!.nick) +// } +// } +// +// }) +// recycler_view!!.layoutManager = LinearLayoutManager(activity) +// recycler_view!!.adapter = adapter +// +// loadFriends() +// +// val d = IMNetEaseManager.get().relationShipEventObservable.subscribe(this::onGetRelationShipEvent) +// mCompositeDisposable.add(d) +// +// } +// +// private fun onGetRelationShipEvent(event: RelationShipEvent) { +// if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) { +// onFriendListUpdate(event.accounts) +// } +// } +// +// private fun loadFriends() { +// onFriendListUpdate(IMFriendModel.get().myFriendsAccounts) +// } +// +// override fun getRootLayoutId(): Int { +// return R.layout.fragment_fans_list +// } +// +// //@CoreEvent(coreClientClass = IIMFriendCoreClient::class) +// private fun onFriendListUpdate(accounts: List?) { +// if (ListUtils.isListEmpty(accounts)) { +// showNoData(getString(R.string.no_frenids_text)) +// return +// } +// val ids = ArrayList(accounts!!.size) +// accounts.mapTo(destination = ids) { java.lang.Long.valueOf(it) } +// val mapByUidList = UserModel.get().getCacheThenServerUserInfoMapByUidList(ids) +// onRequestUserInfoMap(mapByUidList) +// } +// +// private fun setData(userInfos: List?) { +// if (userInfos != null && userInfos.isNotEmpty()) { +// hideStatus() +// adapter!!.friendList = userInfos +// adapter!!.notifyDataSetChanged() +// } else { +// showNoData(getString(R.string.no_frenids_text)) +// } +// } +// +// @Subscribe(threadMode = ThreadMode.MAIN) +// fun onCurrentUserInfoUpdate(userInfo: UserInfo) { +// recycler_view!!.postDelayed({ +// onFriendListUpdate(IMFriendModel.get().myFriendsAccounts) +// }, 250) +// } +// +// @Subscribe(threadMode = ThreadMode.MAIN) +// fun onRequestUserInfoMap(userInfoLinkedHashMap: LinkedHashMap?) { +// hideStatus() +// var userInfos: MutableList? = if (adapter == null) null else adapter!!.friendList +// if (userInfoLinkedHashMap != null && userInfoLinkedHashMap.size > 0) { +// userInfos = ArrayList(userInfoLinkedHashMap.size) +// val entries = userInfoLinkedHashMap.entries +// for ((_, value) in entries) { +// userInfos.add(value) +// } +// } +// setData(userInfos) +// } +//} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentContactsFragment.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentContactsFragment.java new file mode 100644 index 000000000..b5410eaad --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentContactsFragment.java @@ -0,0 +1,841 @@ +package com.yizhuan.erban.ui.im.recent; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.api.model.contact.ContactChangedObserver; +import com.netease.nim.uikit.api.model.main.OnlineStateChangeObserver; +import com.netease.nim.uikit.api.model.team.TeamDataChangedObserver; +import com.netease.nim.uikit.api.model.team.TeamMemberDataChangedObserver; +import com.netease.nim.uikit.api.model.user.UserInfoObserver; +import com.netease.nim.uikit.business.recent.RecentContactsCallback; +import com.netease.nim.uikit.business.recent.TeamMemberAitHelper; +import com.netease.nim.uikit.business.uinfo.UserInfoHelper; +import com.netease.nim.uikit.common.badger.Badger; +import com.netease.nim.uikit.common.fragment.TFragment; +import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog; +import com.netease.nim.uikit.common.ui.drop.DropCover; +import com.netease.nim.uikit.common.ui.drop.DropManager; +import com.netease.nim.uikit.common.ui.imageview.HeadImageView; +import com.netease.nim.uikit.common.ui.recyclerview.listener.SimpleClickListener; +import com.netease.nim.uikit.impl.NimUIKitImpl; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.Observer; +import com.netease.nimlib.sdk.RequestCallback; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.MsgServiceObserve; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.model.Team; +import com.netease.nimlib.sdk.team.model.TeamMember; +import com.qiyukf.unicorn.api.Unicorn; +import com.qiyukf.unicorn.api.msg.MsgTypeEnum; +import com.qiyukf.unicorn.api.msg.UnicornMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.im.recent.adapter.RecentContactAdapter; +import com.yizhuan.xchat_android_core.customer_server.CustomerServerModel; +import com.yizhuan.xchat_android_core.customer_server.event.CustomerServerMsgEvent; +import com.yizhuan.xchat_android_core.manager.IMMessageManager; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import me.everything.android.ui.overscroll.OverScrollDecoratorHelper; + +import static com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog.onSeparateItemClickListener; + +/** + * 最近联系人列表(会话列表) + *

+ * Created by huangjun on 2015/2/1. + */ +public class RecentContactsFragment extends TFragment { + + // 置顶功能可直接使用,也可作为思路,供开发者充分利用RecentContact的tag字段 + public static final long RECENT_TAG_STICKY = 1; // 联系人置顶tag + + // view + private RecyclerView recyclerView; + + private View emptyBg; + + private TextView emptyHint; + + // data + private List items; + + private Map cached; // 暂缓刷上列表的数据(未读数红点拖拽动画运行时用) + + private RecentContactAdapter adapter; + + private boolean msgLoaded = false; + + private RecentContactsCallback callback; + + private UserInfoObserver userInfoObserver; + + private boolean isInRoom; + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + findViews(); + initMessageList(); + requestMessages(true); + registerObservers(true); + registerDropCompletedListener(true); + registerOnlineStateChangeListener(true); + + initKFView(); + + EventBus.getDefault().register(this); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + isInRoom = getArguments().getBoolean("isInRoom", false); + } + } + + public static RecentContactsFragment newInstance(boolean isInRoom) { + Bundle args = new Bundle(); + args.putBoolean("isInRoom", isInRoom); + RecentContactsFragment fragment = new RecentContactsFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_recent_contacts, container, false); + } + + private void notifyDataSetChanged() { + adapter.notifyDataSetChanged(); + boolean empty = items.isEmpty() && msgLoaded && !isHaveKFHeadView(); + emptyBg.setVisibility(empty ? View.VISIBLE : View.GONE); + emptyHint.setHint("你还没有聊天记录哦!\n快去和好友聊天吧!"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + registerObservers(false); + registerDropCompletedListener(false); + registerOnlineStateChangeListener(false); + DropManager.getInstance().setDropListener(null); + } + + /** + * 查找页面控件 + */ + private void findViews() { + recyclerView = findView(R.id.recycler_view); + emptyBg = findView(R.id.emptyBg); + emptyHint = findView(R.id.message_list_empty_hint); + } + + /** + * 初始化消息列表 + */ + private void initMessageList() { + items = new ArrayList<>(); + cached = new HashMap<>(3); + + // adapter + adapter = new RecentContactAdapter(recyclerView, items); + initCallBack(); + adapter.setCallback(callback); + + // recyclerView + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerView.addOnItemTouchListener(touchListener); + // ios style + OverScrollDecoratorHelper.setUpOverScroll(recyclerView, OverScrollDecoratorHelper.ORIENTATION_VERTICAL); + + // drop listener + DropManager.getInstance().setDropListener(new DropManager.IDropListener() { + @Override + public void onDropBegin() { + touchListener.setShouldDetectGesture(false); + } + + @Override + public void onDropEnd() { + touchListener.setShouldDetectGesture(true); + } + }); + } + + private void initCallBack() { + if (callback != null) { + return; + } + callback = new RecentContactsCallback() { + @Override + public void onRecentContactsLoaded() { + + } + + @Override + public void onUnreadCountChange(int unreadCount) { + + } + + @Override + public void onItemClick(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.Team) { + NimUIKit.startTeamSession(getActivity(), recent.getContactId()); + } else if (recent.getSessionType() == SessionTypeEnum.P2P) { + NimUIKit.startP2PSession(getActivity(), recent.getContactId()); + } + } + + @Override + public String getDigestOfAttachment(RecentContact recentContact, MsgAttachment attachment) { + return null; + } + + @Override + public String getDigestOfTipMsg(RecentContact recent) { + return null; + } + }; + } + + private SimpleClickListener touchListener = new SimpleClickListener() { + @Override + public void onItemClick(RecentContactAdapter adapter, View view, int position) { + if (callback != null) { + RecentContact recent = adapter.getItem(position); + callback.onItemClick(recent); + } + } + + @Override + public void onItemLongClick(RecentContactAdapter adapter, View view, int position) { + showLongClickMenu(adapter.getItem(position), position); + } + + @Override + public void onItemChildClick(RecentContactAdapter adapter, View view, int position) { + + } + + @Override + public void onItemChildLongClick(RecentContactAdapter adapter, View view, int position) { + + } + }; + + OnlineStateChangeObserver onlineStateChangeObserver = new OnlineStateChangeObserver() { + @Override + public void onlineStateChange(Set accounts) { + notifyDataSetChanged(); + } + }; + + private void registerOnlineStateChangeListener(boolean register) { + if (!NimUIKitImpl.enableOnlineState()) { + return; + } + NimUIKitImpl.getOnlineStateChangeObservable().registerOnlineStateChangeListeners(onlineStateChangeObserver, register); + } + + private void showLongClickMenu(final RecentContact recent, final int position) { + CustomAlertDialog alertDialog = new CustomAlertDialog(getActivity()); + alertDialog.setTitle(UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType())); + String title = getString(R.string.main_msg_list_delete_chatting); + alertDialog.addItem(title, new onSeparateItemClickListener() { + @Override + public void onClick() { + // 删除会话,删除后,消息历史被一起删除 + NIMClient.getService(MsgService.class).deleteRecentContact2(recent.getContactId(), recent.getSessionType()); + NIMClient.getService(MsgService.class).clearChattingHistory(recent.getContactId(), recent.getSessionType()); + } + }); + + title = (isTagSet(recent, RECENT_TAG_STICKY) ? getString(R.string.main_msg_list_clear_sticky_on_top) : getString(R.string.main_msg_list_sticky_on_top)); + alertDialog.addItem(title, new onSeparateItemClickListener() { + @Override + public void onClick() { + if (isTagSet(recent, RECENT_TAG_STICKY)) { + removeTag(recent, RECENT_TAG_STICKY); + } else { + addTag(recent, RECENT_TAG_STICKY); + } + NIMClient.getService(MsgService.class).updateRecent(recent); + + refreshMessages(false); + } + }); + + alertDialog.addItem("删除该聊天(仅服务器)", new onSeparateItemClickListener() { + @Override + public void onClick() { + NIMClient.getService(MsgService.class) + .deleteRoamingRecentContact(recent.getContactId(), recent.getSessionType()) + .setCallback(new RequestCallback() { + @Override + public void onSuccess(Void param) { +// Toast.makeText(getActivity(), "delete success", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("delete success"); + } + + @Override + public void onFailed(int code) { + SingleToastUtil.showToastShort("delete failed, code:" + code); +// Toast.makeText(getActivity(), "delete failed, code:" + code, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onException(Throwable exception) { + + } + }); + } + }); + alertDialog.show(); + } + + private void addTag(RecentContact recent, long tag) { + tag = recent.getTag() | tag; + recent.setTag(tag); + } + + private void removeTag(RecentContact recent, long tag) { + tag = recent.getTag() & ~tag; + recent.setTag(tag); + } + + private boolean isTagSet(RecentContact recent, long tag) { + return (recent.getTag() & tag) == tag; + } + + private List loadedRecents; + + public void requestMessages(boolean delay) { + getHandler().postDelayed(new Runnable() { + + @Override + public void run() { + // 查询最近联系人列表数据 + NIMClient.getService(MsgService.class).queryRecentContacts().setCallback(new RequestCallbackWrapper>() { + + @Override + public void onResult(int code, List recents, Throwable exception) { + if (code != ResponseCode.RES_SUCCESS || recents == null) { + return; + } + loadedRecents = recents; + // 初次加载,更新离线的消息中是否有@我的消息 + for (RecentContact loadedRecent : loadedRecents) { + if (loadedRecent.getSessionType() == SessionTypeEnum.Team) { + updateOfflineContactAited(loadedRecent); + } + } + // 此处如果是界面刚初始化,为了防止界面卡顿,可先在后台把需要显示的用户资料和群组资料在后台加载好,然后再刷新界面 + // + msgLoaded = true; + if (isAdded()) { + onRecentContactsLoaded(); + } + } + }); + } + }, delay ? 250 : 0); + } + + private void onRecentContactsLoaded() { + items.clear(); + if (loadedRecents != null) { + items.addAll(loadedRecents); + loadedRecents = null; + } + refreshMessages(true); + + if (callback != null) { + callback.onRecentContactsLoaded(); + } + } + + private void refreshMessages(boolean unreadChanged) { + sortRecentContacts(items); + notifyDataSetChanged(); + + if (unreadChanged) { + + // 方式一:累加每个最近联系人的未读(快) + + int unreadNum = 0; + for (RecentContact r : items) { + unreadNum += r.getUnreadCount(); + } + + // 方式二:直接从SDK读取(相对慢) + //int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount(); + + if (callback != null) { + callback.onUnreadCountChange(unreadNum); + } + + Badger.updateBadgerCount(unreadNum); + } + } + + /** + * **************************** 排序 *********************************** + */ + private void sortRecentContacts(List list) { + if (list.size() == 0) { + return; + } + Collections.sort(list, comp); + } + + private static Comparator comp = new Comparator() { + + @Override + public int compare(RecentContact o1, RecentContact o2) { + // 先比较置顶tag + long sticky = (o1.getTag() & RECENT_TAG_STICKY) - (o2.getTag() & RECENT_TAG_STICKY); + if (sticky != 0) { + return sticky > 0 ? -1 : 1; + } else { + long time = o1.getTime() - o2.getTime(); + return time == 0 ? 0 : (time > 0 ? -1 : 1); + } + } + }; + + /** + * ********************** 收消息,处理状态变化 ************************ + */ + private void registerObservers(boolean register) { + MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); + service.observeReceiveMessage(messageReceiverObserver, register); + service.observeRecentContact(messageObserver, register); + service.observeMsgStatus(statusObserver, register); + service.observeRecentContactDeleted(deleteObserver, register); + + registerTeamUpdateObserver(register); + registerTeamMemberUpdateObserver(register); + NimUIKit.getContactChangedObservable().registerObserver(friendDataChangedObserver, register); + if (register) { + registerUserInfoObserver(); + } else { + unregisterUserInfoObserver(); + } + } + + /** + * 注册群信息&群成员更新监听 + */ + private void registerTeamUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamDataChangedObserver(teamDataChangedObserver, register); + } + + private void registerTeamMemberUpdateObserver(boolean register) { + NimUIKit.getTeamChangedObservable().registerTeamMemberDataChangedObserver(teamMemberDataChangedObserver, register); + } + + private void registerDropCompletedListener(boolean register) { + if (register) { + DropManager.getInstance().addDropCompletedListener(dropCompletedListener); + } else { + DropManager.getInstance().removeDropCompletedListener(dropCompletedListener); + } + } + + // 暂存消息,当RecentContact 监听回来时使用,结束后清掉 + private Map> cacheMessages = new HashMap<>(); + + //监听在线消息中是否有@我 + private Observer> messageReceiverObserver = new Observer>() { + @Override + public void onEvent(List imMessages) { + if (imMessages != null) { + for (IMMessage imMessage : imMessages) { + if (!TeamMemberAitHelper.isAitMessage(imMessage)) { + continue; + } + Set cacheMessageSet = cacheMessages.get(imMessage.getSessionId()); + if (cacheMessageSet == null) { + cacheMessageSet = new HashSet<>(); + cacheMessages.put(imMessage.getSessionId(), cacheMessageSet); + } + cacheMessageSet.add(imMessage); + } + } + } + }; + + Observer> messageObserver = new Observer>() { + @Override + public void onEvent(List recentContacts) { + if (!DropManager.getInstance().isTouchable()) { + // 正在拖拽红点,缓存数据 + for (RecentContact r : recentContacts) { + cached.put(r.getContactId(), r); + } + + return; + } + + onRecentContactChanged(recentContacts); + } + }; + + private void onRecentContactChanged(List recentContacts) { + int index; + for (RecentContact r : recentContacts) { + index = -1; + for (int i = 0; i < items.size(); i++) { + if (r.getContactId().equals(items.get(i).getContactId()) + && r.getSessionType() == (items.get(i).getSessionType())) { + index = i; + break; + } + } + + if (index >= 0) { + items.remove(index); + } + + items.add(r); + if (r.getSessionType() == SessionTypeEnum.Team && cacheMessages.get(r.getContactId()) != null) { + TeamMemberAitHelper.setRecentContactAited(r, cacheMessages.get(r.getContactId())); + } + } + + cacheMessages.clear(); + + refreshMessages(true); + } + + DropCover.IDropCompletedListener dropCompletedListener = new DropCover.IDropCompletedListener() { + @Override + public void onCompleted(Object id, boolean explosive) { + if (cached != null && !cached.isEmpty()) { + // 红点爆裂,已经要清除未读,不需要再刷cached + if (explosive) { + if (id instanceof RecentContact) { + RecentContact r = (RecentContact) id; + cached.remove(r.getContactId()); + } else if (id instanceof String && ((String) id).contentEquals("0")) { + cached.clear(); + } + } + + // 刷cached + if (!cached.isEmpty()) { + List recentContacts = new ArrayList<>(cached.size()); + recentContacts.addAll(cached.values()); + cached.clear(); + + onRecentContactChanged(recentContacts); + } + } + if (id instanceof RecentContact) { + RecentContact recentContact = (RecentContact) id; + NIMClient.getService(MsgService.class).clearUnreadCount(recentContact.getContactId(), recentContact.getSessionType()); + } + } + }; + + Observer statusObserver = new Observer() { + @Override + public void onEvent(IMMessage message) { + int index = getItemIndex(message.getUuid()); + if (index >= 0 && index < items.size()) { + RecentContact item = items.get(index); + item.setMsgStatus(message.getStatus()); + refreshViewHolderByIndex(index); + } + } + }; + + Observer deleteObserver = new Observer() { + @Override + public void onEvent(RecentContact recentContact) { + if (recentContact != null) { + for (RecentContact item : items) { + if (TextUtils.equals(item.getContactId(), recentContact.getContactId()) + && item.getSessionType() == recentContact.getSessionType()) { + items.remove(item); + refreshMessages(true); + break; + } + } + } else { + items.clear(); + refreshMessages(true); + } + } + }; + + TeamDataChangedObserver teamDataChangedObserver = new TeamDataChangedObserver() { + + @Override + public void onUpdateTeams(List teams) { + adapter.notifyDataSetChanged(); + } + + @Override + public void onRemoveTeam(Team team) { + + } + }; + + TeamMemberDataChangedObserver teamMemberDataChangedObserver = new TeamMemberDataChangedObserver() { + @Override + public void onUpdateTeamMember(List members) { + adapter.notifyDataSetChanged(); + } + + @Override + public void onRemoveTeamMember(List member) { + + } + }; + + private int getItemIndex(String uuid) { + for (int i = 0; i < items.size(); i++) { + RecentContact item = items.get(i); + if (TextUtils.equals(item.getRecentMessageId(), uuid)) { + return i; + } + } + + return -1; + } + + protected void refreshViewHolderByIndex(final int index) { + if (recyclerView == null) return; + recyclerView.post(() -> adapter.notifyItemChanged(index)); +// if (getActivity() == null) return; +// getActivity().runOnUiThread(new Runnable() { +// +// @Override +// public void run() { +// adapter.notifyItemChanged(index); +// } +// }); + } + + public void setCallback(RecentContactsCallback callback) { + this.callback = callback; + } + + private void registerUserInfoObserver() { + if (userInfoObserver == null) { + userInfoObserver = new UserInfoObserver() { + @Override + public void onUserInfoChanged(List accounts) { + refreshMessages(false); + } + }; + } + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, true); + } + + private void unregisterUserInfoObserver() { + if (userInfoObserver != null) { + NimUIKit.getUserInfoObservable().registerObserver(userInfoObserver, false); + } + } + + ContactChangedObserver friendDataChangedObserver = new ContactChangedObserver() { + @Override + public void onAddedOrUpdatedFriends(List accounts) { + refreshMessages(false); + } + + @Override + public void onDeletedFriends(List accounts) { + refreshMessages(false); + } + + @Override + public void onAddUserToBlackList(List account) { + refreshMessages(false); + } + + @Override + public void onRemoveUserFromBlackList(List account) { + refreshMessages(false); + } + }; + + private void updateOfflineContactAited(final RecentContact recentContact) { + if (recentContact == null || recentContact.getSessionType() != SessionTypeEnum.Team + || recentContact.getUnreadCount() <= 0) { + return; + } + + // 锚点 + List uuid = new ArrayList<>(1); + uuid.add(recentContact.getRecentMessageId()); + + List messages = NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuid); + + if (messages == null || messages.size() < 1) { + return; + } + final IMMessage anchor = messages.get(0); + + // 查未读消息 + NIMClient.getService(MsgService.class).queryMessageListEx(anchor, QueryDirectionEnum.QUERY_OLD, + recentContact.getUnreadCount() - 1, false).setCallback(new RequestCallbackWrapper>() { + + @Override + public void onResult(int code, List result, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS && result != null) { + result.add(0, anchor); + Set messages = null; + // 过滤存在的@我的消息 + for (IMMessage msg : result) { + if (TeamMemberAitHelper.isAitMessage(msg)) { + if (messages == null) { + messages = new HashSet<>(); + } + messages.add(msg); + } + } + + // 更新并展示 + if (messages != null) { + TeamMemberAitHelper.setRecentContactAited(recentContact, messages); + notifyDataSetChanged(); + } + } + } + }); + + } + + private View kfView; + private HeadImageView ivKfAvatar; + private TextView tvLastMsg; + private TextView tvMsgCount; + + private void initKFView() { + kfView = LayoutInflater.from(getContext()).inflate(R.layout.header_customer_server, null, false); + ivKfAvatar = kfView.findViewById(R.id.iv_kf_avatar); + GlideApp.with(getContext()) + .load(CustomerServerModel.AVATAR_URL) + .dontAnimate() + .into(ivKfAvatar); + tvLastMsg = kfView.findViewById(R.id.tv_last_msg); + tvMsgCount = kfView.findViewById(R.id.tv_msg_count); + kfView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CustomerServerModel.getInstance().contactCustomerServer("", "聊天", null).subscribe(); + } + }); + + kfView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + CustomAlertDialog alertDialog = new CustomAlertDialog(getActivity()); + alertDialog.setTitle("官方客服"); + String title = getString(R.string.main_msg_list_delete_chatting); + alertDialog.addItem(title, new onSeparateItemClickListener() { + @Override + public void onClick() { + Unicorn.clearCache(); + removeKFView(); + } + }); + alertDialog.show(); + + return true; + } + }); + onCustomerServerMsgEvent(new CustomerServerMsgEvent(Unicorn.getUnreadCount())); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCustomerServerMsgEvent(CustomerServerMsgEvent event) { + UnicornMessage message = Unicorn.queryLastMessage(); + if (message != null) { + if (message.getMsgType().equals(MsgTypeEnum.text)) { + tvLastMsg.setText(message.getContent()); + } else if (message.getMsgType().equals(MsgTypeEnum.image)) { + tvLastMsg.setText("[图片]"); + } else if (message.getMsgType().equals(MsgTypeEnum.audio)) { + tvLastMsg.setText("[语音]"); + } else if (message.getMsgType().equals(MsgTypeEnum.video)) { + tvLastMsg.setText("[视频]"); + } else { + tvLastMsg.setText("[收到一条消息]"); + } + if (!isHaveKFHeadView()) { + addKFView(); + } + emptyBg.setVisibility(View.GONE); + } + if (event.unreadCount > 0) { + tvMsgCount.setVisibility(View.VISIBLE); + tvMsgCount.setText(event.unreadCount + ""); + + } else { + tvMsgCount.setVisibility(View.INVISIBLE); + tvMsgCount.setText(""); + } + } + + private boolean isHaveKFHeadView() { + if (adapter.getHeaderLayout() == null) { + return false; + } + for (int i = 0; i < adapter.getHeaderLayout().getChildCount(); i++) { + if (adapter.getHeaderLayout().getChildAt(i) == kfView) { + return true; + } + } + return false; + } + + public void addKFView() { + adapter.addHeaderView(kfView); + adapter.notifyDataSetChanged(); + } + + public void removeKFView() { + adapter.removeHeaderView(kfView); + adapter.notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentListFragment.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentListFragment.java new file mode 100644 index 000000000..6443e2648 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/RecentListFragment.java @@ -0,0 +1,526 @@ +package com.yizhuan.erban.ui.im.recent; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.OrientationHelper; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.google.gson.Gson; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.business.recent.RecentContactsCallback; +import com.netease.nimlib.sdk.msg.attachment.AudioAttachment; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.model.Team; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.home.activity.UserMatchActivity; +import com.yizhuan.erban.miniworld.activity.MWTeamRoomMessageAct; +import com.yizhuan.erban.miniworld.activity.MiniWorldTeamMessageActivity; +import com.yizhuan.erban.module_hall.im.NimHelper; +import com.yizhuan.erban.module_hall.team.activity.HallTeamMessageActivity; +import com.yizhuan.erban.team.view.NimTeamMessageActivity; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.im.recent.adapter.AttentionInRoomAdapter; +import com.yizhuan.erban.ui.relation.AttentionListActivity; +import com.yizhuan.tutu.mentoring_relationship.adapter.GrabApprenticesAdapter; +import com.yizhuan.tutu.room_chat.activity.NimHallTeamRoomMessageActivity; +import com.yizhuan.tutu.room_chat.activity.NimRoomP2PMessageActivity; +import com.yizhuan.tutu.room_chat.activity.NimTeamRoomMessageActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.community.im.WorldDynamicAttachment; +import com.yizhuan.xchat_android_core.im.RefreshInRoomListEvent; +import com.yizhuan.xchat_android_core.im.custom.bean.AssistantAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CarveUpGoldThirdLevelAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyTipsAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NobleAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.NoticeAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RedPacketAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.SysMsgVoiceAttachment; +import com.yizhuan.xchat_android_core.luckymoney.LuckyMoneyInfo; +import com.yizhuan.xchat_android_core.mentoring_relationship.bean.GrabApprenticesInfo; +import com.yizhuan.xchat_android_core.mentoring_relationship.event.GrabApprenticesDataEvent; +import com.yizhuan.xchat_android_core.mentoring_relationship.model.MentoringRelationshipModel; +import com.yizhuan.xchat_android_core.public_chat_hall.attachment.AitMeAttachment; +import com.yizhuan.xchat_android_core.public_chat_hall.bean.AitMeInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionItem; +import com.yizhuan.xchat_android_core.user.event.LoadLoginUserInfoEvent; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.functions.BiConsumer; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_HEAD_CAR; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MESS_HEAD_NOBLE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_ASSISTANT_MSG; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_COMMON_SYSTEM_MSG; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_GIFT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_LOTTERY; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_LUCKY_MONEY; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_NOTICE; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_PACKET; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_HEADER_TYPE_SHARE_IN_APP; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_IM_GAME; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_MODULE_HALL; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_PUBLIC_CHAT_HALL; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SHARE_FAMILY; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SHARE_ROOM; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SHARE_TEAM; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SHIFT_OUT; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_PUBLIC_CHAT_HALL_AIT_ME; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_RECEIVE_LUCKY_MONEY; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_SUB_TYPE_SEND_LUCKY_MONEY; + +/** + * 最近聊天列表 + * + * @author chenran + * @date 2017/9/18 + */ +public class RecentListFragment extends BaseFragment { + + private static final String TAG = "RecentListFragment"; + + private RecyclerView grabApprenticesRecyclerView; + private GrabApprenticesAdapter grabApprenticesAdapter; + + private RecentContactsFragment recentContactsFragment; + private boolean isInRoom; + + private RecyclerView rvAttentionOnline; + private AttentionInRoomAdapter mAttentionInRoomAdapter; + + public static RecentListFragment newInstance(boolean isInRoom) { + + Bundle args = new Bundle(); + args.putBoolean("isInRoom", isInRoom); + RecentListFragment fragment = new RecentListFragment(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + if (getArguments() != null) { + isInRoom = getArguments().getBoolean("isInRoom", false); + } + + } + + @Override + public void onFindViews() { + + // 一起玩、关注用户在房间内列表 + rvAttentionOnline = mView.findViewById(R.id.rv_attention_online); + mAttentionInRoomAdapter = new AttentionInRoomAdapter(); + rvAttentionOnline.setAdapter(mAttentionInRoomAdapter); + rvAttentionOnline.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); + mAttentionInRoomAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List attentionItems = adapter.getData(); + if (attentionItems.size() > position) { + AttentionItem attentionItem = attentionItems.get(position); + switch (attentionItem.getItemType()) { + case AttentionItem.TYPE_PLAY_TOGETHER: + if (mContext != null) { + mContext.startActivity(new Intent(mContext, UserMatchActivity.class)); + } + break; + + case AttentionItem.TYPE_ATTENTION: + try { + AttentionInfo attentionInfo = (AttentionInfo) attentionItem.getData(); + if (attentionInfo != null && attentionInfo.getUserInRoom() != null && mContext != null) { + AVRoomActivity.start(mContext, attentionInfo.getUserInRoom().getUid()); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + break; + + case AttentionItem.TYPE_ATTENTION_MORE: + if (mContext != null) { + AttentionListActivity.start(mContext); + } + break; + } + } + } + }); + + recentContactsFragment = RecentContactsFragment.newInstance(isInRoom); + FragmentManager fragmentManager = getChildFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.recent_container, recentContactsFragment).commitAllowingStateLoss(); + grabApprenticesRecyclerView = mView.findViewById(R.id.rv_grab_apprentices); + grabApprenticesRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), + OrientationHelper.HORIZONTAL, false)); + grabApprenticesAdapter = new GrabApprenticesAdapter(); + grabApprenticesRecyclerView.setAdapter(grabApprenticesAdapter); + grabApprenticesAdapter.setOnItemChildClickListener((adapter, view, position) -> { + GrabApprenticesInfo item = grabApprenticesAdapter.getItem(position); + switch (view.getId()) { + case R.id.btn_grab_apprentice: + grabApprentice(item); + break; + } + }); + } + + @SuppressLint("CheckResult") + @Override + public void onStart() { + super.onStart(); + } + + @SuppressLint("CheckResult") + private void grabApprentice(GrabApprenticesInfo item) { + if (item == null) return; + List grabApprenticesInfoList = + MentoringRelationshipModel.get().getGrabApprenticesInfoList(); + if (grabApprenticesInfoList == null) return; + // 删除 item + grabApprenticesInfoList.remove(item); + // 点击抢徒弟按钮,打点 + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.NEWS_ROB, + "抢徒弟"); + MentoringRelationshipModel.get() + .grabApprentices(item.getUid()) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe((s, throwable) -> { + if (throwable == null) { + NimP2PMessageActivity.start(getContext(), s); + // 抢徒弟成功,打点 + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.NEWS_ROB_SUCCESS, + "抢徒成功"); + } else { + toast(throwable.getMessage()); + } + }); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + recentContactsFragment.setCallback(new RecentContactsCallback() { + @Override + public void onRecentContactsLoaded() { + + } + + @Override + public void onUnreadCountChange(int unreadCount) { + + } + + @Override + public void onItemClick(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.Team) { + //判断群类型 + NimHelper.getTeamById(RecentListFragment.this, recent.getContactId()) + .flatMap(team -> { + int type = 0; + String ext = team.getExtServer(); + if (!TextUtils.isEmpty(ext)) { + TeamExt teamExt = new Gson().fromJson(ext, TeamExt.class); + if (teamExt != null) { + type = teamExt.getType(); + } + } + return Single.just(type); + }) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(Integer type) { + if (type == null) { + return; + } + if (type == 0) {//家族群 + if (isInRoom) { + NimTeamRoomMessageActivity.start(getActivity(), recent.getContactId()); + } else { + NimTeamMessageActivity.start(getActivity(), recent.getContactId()); + } + } else if (type == 1) {//厅群 + if (isInRoom) { + NimHallTeamRoomMessageActivity.start(mContext, recent.getContactId()); + } else { + HallTeamMessageActivity.start(mContext, recent.getContactId()); + } + } else if (type == 2){ + + if (isInRoom) { + MWTeamRoomMessageAct.start(mContext, recent.getContactId()); + } else { + Team t = NimUIKit.getTeamProvider().getTeamById(recent.getContactId()); + if (t != null && t.isMyTeam()) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_PAGE_ENTER_GROUP_CHAT, + "进入群聊:消息页"); + MiniWorldTeamMessageActivity.start(mContext, recent.getContactId(), true); + } else { + MiniWorldTeamMessageActivity.start(mContext, recent.getContactId(), false); + } + + } + + } else { + toast("该版本不支持,请下载最新版本"); + } + } + }); + } else if (recent.getSessionType() == SessionTypeEnum.P2P) { + if (isInRoom) { + NimRoomP2PMessageActivity.start(mContext, recent.getContactId()); + } else { + NimP2PMessageActivity.start(mContext, recent.getContactId()); + } + } + } + + @Override + public String getDigestOfAttachment(RecentContact recent, MsgAttachment attachment) { + if (attachment instanceof CustomAttachment) { + CustomAttachment customAttachment = (CustomAttachment) attachment; + if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_OPEN_ROOM_NOTI) { + return "您关注的TA上线啦,快去围观吧~~~"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_GIFT) { + return "[礼物]"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_NOTICE) { + NoticeAttachment noticeAttachment = (NoticeAttachment) attachment; + return noticeAttachment.getTitle(); + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_PACKET) { + RedPacketAttachment redPacketAttachment = (RedPacketAttachment) attachment; + return "您收到一个" + redPacketAttachment.getRedPacketInfo().getPacketName() + "红包哦!"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_LOTTERY) { + return "恭喜您,获得抽奖机会"; + } else if (customAttachment.getFirst() == CUSTOM_MESS_HEAD_NOBLE) { + NobleAttachment nobleAttachment = (NobleAttachment) attachment; + return "提示:" + nobleAttachment.msg; + } else if (customAttachment.getFirst() == CUSTOM_MESS_HEAD_CAR) { + return ((CarAttachment) attachment).msg; + } else if (customAttachment.getFirst() == CUSTOM_MSG_ASSISTANT_MSG) { + return ((AssistantAttachment) attachment).title; + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_SHARE_IN_APP) { + switch (customAttachment.getSecond()) { + case CUSTOM_MSG_SHARE_ROOM: + return "[分享房间]"; + + case CUSTOM_MSG_SHARE_FAMILY: + return "[分享家族]"; + + case CUSTOM_MSG_SHARE_TEAM: + return "[分享群组]"; + + default: + return "[您收到一条分享消息]"; + + } + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_TYPE_LUCKY_MONEY) { + switch (customAttachment.getSecond()) { + case CUSTOM_MSG_SUB_TYPE_SEND_LUCKY_MONEY: + return "[您收到了一个群红包]"; + + case CUSTOM_MSG_SUB_TYPE_RECEIVE_LUCKY_MONEY: + LuckyMoneyTipsAttachment luckyMoneyTipsAttachment = (LuckyMoneyTipsAttachment) attachment; + String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + LuckyMoneyInfo luckyMoneyInfo = luckyMoneyTipsAttachment.getLuckyMoneyInfo(); + String senderUid = String.valueOf(luckyMoneyInfo.getSenderUid()); + String receiverUid = luckyMoneyInfo.getReceiveUid(); + if (Objects.equals(currentUid, senderUid)) { + return "[" + luckyMoneyInfo.getReceiveNick() + "领取了你的红包]"; + } else if (Objects.equals(currentUid, receiverUid)) { + return "[你领取了" + luckyMoneyInfo.getNick() + "的红包]"; + } else { + return "[" + luckyMoneyInfo.getReceiveNick() + "领取了" + luckyMoneyInfo.getNick() + "的红包]"; + } + } + } else if (customAttachment.getFirst() == CUSTOM_MSG_HEADER_COMMON_SYSTEM_MSG + || customAttachment.getFirst() == CUSTOM_MSG_SHIFT_OUT) { + return "[您收到一条系统消息]"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_PUBLIC_CHAT_HALL) { + switch (customAttachment.getSecond()) { + case CUSTOM_MSG_SUB_PUBLIC_CHAT_HALL_AIT_ME: + AitMeAttachment aitMeAttachment = (AitMeAttachment) customAttachment; + AitMeInfo aitMeInfo = aitMeAttachment.getAitMeInfo(); + return aitMeInfo.getContent(); + } + return "[您收到一条公聊大厅相关消息]"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_MODULE_HALL) { + return "[您收到一条厅消息]"; + } else if (customAttachment.getFirst() == CUSTOM_MSG_IM_GAME) { + return "[您收到一条游戏消息]"; + } else if (customAttachment.getFirst() == CustomAttachment.CUSTOM_MSG_SIGN_IN + && customAttachment.getSecond() == CustomAttachment.CUSTOM_MSG_SUB_JUMP_SIGN_IN_ACTIVITY) { + return "[签到提醒]"; + } else if (customAttachment instanceof CarveUpGoldThirdLevelAttachment) { + return "[签到瓜分百万]"; + } else if (customAttachment instanceof SysMsgVoiceAttachment) { + return "[声音瓶子审核消息]"; + } else if (WorldDynamicAttachment.isShareMsg(customAttachment)) { + return "[分享一条动态]"; + } + } else if (attachment instanceof AudioAttachment) { + return "[语音]"; + } + return null; + } + + @Override + public String getDigestOfTipMsg(RecentContact recent) { + return null; + } + }); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_recent_list; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoadLoginUserInfoEvent event) { + recentContactsFragment.requestMessages(true); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onReceiveGrabApprenticeDataEvent(GrabApprenticesDataEvent event) { + Log.e("main", "onReceiveGrabApprenticeDataEvent: "); + List grabApprenticesInfoList = MentoringRelationshipModel.get().getGrabApprenticesInfoList(); + if (!ListUtils.isListEmpty(grabApprenticesInfoList)) { + grabApprenticesAdapter.setNewData(grabApprenticesInfoList); + grabApprenticesRecyclerView.setVisibility(View.VISIBLE); + } else { + grabApprenticesRecyclerView.setVisibility(View.GONE); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void refreshInRoomList(RefreshInRoomListEvent event) { + loadAttentionList(); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (isVisibleToUser) { // viewpager切换刷新 关注用户在房间内 数据 + loadAttentionList(); + } + } + + /** + * 返回当前页,实时刷新数据 + * 1、其他activity返回msgfragment; + * 2、首页底部tab点击切换返回msgfragment; + * 3、msgfragment viewpager 左右切换 + */ + @SuppressLint("CheckResult") + private void loadAttentionList() { + AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + 1, + 100) + .flatMap(attentionInfos -> { + if (attentionInfos != null) { + Iterator iterator = attentionInfos.iterator(); + while (iterator.hasNext()) { + if (iterator.next().getUserInRoom() == null) { + iterator.remove(); + } + } + } + return Single.just(attentionInfos); + }) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List attentionInfos, Throwable throwable) throws Exception { + + if (attentionInfos != null && attentionInfos.size() > 0) { + + List attentionItems = new ArrayList<>(); + AttentionItem attentionItem = new AttentionItem(AttentionItem.TYPE_PLAY_TOGETHER, null); + attentionItems.add(attentionItem); + + int count = 0; + for (AttentionInfo attentionInfo : attentionInfos) { + if (count >= 20) { // 最多展示20个 + break; + } + attentionItem = new AttentionItem(AttentionItem.TYPE_ATTENTION, attentionInfo); + attentionItems.add(attentionItem); + count++; + } + + // 超过20,提供进入关注列表页入口 + if (attentionInfos.size() > 20) { + attentionItem = new AttentionItem(AttentionItem.TYPE_ATTENTION_MORE, null); + attentionItems.add(attentionItem); + } + + if (rvAttentionOnline != null) { + rvAttentionOnline.setVisibility(View.VISIBLE); + } + + if (mAttentionInRoomAdapter != null) { + mAttentionInRoomAdapter.setNewData(attentionItems); + } + + } else { + if (rvAttentionOnline != null) { + rvAttentionOnline.setVisibility(View.GONE); + } + } + + } + }); + + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/TeamExt.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/TeamExt.java new file mode 100644 index 000000000..ac750f479 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/TeamExt.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.ui.im.recent; + +import java.io.Serializable; + +/** + * 群的拓展信息 + * Created by lvzebiao on 2019/1/14. + */ + +public class TeamExt implements Serializable { + + private int type; + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/AttentionInRoomAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/AttentionInRoomAdapter.java new file mode 100644 index 000000000..8236c0c67 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/AttentionInRoomAdapter.java @@ -0,0 +1,60 @@ +package com.yizhuan.erban.ui.im.recent.adapter; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionItem; + +import java.util.ArrayList; + +public class AttentionInRoomAdapter extends BaseMultiItemQuickAdapter { + + public AttentionInRoomAdapter() { + super(new ArrayList<>()); + addItemType(AttentionItem.TYPE_PLAY_TOGETHER, R.layout.item_play_together); + addItemType(AttentionItem.TYPE_ATTENTION, R.layout.item_attention_in_room); + addItemType(AttentionItem.TYPE_ATTENTION_MORE, R.layout.item_attention_more); + } + + @Override + protected void convert(BaseViewHolder helper, AttentionItem item) { + + if (item == null) { + return; + } + + switch (item.getItemType()) { + case AttentionItem.TYPE_PLAY_TOGETHER: + helper.addOnClickListener(R.id.ll_play_together); + break; + + case AttentionItem.TYPE_ATTENTION: + helper.addOnClickListener(R.id.ll_attention_in_room); + setAttentionInRoom(helper, item); + break; + + case AttentionItem.TYPE_ATTENTION_MORE: + helper.addOnClickListener(R.id.cl_attention_more); + break; + } + + } + + private void setAttentionInRoom(BaseViewHolder helper, AttentionItem item) { + try { + AttentionInfo attentionInfo = (AttentionInfo) item.getData(); + if (attentionInfo != null) { + helper.setText(R.id.tv_name_attention_in_room, attentionInfo.nick); + + CircleImageView imageView = helper.getView(R.id.civ_attention_in_room); + ImageLoadUtilsV2.loadImage(imageView, attentionInfo.avatar); + } + + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/RecentContactAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/RecentContactAdapter.java new file mode 100644 index 000000000..9e75456d7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/adapter/RecentContactAdapter.java @@ -0,0 +1,52 @@ +package com.yizhuan.erban.ui.im.recent.adapter; + +import android.support.v7.widget.RecyclerView; + +import com.netease.nim.uikit.business.recent.RecentContactsCallback; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemQuickAdapter; +import com.netease.nim.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.recent.holder.CommonRecentViewHolder; +import com.yizhuan.erban.ui.im.recent.holder.TeamRecentViewHolder; + +import java.util.List; + +/** + * @author huangjun + * @date 2016/12/11 + */ +public class RecentContactAdapter extends BaseMultiItemQuickAdapter { + + interface ViewType { + int VIEW_TYPE_COMMON = 1; + int VIEW_TYPE_TEAM = 2; + } + + private RecentContactsCallback callback; + + public RecentContactAdapter(RecyclerView recyclerView, List data) { + super(recyclerView, data); + addItemType(ViewType.VIEW_TYPE_COMMON, R.layout.nim_recent_contact_list_item_new, CommonRecentViewHolder.class); + addItemType(ViewType.VIEW_TYPE_TEAM, R.layout.nim_recent_contact_team_list_item, TeamRecentViewHolder.class); + } + + @Override + protected int getViewType(RecentContact item) { + return item.getSessionType() == SessionTypeEnum.Team ? ViewType.VIEW_TYPE_TEAM : ViewType.VIEW_TYPE_COMMON; + } + + @Override + protected String getItemKey(RecentContact item) { + return String.valueOf(item.getSessionType().getValue()) + "_" + item.getContactId(); + } + + public RecentContactsCallback getCallback() { + return callback; + } + + public void setCallback(RecentContactsCallback callback) { + this.callback = callback; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/CommonRecentViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/CommonRecentViewHolder.java new file mode 100644 index 000000000..201a755ba --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/CommonRecentViewHolder.java @@ -0,0 +1,224 @@ +package com.yizhuan.erban.ui.im.recent.holder; + +import android.annotation.SuppressLint; +import android.graphics.drawable.AnimationDrawable; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; + +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleMessageTouchListener; +import com.netease.nim.uikit.common.ui.draggablebubbles.MessageBubbleView; +import com.netease.nim.uikit.common.ui.drop.DropFake; +import com.netease.nim.uikit.common.ui.drop.DropManager; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.netease.nim.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.yizhuan.erban.BuildConfig; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + + +import static android.view.View.GONE; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; + +/** + * @author Administrator + */ +public class CommonRecentViewHolder extends RecentViewHolder { + + public CommonRecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + protected String getContent(RecentContact recent) { + return descOfMsg(recent); + } + + @Override + protected String getOnlineStateContent(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.P2P && NimUIKit.enableOnlineState()) { + return NimUIKit.getOnlineStateContentProvider().getSimpleDisplay(recent.getContactId()); + } else { + return super.getOnlineStateContent(recent); + } + } + + @Override + public void inflate(BaseViewHolder holder, final RecentContact recent) { + this.imgHead = holder.getView(R.id.img_head); + this.tvNickname = holder.getView(R.id.tv_nickname); + this.tvMessage = holder.getView(R.id.tv_message); + this.tvUnread = holder.getView(R.id.unread_number_tip); + this.imgUnreadExplosion = holder.getView(R.id.unread_number_explosion); + this.tvDatetime = holder.getView(R.id.tv_date_time); + this.imgMsgStatus = holder.getView(R.id.img_msg_status); + this.tvOnlineState = holder.getView(R.id.tv_online_state); + this.ivCharmLevel = holder.getView(R.id.iv_charm_level); + this.ivUserGender = holder.getView(R.id.iv_user_gender); + mIvNobleHeadWear = holder.getView(R.id.noble_head_wear); + mIvNobleLevel = holder.getView(R.id.iv_noble_level); + mIvNobleBadge = holder.getView(R.id.iv_user_badge); +// topLine = holder.getView(R.id.top_line); +// ivUserOfficialView = holder.getView(R.id.iv_user_official); + +// holder.addOnClickListener(R.id.unread_number_tip); + + MessageBubbleView.attach(this.tvUnread, new BubbleMessageTouchListener.BubbleDisappearListener() { + @Override + public void dragStart(View view) { + DropManager.getInstance().setTouchable(false); + } + + @Override + public void dismiss(View view) { + DropManager.getInstance().setCurrentId(recent); + DropManager.getInstance().down(tvUnread, tvUnread.getText().toString()); + DropManager.getInstance().dropCompleted(recent); + } + + @Override + public void dragFinish(View view) { + DropManager.getInstance().setTouchable(true); + } + + }); + + + +// this.tvUnread.setTouchListener(new DropFake.ITouchListener() { +// @Override +// public void onDown() { +// DropManager.getInstance().setCurrentId(recent); +// DropManager.getInstance().down(tvUnread, tvUnread.getText()); +// } +// +// @Override +// public void onMove(float curX, float curY) { +// DropManager.getInstance().move(curX, curY); +// } +// +// @Override +// public void onUp() { +// DropManager.getInstance().up(); +// } +// }); + } + + @Override + public void refresh(BaseViewHolder holder, RecentContact recent, final int position) { + + + // unread count animation + boolean shouldBoom = lastUnreadCount > 0 && recent.getUnreadCount() == 0; // 未读数从N->0执行爆裂动画; + lastUnreadCount = recent.getUnreadCount(); + + updateBackground(holder, recent, position); + + loadNoble(recent); + + loadPortrait(recent); + + updateNickLabel(recent); + + updateOnlineState(recent); + + updateMsgLabel(holder, recent); + + updateNewIndicator(recent); + + if (shouldBoom) { + Object o = DropManager.getInstance().getCurrentId(); + if (o instanceof String && o.equals("0")) { + imgUnreadExplosion.setImageResource(R.drawable.explosion); + imgUnreadExplosion.setVisibility(VISIBLE); + new Handler().post(new Runnable() { + @Override + public void run() { + ((AnimationDrawable) imgUnreadExplosion.getDrawable()).start(); + // 解决部分手机动画无法播放的问题(例如华为荣耀) + getAdapter().notifyItemChanged(getAdapter().getViewHolderPosition(position)); + } + }); + } + } else { + imgUnreadExplosion.setVisibility(GONE); + } + +// if (getAdapter().isLastDataItem(position)) { +// topLine.setVisibility(GONE); +// } + } + + @SuppressLint("CheckResult") + private void loadNoble(RecentContact recent) { + mIvNobleHeadWear.setVisibility(INVISIBLE); + mIvNobleLevel.setVisibility(GONE); + mIvNobleBadge.setVisibility(GONE); + if (recent == null) return; + String contactId = recent.getContactId(); + //去除小秘书,系统消息 + long sysMsgUid = XChatApplication.isDebug() ? XChatConstants.SYSTEM_MESSAGER_UID_DEBUG : XChatConstants.SYSTEM_MESSAGER_UID; + long secretaryUid = XChatApplication.isDebug() ? XChatConstants.SECRETARY_UID_DEBUG : XChatConstants.SECRETARY_UID; + if (String.valueOf(sysMsgUid).equals(contactId) || String.valueOf(secretaryUid).equals(contactId)) { + return; + } + + UserModel.get() + .getUserInfo(Long.valueOf(contactId)) + .subscribe(userInfo -> { + UserLevelVo userLevelVo = userInfo.getUserLevelVo(); + if (userLevelVo != null && !TextUtils.isEmpty(userLevelVo.getExperUrl())) { + mIvNobleLevel.setVisibility(VISIBLE); + ImageLoadUtils.loadImage(mIvNobleLevel.getContext(), userLevelVo.getExperUrl(), mIvNobleLevel); + } + if (userLevelVo != null && !TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + ivCharmLevel.setVisibility(VISIBLE); + ImageLoadUtils.loadImage(ivCharmLevel.getContext(), userLevelVo.getCharmUrl(), ivCharmLevel); + } + if (userInfo.getGender() == 1) { + ivUserGender.setImageResource(R.drawable.ic_male); + } else { + ivUserGender.setImageResource(R.drawable.ic_female); + } + if (userInfo.getNobleInfo() != null) + setNobleData(userInfo.getNobleUsers()); +// ivUserOfficialView.setVisibility(userInfo.isOfficial() ? VISIBLE : GONE); + }); + } + + private void setNobleData(NobleInfo nobleInfo) { + if (nobleInfo != null) { + mIvNobleHeadWear.setVisibility(VISIBLE); + mIvNobleBadge.setVisibility(VISIBLE); + String headWear = nobleInfo.getHeadWear(); + if (TextUtils.isEmpty(headWear)) { + mIvNobleHeadWear.setVisibility(INVISIBLE); + mIvNobleBadge.setVisibility(nobleInfo.getLevel() > 0 ? VISIBLE : GONE); + NobleUtil.loadResource(NobleUtil.getBadgeByLevel(nobleInfo.getLevel()), mIvNobleBadge); + } else { + mIvNobleBadge.setVisibility(GONE); + NobleUtil.loadResource(headWear, mIvNobleHeadWear); + } + String badgeByLevel = NobleUtil.getBadgeByLevel(nobleInfo.getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + mIvNobleBadge.setVisibility(VISIBLE); + NobleUtil.loadResource(badgeByLevel, mIvNobleBadge); + } + } else { + mIvNobleHeadWear.setVisibility(INVISIBLE); + mIvNobleBadge.setVisibility(GONE); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/RecentViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/RecentViewHolder.java new file mode 100644 index 000000000..1312b19c1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/RecentViewHolder.java @@ -0,0 +1,307 @@ +package com.yizhuan.erban.ui.im.recent.holder; + +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.business.recent.RecentContactsCallback; +import com.netease.nim.uikit.business.session.emoji.MoonUtil; +import com.netease.nim.uikit.business.session.helper.TeamNotificationHelper; +import com.netease.nim.uikit.business.uinfo.UserInfoHelper; +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleView; +import com.netease.nim.uikit.common.ui.drop.DropFake; +import com.netease.nim.uikit.common.ui.imageview.HeadImageView; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.netease.nim.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nim.uikit.common.ui.recyclerview.holder.RecyclerViewHolder; +import com.netease.nim.uikit.common.util.sys.TimeUtil; +import com.netease.nim.uikit.impl.cache.TeamDataCache; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.model.Team; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.recent.RecentContactsFragment; +import com.yizhuan.erban.ui.im.recent.adapter.RecentContactAdapter; +import com.yizhuan.xchat_android_core.im.custom.bean.AssistantAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.ImTipAttachment; + +import java.util.ArrayList; +import java.util.List; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + +public abstract class RecentViewHolder extends RecyclerViewHolder { + + public RecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + protected int lastUnreadCount = 0; + + protected View topLine; + protected HeadImageView imgHead; + protected AppCompatImageView mIvNobleHeadWear; + protected AppCompatImageView mIvNobleLevel; + protected AppCompatImageView mIvNobleBadge; + protected AppCompatImageView ivCharmLevel; + protected AppCompatImageView ivUserGender; + protected AppCompatImageView ivUserOfficialView; + + protected TextView tvNickname; + + protected TextView tvMessage; + + protected TextView tvDatetime; + + // 消息发送错误状态标记,目前没有逻辑处理 + protected ImageView imgMsgStatus; + + // 未读红点(一个占坑,一个全屏动画) + protected BubbleView tvUnread; + + protected ImageView imgUnreadExplosion; + + protected TextView tvOnlineState; + + protected ImageView msgNotifyIcon; + + // 子类覆写 + protected abstract String getContent(RecentContact recent); + + @Override + public void convert(BaseViewHolder holder, RecentContact data, int position, boolean isScrolling) { + inflate(holder, data); + refresh(holder, data, position); + } + + protected abstract void inflate(BaseViewHolder holder, RecentContact data); + + protected abstract void refresh(BaseViewHolder holder, RecentContact data, int position); + + + protected void updateBackground(BaseViewHolder holder, RecentContact recent, int position) { + if ((recent.getTag() & RecentContactsFragment.RECENT_TAG_STICKY) == 0) { + holder.getConvertView().setBackgroundResource(R.drawable.bg_common_touch_while); + } else { + holder.getConvertView().setBackgroundResource(R.drawable.nim_recent_contact_sticky_selecter); + } + } + + protected void loadPortrait(RecentContact recent) { + // 设置头像 + if (recent.getSessionType() == SessionTypeEnum.P2P) { + imgHead.loadBuddyAvatar(recent.getContactId()); + } else if (recent.getSessionType() == SessionTypeEnum.Team) { + Team team = TeamDataCache.getInstance().getTeamById(recent.getContactId()); + imgHead.loadTeamIconByTeam(team); + } + } + + protected void updateNewIndicator(RecentContact recent) { + int unreadNum = recent.getUnreadCount(); + setUnRead(unreadNum); +// tvUnread.setNumText(unreadNum); +// tvUnread.setVisibility(unreadNum > 0 ? VISIBLE : GONE); +// tvUnread.setText(unreadCountShowRule(unreadNum)); + } + + protected void setUnRead(int count) { + tvUnread.setNumText(count); + } + + protected void updateMsgNotifyIcon(RecentContact recentContact) { + // + } + + protected void updateMsgLabel(BaseViewHolder holder, RecentContact recent) { + // 显示消息具体内容 + MoonUtil.identifyRecentVHFaceExpressionAndTags(holder.getContext(), tvMessage, getContent(recent), -1, 0.45f); + //tvMessage.setText(getContent()); + + MsgStatusEnum status = recent.getMsgStatus(); + switch (status) { + case fail: + imgMsgStatus.setImageResource(R.drawable.nim_g_ic_failed_small); + imgMsgStatus.setVisibility(VISIBLE); + break; + case sending: + imgMsgStatus.setImageResource(R.drawable.nim_recent_contact_ic_sending); + imgMsgStatus.setVisibility(VISIBLE); + break; + default: + imgMsgStatus.setVisibility(GONE); + break; + } + + String timeString = TimeUtil.getTimeShowString(recent.getTime(), true); + tvDatetime.setText(timeString); + } + + protected String getOnlineStateContent(RecentContact recent) { + return ""; + } + + protected void updateOnlineState(RecentContact recent) { + if (recent.getSessionType() == SessionTypeEnum.Team) { + tvOnlineState.setVisibility(GONE); + } else { + String onlineStateContent = getOnlineStateContent(recent); + if (TextUtils.isEmpty(onlineStateContent)) { + tvOnlineState.setVisibility(GONE); + } else { + tvOnlineState.setVisibility(VISIBLE); + tvOnlineState.setText(getOnlineStateContent(recent)); + } + } + } + + protected void updateNickLabel(RecentContact recent) { + switch (recent.getSessionType()) { + case Team: + Team team = TeamDataCache.getInstance().getTeamById(recent.getContactId()); + if (team != null) { + tvNickname.setText(team.getName()); + } + break; + + default: + case P2P: + String nick = UserInfoHelper.getUserTitleName(recent.getContactId(), recent.getSessionType()); + tvNickname.setText(nick); + break; + } + } + + protected String unreadCountShowRule(int unread) { + unread = Math.min(unread, 99); + return String.valueOf(unread); + } + + protected RecentContactsCallback getCallback() { + return ((RecentContactAdapter) getAdapter()).getCallback(); + } + + protected String descOfMsg(RecentContact recent) { + if (recent.getMsgType() == MsgTypeEnum.text) { + return recent.getContent(); + } else if (recent.getMsgType() == MsgTypeEnum.tip) { + String digest = null; + if (getCallback() != null) { + digest = getCallback().getDigestOfTipMsg(recent); + } + + if (digest == null) { + digest = getDefaultDigest(null, recent); + } + + return digest; + } else if (recent.getAttachment() != null) { + String digest = null; + if (getCallback() != null) { + digest = getCallback().getDigestOfAttachment(recent, recent.getAttachment()); + } + + if (digest == null) { + digest = getDefaultDigest(recent.getAttachment(), recent); + } + + return digest; + } + return ""; + } + + // SDK本身只记录原始数据,第三方APP可根据自己实际需求,在最近联系人列表上显示缩略消息 + // 以下为一些常见消息类型的示例。 + private String getDefaultDigest(MsgAttachment attachment, RecentContact recent) { + switch (recent.getMsgType()) { + case text: + return recent.getContent(); + case image: + return "[图片]"; + case video: + return "[视频]"; + case audio: + return "[语音消息]"; + case location: + return "[位置]"; + case file: + return "[文件]"; + case tip: + List uuids = new ArrayList<>(); + uuids.add(recent.getRecentMessageId()); + List messages = NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuids); + if (messages != null && messages.size() > 0) { + return messages.get(0).getContent(); + } + return "[通知提醒]"; + case notification: + return TeamNotificationHelper.getTeamNotificationText(recent.getContactId(), + recent.getFromAccount(), + (NotificationAttachment) recent.getAttachment()); + case avchat: +// AVChatAttachment avchat = (AVChatAttachment) attachment; +// if (avchat.getState() == AVChatRecordState.Missed && !recent.getFromAccount().equals(NimUIKit.getAccount())) { +// // 未接通话请求 +// StringBuilder sb = new StringBuilder("[未接"); +// if (avchat.getType() == AVChatType.VIDEO) { +// sb.append("视频电话]"); +// } else { +// sb.append("音频电话]"); +// } +// return sb.toString(); +// } else if (avchat.getState() == AVChatRecordState.Success) { +// StringBuilder sb = new StringBuilder(); +// if (avchat.getType() == AVChatType.VIDEO) { +// sb.append("[视频电话]: "); +// } else { +// sb.append("[音频电话]: "); +// } +// sb.append(TimeUtil.secToTime(avchat.getDuration())); +// return sb.toString(); +// } else { +// if (avchat.getType() == AVChatType.VIDEO) { +// return ("[视频电话]"); +// } else { +// return ("[音频电话]"); +// } +// } + case robot: + return "[机器人消息]"; + + case custom: + if (attachment instanceof CustomAttachment) { + CustomAttachment customAttachment = (CustomAttachment) attachment; + switch (customAttachment.getFirst()) { + case CustomAttachment.CUSTOM_MSG_ASSISTANT_MSG: + AssistantAttachment monsterAwardAttachment = (AssistantAttachment) attachment; + switch (monsterAwardAttachment.getSecond()) { + case CustomAttachment.CUSTOM_MSG_ASSISTANT_COMMON_MSG: + return monsterAwardAttachment.title; + } + break; + case CustomAttachment.CUSTOM_MSG_IM_GAME: + return "[游戏邀请]"; + case CustomAttachment.CUSTOM_MSG_IM_TIP: + ImTipAttachment imTipAttachment = (ImTipAttachment) attachment; + return imTipAttachment.getMsg(); + case CustomAttachment.CUSTOM_MSG_LEVEL_UP: + return "[升级信息]"; + } + } + + default: + return "[自定义消息] "; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/TeamRecentViewHolder.java b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/TeamRecentViewHolder.java new file mode 100644 index 000000000..af6bf73be --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/im/recent/holder/TeamRecentViewHolder.java @@ -0,0 +1,223 @@ +package com.yizhuan.erban.ui.im.recent.holder; + +import android.graphics.drawable.AnimationDrawable; +import android.os.Handler; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.google.gson.Gson; +import com.netease.nim.uikit.api.NimUIKit; +import com.netease.nim.uikit.business.recent.TeamMemberAitHelper; +import com.netease.nim.uikit.business.team.helper.TeamHelper; +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleMessageTouchListener; +import com.netease.nim.uikit.common.ui.draggablebubbles.MessageBubbleView; +import com.netease.nim.uikit.common.ui.drop.DropFake; +import com.netease.nim.uikit.common.ui.drop.DropManager; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseQuickAdapter; +import com.netease.nim.uikit.common.ui.recyclerview.holder.BaseViewHolder; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; +import com.netease.nimlib.sdk.msg.attachment.NotificationAttachment; +import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; +import com.netease.nimlib.sdk.msg.model.RecentContact; +import com.netease.nimlib.sdk.team.TeamService; +import com.netease.nimlib.sdk.team.constant.TeamMessageNotifyTypeEnum; +import com.netease.nimlib.sdk.team.model.Team; +import com.trello.rxlifecycle2.LifecycleProvider; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.im.recent.TeamExt; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.LuckyMoneyTipsAttachment; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + +public class TeamRecentViewHolder extends RecentViewHolder { + + private Team team; + private ImageView ivMiniWorld; + + public TeamRecentViewHolder(BaseQuickAdapter adapter) { + super(adapter); + } + + @Override + public void inflate(BaseViewHolder holder, final RecentContact recent) { + this.imgHead = holder.getView(R.id.img_head); + this.tvNickname = holder.getView(R.id.tv_nickname); + this.tvMessage = holder.getView(R.id.tv_message); + this.tvUnread = holder.getView(R.id.unread_number_tip); + this.imgUnreadExplosion = holder.getView(R.id.unread_number_explosion); + this.tvDatetime = holder.getView(R.id.tv_date_time); + this.imgMsgStatus = holder.getView(R.id.img_msg_status); + this.tvOnlineState = holder.getView(R.id.tv_online_state); + this.msgNotifyIcon = holder.getView(R.id.iv_mute_notification); + this.ivMiniWorld = holder.getView(R.id.iv_mini_world_img); +// topLine = holder.getView(R.id.top_line); + +// holder.addOnClickListener(R.id.unread_number_tip); + + MessageBubbleView.attach(this.tvUnread, new BubbleMessageTouchListener.BubbleDisappearListener() { + @Override + public void dragStart(View view) { + DropManager.getInstance().setTouchable(false); + } + + @Override + public void dismiss(View view) { + DropManager.getInstance().setCurrentId(recent); + DropManager.getInstance().down(tvUnread, tvUnread.getText().toString()); + } + + @Override + public void dragFinish(View view) { + DropManager.getInstance().setTouchable(true); + } + + }); +// this.tvUnread.setTouchListener(new DropFake.ITouchListener() { +// @Override +// public void onDown() { +// DropManager.getInstance().setCurrentId(recent); +// DropManager.getInstance().down(tvUnread, tvUnread.getText()); +// } +// +// @Override +// public void onMove(float curX, float curY) { +// DropManager.getInstance().move(curX, curY); +// } +// +// @Override +// public void onUp() { +// DropManager.getInstance().up(); +// } +// }); + + team = NIMClient.getService(TeamService.class).queryTeamBlock(recent.getContactId()); + } + + @Override + public void refresh(BaseViewHolder holder, RecentContact recent, final int position) { + + // unread count animation + boolean shouldBoom = lastUnreadCount > 0 && recent.getUnreadCount() == 0; // 未读数从N->0执行爆裂动画; + lastUnreadCount = recent.getUnreadCount(); + + updateBackground(holder, recent, position); + + loadPortrait(recent); + + updateOnlineState(recent); + + updateNickLabel(recent); + + updateMsgLabel(holder, recent); + + if (!isNotifyIconShow(recent)) + updateNewIndicator(recent); + else + setUnRead(0);// 关闭消息提醒不显示未读数量 + + updateMsgNotifyIcon(recent); + + if (shouldBoom) { + Object o = DropManager.getInstance().getCurrentId(); + if (o instanceof String && o.equals("0")) { + imgUnreadExplosion.setImageResource(R.drawable.explosion); + imgUnreadExplosion.setVisibility(VISIBLE); + new Handler().post(new Runnable() { + @Override + public void run() { + ((AnimationDrawable) imgUnreadExplosion.getDrawable()).start(); + // 解决部分手机动画无法播放的问题(例如华为荣耀) + getAdapter().notifyItemChanged(getAdapter().getViewHolderPosition(position)); + } + }); + } + } else { + imgUnreadExplosion.setVisibility(GONE); + } + + if (ivMiniWorld != null) { + if (team != null) { + + int type = 0; + String ext = team.getExtServer(); + if (!TextUtils.isEmpty(ext)) { + TeamExt teamExt = new Gson().fromJson(ext, TeamExt.class); + if (teamExt != null) { + type = teamExt.getType(); + } + } + + if (type == 2) { + ivMiniWorld.setVisibility(VISIBLE); + + } else { + ivMiniWorld.setVisibility(GONE); + + } + } else { + ivMiniWorld.setVisibility(GONE); + } + + } + +// if (getAdapter().isLastDataItem(position)) { +// topLine.setVisibility(GONE); +// } + } + + @Override + protected String getContent(RecentContact recent) { + String content = descOfMsg(recent); + + String fromId = recent.getFromAccount(); + MsgAttachment attachment = recent.getAttachment(); + if (!TextUtils.isEmpty(fromId) + && !fromId.equals(NimUIKit.getAccount()) + && !(attachment instanceof NotificationAttachment) + && !(attachment instanceof LuckyMoneyAttachment) + && !(attachment instanceof LuckyMoneyTipsAttachment)) { + String tid = recent.getContactId(); + String teamNick = getTeamUserDisplayName(tid, fromId); + content = teamNick + ": " + content; + + if (TeamMemberAitHelper.hasAitExtension(recent)) { + if (recent.getUnreadCount() == 0) { + TeamMemberAitHelper.clearRecentContactAited(recent); + } else { + content = TeamMemberAitHelper.getAitAlertString(content); + } + } + } + + return content; + } + + private String getTeamUserDisplayName(String tid, String account) { + return TeamHelper.getTeamMemberDisplayName(tid, account); + } + +// @Override +// protected void updateNewIndicator(RecentContact recent) { +// if (team != null && team.getMessageNotifyType() == TeamMessageNotifyTypeEnum.Mute) { +//// NIMClient.getService(MsgService.class).clearUnreadCount(recent.getContactId(), SessionTypeEnum.Team); +// tvUnread.setVisibility(GONE); +// } else { +// super.updateNewIndicator(recent); +// } +// } + + @Override + protected void updateMsgNotifyIcon(RecentContact recentContact) { + super.updateMsgNotifyIcon(recentContact); + msgNotifyIcon.setVisibility(isNotifyIconShow(recentContact) ? VISIBLE : GONE); + } + + private boolean isNotifyIconShow(RecentContact recentContact) { + return recentContact.getSessionType() == SessionTypeEnum.Team + && team != null && team.getMessageNotifyType() == TeamMessageNotifyTypeEnum.Mute; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/IndicatorHelper.java b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/IndicatorHelper.java new file mode 100644 index 000000000..da577113b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/IndicatorHelper.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.ui.indicator_impl; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.widget.LinearLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; + +import java.util.List; + +/** + * create by lvzebiao @2020/1/7 + */ +public class IndicatorHelper { + + public static void handle(Context context, ViewPager viewPager, MagicIndicator magicIndicator, + List list, OnItemSelectListener listener) { + CommonNavigator commonNavigator = new CommonNavigator(context); + JustColorIndicatorAdapter magicIndicatorAdapter = new JustColorIndicatorAdapter(context, list); + if (listener == null) { + listener = (position, view) -> viewPager.setCurrentItem(position); + } + magicIndicatorAdapter.setOnItemSelectListener(listener); + commonNavigator.setAdapter(magicIndicatorAdapter); + magicIndicator.setNavigator(commonNavigator); + commonNavigator.getTitleContainer().setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + ViewPagerHelper.bind(magicIndicator, viewPager); + } + + public static void handle(Context context, ViewPager viewPager, MagicIndicator magicIndicator, + List list) { + handle(context, viewPager, magicIndicator, list, null); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/JustColorIndicatorAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/JustColorIndicatorAdapter.java new file mode 100644 index 000000000..0a9c51a68 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/JustColorIndicatorAdapter.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.ui.indicator_impl; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.XRecyclerView.ScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; + +import java.util.List; + +/** + * create by lvzebiao @2020/1/7 + */ +public class JustColorIndicatorAdapter extends CommonNavigatorAdapter { + + private final Context mContext; + private final List mTitleList; + + + + public JustColorIndicatorAdapter(Context context, List charSequences) { + this.mContext = context; + this.mTitleList = charSequences; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + ScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new ScaleTransitionPagerTitleView(context, false, 0); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_B3B3B3)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setAlwaysBold(); + scaleTransitionPagerTitleView.setMinScale(1.0f); + scaleTransitionPagerTitleView.setTextSize(16); + int padding = UIUtil.dip2px(context, 11); + scaleTransitionPagerTitleView.setPadding(padding, 0, padding, 0); + scaleTransitionPagerTitleView.setText(mTitleList.get(i)); + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i, scaleTransitionPagerTitleView); + } + }); + return scaleTransitionPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(mContext, 3)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 22)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 12)); + indicator.setColors(context.getResources().getColor(R.color.appColor)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = UIUtil.dip2px(mContext, 5); + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/OnItemSelectListener.java b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/OnItemSelectListener.java new file mode 100644 index 000000000..e8894f5d7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/indicator_impl/OnItemSelectListener.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.ui.indicator_impl; + +import android.widget.TextView; + +/** + * create by lvzebiao @2020/1/7 + */ +public interface OnItemSelectListener { + + void onItemSelect(int position, TextView view); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/keepalive/OnePiexlActivity.java b/app/src/main/java/com/yizhuan/erban/ui/keepalive/OnePiexlActivity.java new file mode 100644 index 000000000..e0e19b6fb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/keepalive/OnePiexlActivity.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.ui.keepalive; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.os.PowerManager; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.base.BaseActivity; + +/** + * Created by chenran on 2017/11/16. + */ + +public class OnePiexlActivity extends BaseActivity { + + private BroadcastReceiver endReceiver; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + //设置1像素 + Window window = getWindow(); + window.setGravity(Gravity.LEFT | Gravity.TOP); + WindowManager.LayoutParams params = window.getAttributes(); + params.x = 0; + params.y = 0; + params.height = 1; + params.width = 1; + window.setAttributes(params); + + //结束该页面的广播 + endReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + finish(); + } + }; + registerReceiver(endReceiver, new IntentFilter("finish")); + //检查屏幕状态 + checkScreen(); + } + + @Override + protected void onResume() { + super.onResume(); + checkScreen(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(endReceiver); + } + + /** + * 检查屏幕状态 isScreenOn为true 屏幕“亮”结束该Activity + */ + private void checkScreen() { + + PowerManager pm = (PowerManager) OnePiexlActivity.this.getSystemService(Context.POWER_SERVICE); + boolean isScreenOn = pm.isScreenOn(); + if (isScreenOn) { + finish(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/list/BaseListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/list/BaseListAdapter.java new file mode 100644 index 000000000..4160c5be1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/list/BaseListAdapter.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.ui.list; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import java.util.List; + +/** + * Created by ${user} on 2017/11/3. + */ +public abstract class BaseListAdapter extends RecyclerView.Adapter { + protected static final int VIEW_TYPE_ONE = 1; + protected static final int VIEW_TYPE_TWO = 2; + protected static final int VIEW_TYPE_THREE = 3; + protected static final int VIEW_TYPE_OTHER = 4; + protected Context mContext; + protected LayoutInflater mLayoutInflater; + private List mDataList; + + public BaseListAdapter(Context context) { + mContext = context; + mLayoutInflater = LayoutInflater.from(context); + } + + public void setDataList(List dataList) { + mDataList = dataList; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mDataList == null ? 0 : mDataList.size(); + } + + @Override + public int getItemViewType(int position) { + if (position == 0) return VIEW_TYPE_ONE; + else if (position == 1) return VIEW_TYPE_TWO; + else if (position == 2) return VIEW_TYPE_THREE; + else return VIEW_TYPE_OTHER; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return onCreateHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder == null) + throw new IllegalArgumentException("holder is null !!!"); + onBindHolder((T) holder, position); + } + + public abstract T onCreateHolder(ViewGroup parent, int viewType); + + public abstract void onBindHolder(T holder, int position); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/AccountValidator.java b/app/src/main/java/com/yizhuan/erban/ui/login/AccountValidator.java new file mode 100644 index 000000000..7ae72a4b6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/AccountValidator.java @@ -0,0 +1,101 @@ +package com.yizhuan.erban.ui.login; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import com.yizhuan.xchat_android_library.utils.StringUtils; + +import java.util.regex.Pattern; + +/** + * Created by zhouxiangfeng on 2017/5/3. + */ + +public class AccountValidator { + + /** + * 正则:手机号(精确) + *

移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188、198

+ *

联通:130、131、132、145、155、156、175、176、185、186、166

+ *

电信:133、153、173、177、180、181、189、199

+ *

全球星:1349

+ *

虚拟运营商:170

+ */ + public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"; + + private String errorMessage; + + public AccountValidator() { + } + + public AccountValidator(@NonNull String errorMessage) { + this.errorMessage = errorMessage; + } + + private boolean isValidMobileNumber(String phone) { + return phone.length() > 0 && Pattern.matches(REGEX_MOBILE_EXACT, phone); + } + + private boolean isAllDigits(String str) { + if (StringUtils.isEmpty(str)) return false; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c < '0' || c > '9') { + return false; + } + } + return true; + } + + public boolean isValid(@NonNull CharSequence text) { + if (!TextUtils.isEmpty(text)) { +// char c = text.charAt(0); +// if (!(c == '1')) { +// errorStr = "手机号码错误"; +// return false; +// } +// if (text.length() > 11) { +// errorStr = "账号长度为11个字符"; +// return false; +// } +// if(!MobileNumberUtils.isChinaInternalNumber(text) && !MobileNumberUtils.isChinaMobileNumber(text) && !MobileNumberUtils.isChinaTelecomNumber(text) && !MobileNumberUtils.isChinaUnicomNumber(text)){ +// errorStr = "请填写正确的手机号码"; +// return false; +// } + } else { + errorMessage = "账号不能为空!"; + return false; + } + return true; + } + + public boolean isValidToRegister(@NonNull CharSequence text) { + if (!TextUtils.isEmpty(text)) { +// char c = text.charAt(0); +// if (!(c == '1')) { +// errorStr = "手机号码错误"; +// return false; +// } + if (text.length() != 11) { + errorMessage = "账号长度为11个字符"; + return false; + } +// if(!MobileNumberUtils.isChinaInternalNumber(text) && !MobileNumberUtils.isChinaMobileNumber(text) && !MobileNumberUtils.isChinaTelecomNumber(text) && !MobileNumberUtils.isChinaUnicomNumber(text)){ +// errorStr = "请填写正确的手机号码"; +// return false; +// } + } else { + errorMessage = "账号不能为空!"; + return false; + } + return true; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/AddUserInfoActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/AddUserInfoActivity.java new file mode 100644 index 000000000..df7d6eb5f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/AddUserInfoActivity.java @@ -0,0 +1,62 @@ +package com.yizhuan.erban.ui.login; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.view.KeyEvent; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.login.fragment.AddUserInfoFragment; + +/** + * @author zhouxiangfeng + * @date 2017/5/12 + */ + +public class AddUserInfoActivity extends BaseActivity { + + private static final String TAG = "AddUserInfoActivity"; + private AddUserInfoFragment addUserInfoFragment; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_addinfo); + + addUserInfoFragment = new AddUserInfoFragment(); + showAddUserInfo(); + } + + public void showAddUserInfo() { +// initTitleBar("", false); +// if (mTitleBar != null) +// mTitleBar.setLeftClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// try { +// moveTaskToBack(true); +// } catch (Exception ex) { +// +// } +// } +// }); + replaceFragment(addUserInfoFragment); + } + + private void replaceFragment(Fragment fragment) { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.replace(R.id.fl_fragment_container, fragment, fragment.getClass().getSimpleName()); + fragmentTransaction.commit(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + moveTaskToBack(true); + return true; + } + return super.onKeyDown(keyCode, event); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/BindSuccessDialog.java b/app/src/main/java/com/yizhuan/erban/ui/login/BindSuccessDialog.java new file mode 100644 index 000000000..2244336a9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/BindSuccessDialog.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.ui.login; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +public class BindSuccessDialog extends DialogFragment implements View.OnClickListener { + + private BindSuccessDialogListener mListener; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); + getDialog().setOnKeyListener(((dialog, keyCode, event) -> true)); + getDialog().setCanceledOnTouchOutside(false); + + View root = inflater.inflate(R.layout.dialog_bind_success, container, false); + root.findViewById(R.id.tv_dialog_close).setOnClickListener(this); + + return root; + } + + public void setmListener(BindSuccessDialogListener mListener) { + this.mListener = mListener; + } + + @Override + public void onResume() { + super.onResume(); + + getDialog().getWindow().setLayout(SizeUtils.dp2px(getContext(), 308), ViewGroup.LayoutParams.WRAP_CONTENT); + getDialog().getWindow().setBackgroundDrawableResource(R.color.transparent); + } + + @Override + public void dismiss() { + super.dismiss(); + + if (mListener != null) + mListener.close(); + + mListener = null; + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_dialog_close: + dismiss(); + break; + } + } + + public interface BindSuccessDialogListener { + void close(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/BinderPhoneActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/BinderPhoneActivity.java new file mode 100644 index 000000000..2e74f77ac --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/BinderPhoneActivity.java @@ -0,0 +1,256 @@ +package com.yizhuan.erban.ui.login; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.login.helper.LogoutHelper; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.TextWatcherWrapper; + +import java.text.NumberFormat; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/* + * copy绑定支付宝页面,控件ID没有改变 详情请看布局 + */ +public class BinderPhoneActivity extends BaseActivity implements View.OnClickListener, + BindSuccessDialog.BindSuccessDialogListener { + + /** + * ture的话,表示,能返回登录 + */ + public static final String KEY_BACK_LOGIN = "key_back_login"; + + private EditText etAlipayAccount; + private EditText etSmsCode; + private Button btnGetCode; + private Button btnBinderRquest; + private CodeDownTimer timer; + private TextView tvSkip; + private ImageView ivBack; + private TextView tvBackLogin; + + private boolean isBackLogin; + + public static void start(Context context, boolean backLogin) { + Intent intent = new Intent(context, BinderPhoneActivity.class); + intent.putExtra(KEY_BACK_LOGIN, backLogin); + context.startActivity(intent); + } + + public static void start(Context context) { + start(context, false); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_binder_phone); + initView(); + initData(); + setListener(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stopCountDownTimer(); + } + + private void initView() { + etAlipayAccount = findViewById(R.id.et_phone); + etSmsCode = findViewById(R.id.et_smscode); + btnGetCode = findViewById(R.id.btn_get_code); + btnBinderRquest = findViewById(R.id.btn_binder_request); + tvSkip = findViewById(R.id.tv_skip); + ivBack = findViewById(R.id.iv_back); + tvBackLogin = findViewById(R.id.tv_back_login); + } + + private void initData() { + //设置是否显示跳过按钮 + tvSkip.setVisibility(View.GONE); + isBackLogin = getIntent().getBooleanExtra(KEY_BACK_LOGIN, false); + tvBackLogin.setVisibility(View.VISIBLE); + tvBackLogin.setText(isBackLogin ? R.string.back_login_page : R.string.back); + } + + private void setListener() { + btnBinderRquest.setEnabled(false); + //获取绑定手机验证码 + btnGetCode.setOnClickListener(this); + //请求绑定手机号码 + btnBinderRquest.setOnClickListener(this); + + //输入框监听改变 + TextWatcher textWatcher = new TextWatcherWrapper() { + @Override + public void afterTextChanged(Editable s) { + if (etAlipayAccount.getText() != null && etAlipayAccount.getText().length() > 0 + && etSmsCode.getText() != null && etSmsCode.getText().length() > 0) { + btnBinderRquest.setEnabled(true); + } else { + btnBinderRquest.setEnabled(false); + } + } + }; + + etAlipayAccount.addTextChangedListener(textWatcher); + etSmsCode.addTextChangedListener(textWatcher); + + tvSkip.setOnClickListener(this); + ivBack.setOnClickListener(this); + tvBackLogin.setOnClickListener(this); + } + + private void bindPhone() { + getDialogManager().showProgressDialog(BinderPhoneActivity.this, "正在绑定请稍后..."); + AuthModel.get().bindPhone( + etAlipayAccount.getText().toString(), + etSmsCode.getText().toString() + ) + .flatMap(s -> UserModel.get().updateCurrentUserInfo()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(UserInfo s) { + getDialogManager().dismissDialog(); + toast("绑定手机号成功"); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + + } + + private void bindSuccessDialog() { + BindSuccessDialog dialog = new BindSuccessDialog(); + dialog.setmListener(this); + dialog.show(getSupportFragmentManager(), "bindSuccess"); + } + + private void getCode() { + String phoneNumber = etAlipayAccount.getText().toString().trim(); + Number parse = null; + try { + parse = NumberFormat.getIntegerInstance().parse(phoneNumber); + } catch (Exception e) { + Log.e("bind phone", e.getMessage(), e); + } + if (parse == null || parse.intValue() == 0 || phoneNumber.length() != 11) { +// Toast.makeText(BasicConfig.INSTANCE.getAppContext(), "请输入正确的手机号码", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入正确的手机号码"); + return; + } + startCountDownTimer(); + + CodeModel.get().sendCode(phoneNumber, CodeType.BIND_PHONE) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + + @Override + public void onClick(View v) { + + switch (v.getId()) { + case R.id.btn_get_code: + getCode(); + break; + + case R.id.btn_binder_request: + bindPhone(); + break; + case R.id.tv_skip: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.LOGIN_BINDING_PHONE_SKIP, "绑定手机-跳过"); + finish(); + break; + case R.id.iv_back: + case R.id.tv_back_login: + handleFinish(); + break; + default: + break; + } + + } + + @Override + public void close() { + setResult(RESULT_OK); + finish(); + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(btnGetCode, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + + @Override + public void onBackPressed() { + handleFinish(); + } + + private void handleFinish() { + if (!isBackLogin) { + toast("请先绑定手机号"); + return; + } + LogoutHelper.logout(); + finish(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/CodeDownTimer.java b/app/src/main/java/com/yizhuan/erban/ui/login/CodeDownTimer.java new file mode 100644 index 000000000..944d2f136 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/CodeDownTimer.java @@ -0,0 +1,68 @@ +package com.yizhuan.erban.ui.login; + +import android.graphics.Color; +import android.os.CountDownTimer; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.widget.TextView; + +import com.yizhuan.erban.R; + + +/** + * Created by zhouxiangfeng on 2017/5/2. + */ + +public class CodeDownTimer extends CountDownTimer { + private TextView mTextView; + + /** + * @param textView The TextView + * @param millisInFuture The number of millis in the future from the call + * to {@link #start()} until the countdown is done and {@link #onFinish()} + * is called. + * @param countDownInterval The interval along the way to receiver + * {@link #onTick(long)} callbacks. + */ + public CodeDownTimer(TextView textView, long millisInFuture, long countDownInterval) { + super(millisInFuture, countDownInterval); + this.mTextView = textView; + } + + @Override + public void onTick(long millisUntilFinished) { + mTextView.setClickable(false); //设置不可点击 + mTextView.setText(millisUntilFinished / 1000 + "秒后重试"); //设置倒计时时间 + mTextView.setTextColor(mTextView.getResources().getColor(R.color.color_FF3852)); //设置按钮为灰色,这时是不能点击的 + + /** + * 超链接 URLSpan + * 文字背景颜色 BackgroundColorSpan + * 文字颜色 ForegroundColorSpan + * 字体大小 AbsoluteSizeSpan + * 粗体、斜体 StyleSpan + * 删除线 StrikethroughSpan + * 下划线 UnderlineSpan + * 图片 ImageSpan + * http://blog.csdn.net/ah200614435/article/details/7914459 + */ + SpannableString spannableString = new SpannableString(mTextView.getText().toString()); //获取按钮上的文字 + ForegroundColorSpan span = new ForegroundColorSpan(Color.RED); + /** + * public void setSpan(Object what, int start, int end, int flags) { + * 主要是start跟end,start是起始位置,无论中英文,都算一个。 + * 从0开始计算起。end是结束位置,所以处理的文字,包含开始位置,但不包含结束位置。 + */ + spannableString.setSpan(span, 0, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);//将倒计时的时间设置为红色 + mTextView.setText(spannableString); + } + + @Override + public void onFinish() { + mTextView.setText("重新获取"); + mTextView.setClickable(true);//重新获得点击 + mTextView.setTextColor(mTextView.getResources().getColor(R.color.appColor)); //还原背景色 + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/ErbanQQMemberBindAndLoginActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/ErbanQQMemberBindAndLoginActivity.java new file mode 100644 index 000000000..2378251b2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/ErbanQQMemberBindAndLoginActivity.java @@ -0,0 +1,174 @@ +package com.yizhuan.erban.ui.login; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.text.style.ForegroundColorSpan; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityErbanQqBindLoginBinding; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.exception.BanAccountException; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.TextWatcherWrapper; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.activity_erban_qq_bind_login) +public class ErbanQQMemberBindAndLoginActivity extends BaseBindingActivity { + + public static final String KEY_OPEN_ID = "key_open_id"; + + private String errorStr; + private String openid; + private AccountValidator accountValidator = new AccountValidator(); + private PasswordValidator passwordValidator = new PasswordValidator(); + private TextWatcher textWatcher = new TextWatcherWrapper() { + @Override + public void afterTextChanged(Editable s) { + checkInput(); + } + }; + + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault()); + + public static void start(Context context, String openid) { + Intent intent = new Intent(context, ErbanQQMemberBindAndLoginActivity.class); + intent.putExtra(KEY_OPEN_ID, openid); + context.startActivity(intent); + } + + @Override + protected void init() { + mBinding.setClick(this); + if (getIntent() != null) { + this.openid = getIntent().getStringExtra(KEY_OPEN_ID); + } + mBinding.etAccount.addTextChangedListener(textWatcher); + mBinding.etPassword.addTextChangedListener(textWatcher); + + String howToSetPwdTip = "如何设置密码?"; + String howToSetPwdDescTip = context.getString(R.string.text_how_to_set_pwd, howToSetPwdTip); + SpannableString ss = new SpannableString(howToSetPwdDescTip); + int userAgreementTipIndex = howToSetPwdDescTip.indexOf(howToSetPwdTip); + ss.setSpan(new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + CommonWebViewActivity.start(context, UriProvider.JAVA_WEB_URL + XChatConstants.LOGIN_ERBAN_ACCOUNT_URL); + } + }, userAgreementTipIndex, userAgreementTipIndex + howToSetPwdTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.design_color)), + userAgreementTipIndex, userAgreementTipIndex + howToSetPwdTip.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + mBinding.tvLoginHint.setText(ss); + mBinding.tvLoginHint.setMovementMethod(new LinkMovementMethod()); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.btn_login: + final String account = mBinding.etAccount.getText().toString().toLowerCase(); + final String password = mBinding.etPassword.getText().toString(); + if (isOK(account, password)) { + + showDialog("正在登录...", true, dialog -> { + }); + + AuthModel.get().loginForOldMember( + account, + password, + openid + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + dealWithLoginError(e); + } + }); + + + } else { + toast(errorStr); + } + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_PHONE_CLICK, "点击手机号登录", null); + break; + } + } + + private void dealWithLoginError(Throwable e) { + if (e instanceof BanAccountException) { + BanAccountException exception = (BanAccountException) e; + String text = "您的账号因" + exception.getMessage() + "被封禁\n解封时间:"; + int start = text.length(); + text += simpleDateFormat.format(new Date(exception.getDate())); + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(ErbanQQMemberBindAndLoginActivity.this, R.color.appColor)), + start, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + getDialogManager().showOkCancelWithTitleDialog("您被封号了", + spannableString, "确定", "取消", null); + } else { + toast(e.getMessage()); + } + } + + private void showDialog(String tip, boolean cancelable, DialogInterface.OnDismissListener listener) { + getDialogManager().showProgressDialog(ErbanQQMemberBindAndLoginActivity.this, tip, cancelable, cancelable, listener); + } + + private boolean isOK(String account, String password) { + if (!accountValidator.isValid(account)) { + errorStr = accountValidator.getErrorMessage(); + return false; + } + if (!passwordValidator.isValid(password)) { + errorStr = passwordValidator.getErrorMessage(); + return false; + } + return true; + } + + private void checkInput() { + if (accountValidator.isValid(mBinding.etAccount.getText().toString()) + && passwordValidator.isValid(mBinding.etPassword.getText().toString())) { + mBinding.btnLogin.setEnabled(true); + } else { + mBinding.btnLogin.setEnabled(false); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/ForgetPswActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/ForgetPswActivity.java new file mode 100644 index 000000000..6ce575a25 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/ForgetPswActivity.java @@ -0,0 +1,172 @@ +package com.yizhuan.erban.ui.login; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.user.UserModel; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * Created by zhouxiangfeng on 17/3/5. + */ +public class ForgetPswActivity extends BaseActivity implements View.OnClickListener { + private static final String TAG = "RegisterActivity"; + private EditText phoneEt; + private Button getCodeBtn; + private EditText pswEt; + private EditText codeEt; + private Button btnModify; + private CodeDownTimer timer; + private AccountValidator accountValidator = new AccountValidator(); + private PasswordValidator passwordValidator = new PasswordValidator(); + private SMSCodeValidator smsCodeValidator = new SMSCodeValidator(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_forget_psw); + onFindViews(); + onSetListener(); + initTitleBar("", false); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stopCountDownTimer(); + } + + public void onFindViews() { + phoneEt = findViewById(R.id.et_phone); + pswEt = findViewById(R.id.et_password); + codeEt = findViewById(R.id.et_code); + getCodeBtn = findViewById(R.id.btn_get_code); + + if (UserModel.get().getCacheLoginUserInfo() != null && !TextUtils.isEmpty(UserModel.get().getCacheLoginUserInfo().getPhone())) { + phoneEt.setText(UserModel.get().getCacheLoginUserInfo().getPhone()); + phoneEt.clearFocus(); + phoneEt.setFocusable(false); + phoneEt.setFocusableInTouchMode(false); + } + + btnModify = (Button) findViewById(R.id.btn_modify); + btnModify.setEnabled(true); + } + + public void onSetListener() { + btnModify.setOnClickListener(this); + getCodeBtn.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_modify: + if (!accountValidator.isValidToRegister(phoneEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + String phone = phoneEt.getText().toString(); + + if (!passwordValidator.isValid(pswEt.getText().toString())) { + toast(passwordValidator.getErrorMessage()); + return; + } + String psw = pswEt.getText().toString(); + + if (!smsCodeValidator.isValid(codeEt.getText().toString())) { + toast(smsCodeValidator.getErrorMessage()); + return; + } + String sms_code = codeEt.getText().toString(); + + AuthModel.get().requestResetPsw(phone, sms_code, psw) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast("重置密码成功!"); + finish(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + break; + case R.id.btn_get_code: + if (!accountValidator.isValidToRegister(phoneEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + phone = phoneEt.getText().toString(); + + CodeModel.get().sendCode(phone, CodeType.RESET_PSW) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + toast(s); + startCountDownTimer(); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + break; + case R.id.iv_back: + finish(); + break; + } + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(getCodeBtn, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { +// super.setStatusBar(); + StatusBarLightModes(true); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/LoginActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/LoginActivity.java new file mode 100644 index 000000000..b02a87a72 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/LoginActivity.java @@ -0,0 +1,613 @@ +package com.yizhuan.erban.ui.login; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.text.style.ForegroundColorSpan; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.ishumei.smantifraud.SmAntiFraud; +import com.netease.mobsec.rjsb.watchman; +import com.orhanobut.logger.Logger; +import com.tongdaxing.erban.upgrade.AppUpgradeHelper; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.OriginalDrawStatusClickSpan; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Env; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.event.LoginEvent; +import com.yizhuan.xchat_android_core.auth.exception.BanAccountException; +import com.yizhuan.xchat_android_core.auth.exception.IsSuperAdminException; +import com.yizhuan.xchat_android_core.auth.exception.ShowPhoneCodeException; +import com.yizhuan.xchat_android_core.bean.LoginTipsInfo; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.DeviceUuidFactory; +import com.yizhuan.xchat_android_library.utils.TextWatcherWrapper; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; + +/** + * @author zhouxiangfeng + * @date 17/2/26 + */ +public class LoginActivity extends BaseActivity implements View.OnClickListener { + + private static final String TAG = "LoginActivity"; + + private static final String KICK_OUT = "KICK_OUT"; + + /** + * 基本权限管理 + */ + private final String[] BASIC_PERMISSIONS = new String[]{ + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, +// Manifest.permission.CAMERA, +// Manifest.permission.RECORD_AUDIO, +// Manifest.permission.ACCESS_COARSE_LOCATION, +// Manifest.permission.ACCESS_FINE_LOCATION + }; + + private EditText accountEt; + private EditText passwordEt; + private ImageView wxLogin; + private ImageView qqLogin; + private Button btnLogin; + private TextView tvLoginTip; + private EditText codeEditText; + private Button getCodeButton; +// private volatile boolean isCheckingState = false; + + private TextView tvProtocol; + + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault()); + private AccountValidator accountValidator = new AccountValidator(); + private SMSCodeValidator smsCodeValidator = new SMSCodeValidator(); + private CodeDownTimer timer; + private TextWatcher textWatcher = new TextWatcherWrapper() { + @Override + public void afterTextChanged(Editable s) { + checkInput(); + } + }; + private TextView tvDesc; + private boolean isSuperAdmin = false; + + public static void start(Context context) { + Intent intent = new Intent(context, LoginActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + onFindViews(); + onSetListener(); + permission(); + showLoginTip(); + EventBus.getDefault().register(this); + AuthModel.get().isFromLogin = true; + AppUpgradeHelper.checkAppUpgrade(this); + } + + @Override + protected void setStatusBar() { +// super.setStatusBar(); + StatusBarLightModes(true); + } + + private void permission() { + checkPermission(() -> { + InitialModel.get().reportBaiduAdv().subscribe(); + }, + R.string.ask_again, + BASIC_PERMISSIONS); + } + + private void onFindViews() { + accountEt = findViewById(R.id.et_account); + passwordEt = findViewById(R.id.et_password); + tvProtocol = (TextView) findViewById(R.id.tv_protocol); + wxLogin = (ImageView) findViewById(R.id.img_wx_login); + qqLogin = (ImageView) findViewById(R.id.img_qq_login); + tvLoginTip = (TextView) findViewById(R.id.tv_login_tip); + codeEditText = findViewById(R.id.et_code); + getCodeButton = findViewById(R.id.btn_get_code); + tvDesc = findViewById(R.id.tv_desc); + + String privacyAgreementTip = context.getString(R.string.tip_privacy_agreement); + String userAgreementTip = context.getString(R.string.tip_user_agreement); + String privacyAgreementDescTip = context.getString(R.string.text_login_protocol, privacyAgreementTip, userAgreementTip); + SpannableString ss = new SpannableString(privacyAgreementDescTip); + int privacyAgreementTipIndex = privacyAgreementDescTip.indexOf(privacyAgreementTip); + int userAgreementTipIndex = privacyAgreementDescTip.indexOf(userAgreementTip); + + + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.design_color)), privacyAgreementTipIndex, privacyAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(context, R.color.design_color)) { + @Override + public void onClick(@NonNull View widget) { + if (widget instanceof TextView) + ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); + + CommonWebViewActivity.start(context, UriProvider.getPrivacyAgreement()); + } + }, privacyAgreementTipIndex, privacyAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.design_color)), userAgreementTipIndex, userAgreementTipIndex + userAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new OriginalDrawStatusClickSpan(ContextCompat.getColor(context, R.color.design_color)) { + @Override + public void onClick(@NonNull View widget) { + if (widget instanceof TextView) + ((TextView) widget).setHighlightColor(getResources().getColor(android.R.color.transparent)); + + CommonWebViewActivity.start(context, UriProvider.getUserProtocolUrl()); + } + }, userAgreementTipIndex, userAgreementTipIndex + privacyAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvProtocol.setText(ss); + tvProtocol.setHighlightColor(Color.TRANSPARENT); + tvProtocol.setMovementMethod(new LinkMovementMethod()); + + +// initOldAccount(); + + codeEditText.setVisibility(View.GONE); + getCodeButton.setVisibility(View.GONE); + } + +// private void initOldAccount() { +// String howLogin = context.getString(R.string.tip_login_how_login); +// String content = context.getString(R.string.tip_login_old_account, context.getString(R.string.old_app_name), context.getString(R.string.app_name),howLogin); +// SpannableString ss = new SpannableString(content); +// int howLoginIndex = content.indexOf(howLogin); +// +// +// ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.design_color)), howLoginIndex, howLoginIndex + howLogin.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); +// ss.setSpan(new OriginalDrawStatusClickSpan() { +// @Override +// public void onClick(@NonNull View widget) { +// CommonWebViewActivity.start(context, UriProvider.getPrivacyAgreement()); +// } +// }, howLoginIndex, howLoginIndex + howLogin.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); +// +// tvDesc.setText(ss); +// tvDesc.setMovementMethod(new LinkMovementMethod()); +// } + + + private void onSetListener() { + btnLogin = findViewById(R.id.btn_login); + btnLogin.setOnClickListener(this); + btnLogin.setEnabled(false); + findViewById(R.id.btn_register).setOnClickListener(this); + findViewById(R.id.btn_forget).setOnClickListener(this); + wxLogin.setOnClickListener(this); + qqLogin.setOnClickListener(this); +// tvDesc.setOnClickListener(this); +// tvLoginTip.setOnClickListener(this); +// tvProtocol.setOnClickListener(this); + + accountEt.addTextChangedListener(textWatcher); + passwordEt.addTextChangedListener(textWatcher); + codeEditText.addTextChangedListener(textWatcher); + + getCodeButton.setOnClickListener(this); + } + + private void checkInput() { + if (!TextUtils.isEmpty(accountEt.getText().toString()) + && !TextUtils.isEmpty(passwordEt.getText().toString())) { + if (codeEditText.getVisibility() == View.VISIBLE) { + if (!smsCodeValidator.isValid(codeEditText.getText().toString())) { + toast(smsCodeValidator.getErrorMessage()); + btnLogin.setEnabled(false); + } else { + btnLogin.setEnabled(true); + } + } else { + btnLogin.setEnabled(true); + } + } else { + btnLogin.setEnabled(false); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + moveTaskToBack(true); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onClick(View v) { + // 易盾保护 token + String yiDunToken = watchman.getToken(XChatConstants.YI_DUN_BUSINESS_ID); + // 易盾保护 token 登录 + String yiDunLoginToken = watchman.getToken(XChatConstants.YI_DUN_LOGIN_BUSINESS_ID); + // 数美天网 deviceId + String shuMeiDeviceId = SmAntiFraud.getDeviceId(); + switch (v.getId()) { + case R.id.btn_login: + if (!accountValidator.isValid(accountEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + final String account = accountEt.getText().toString().toLowerCase(); + + final String password = passwordEt.getText().toString(); + + if (codeEditText.getVisibility() == View.VISIBLE && + !smsCodeValidator.isValid(codeEditText.getText().toString())) { + toast(smsCodeValidator.getErrorMessage()); + return; + } + String smsCode = codeEditText.getText().toString(); + + KeyBoardUtils.hideKeyBoard(this, accountEt); + KeyBoardUtils.hideKeyBoard(this, passwordEt); + getDialogManager().showProgressDialog(this, "正在登录..."); + AuthModel.get().login( + account, + password, + smsCode, + yiDunLoginToken, + shuMeiDeviceId) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + dealWithLoginError(e); + } + }); + + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_PHONE_CLICK, "点击手机号登录", null); + break; + case R.id.btn_register: + UIHelper.showRegisterAct(LoginActivity.this); + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_PHONE_REGISTER_CLICK, "手机立即注册按钮", null); + break; + case R.id.btn_forget: + UIHelper.showForgetPswAct(LoginActivity.this); + break; + + case R.id.img_wx_login: + getDialogManager().showProgressDialog(this, "请稍后"); + AuthModel.get() + .wxLogin(yiDunToken, shuMeiDeviceId) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + dealWithLoginError(e); + } + }); + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_WX_CLICK, "点击微信登录", null); + break; + case R.id.img_qq_login: + getDialogManager().showProgressDialog(this, "请稍后"); + AuthModel.get() + .qqLogin(yiDunToken, shuMeiDeviceId) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + dealWithLoginError(e); + } + }); + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_QQ_CLICK, "点击qq登录", null); +// } else { +// QQLoginSelectMemberTypeActivity.start(this); +// } + break; + +// case R.id.tv_desc: +// case R.id.tv_login_tip: +// CommonWebViewActivity.start(this, UriProvider.JAVA_WEB_URL + XChatConstants.LOGIN_ERBAN_ACCOUNT_URL); +// break; + case R.id.tv_protocol: + CommonWebViewActivity.start(this, UriProvider.getUserProtocolUrl()); + break; + + case R.id.btn_get_code: + getSmsCode(); + break; + default: + + } + } + + private void dealWithLoginError(Throwable e) { + if (!(e instanceof IsSuperAdminException)) { + String msg = e.getMessage(); + StringBuilder eventLabel = new StringBuilder("登录注册页-登录失败"); + if (!TextUtils.isEmpty(msg)) { + eventLabel.append(msg); + } + // 2004可以完整写入 + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_LOGIN_FAILED_CLICK, eventLabel.toString()); + } + if (e instanceof BanAccountException) { + isSuperAdmin = false; + BanAccountException exception = (BanAccountException) e; + String text = "您的账号因" + exception.getMessage() + "被封禁\n解封时间:"; + int start = text.length(); + text += simpleDateFormat.format(new Date(exception.getDate())); + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(LoginActivity.this, R.color.appColor)), + start, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + getDialogManager().showOkCancelWithTitleDialog("您被封号了", + spannableString, "确定", "取消", null); + } else if (e instanceof ShowPhoneCodeException) { + isSuperAdmin = false; + ShowPhoneCodeException showPhoneCodeException = (ShowPhoneCodeException) e; + boolean isShowPhoneCode = showPhoneCodeException.isShowPhoneCode(); + if (isShowPhoneCode) { + // 需要显示验证码 + if (codeEditText.getVisibility() == View.GONE) { + codeEditText.setVisibility(View.VISIBLE); + getCodeButton.setVisibility(View.VISIBLE); + btnLogin.setEnabled(false); + } + } + toast(e.getMessage()); + } else if (e instanceof IsSuperAdminException) { + isSuperAdmin = true; + // 需要显示验证码 + if (codeEditText.getVisibility() == View.GONE) { + codeEditText.setVisibility(View.VISIBLE); + getCodeButton.setVisibility(View.VISIBLE); + btnLogin.setEnabled(false); + }else { + stopCountDownTimer(); + getCodeButton.setText("重新获取"); + getCodeButton.setClickable(true);//重新获得点击 + getCodeButton.setTextColor(getCodeButton.getResources().getColor(R.color.appColor)); //还原背景色 + btnLogin.setEnabled(false); + } + toast(e.getMessage()); + } else { + isSuperAdmin = false; + toast(e.getMessage()); + } + } + + /** + * 获取验证码 + */ + @SuppressLint("CheckResult") + private void getSmsCode() { + getCodeButton.setText("获取中.."); + String deviceId = DeviceUuidFactory.getDeviceId(this); + if (isSuperAdmin) { + CodeModel.get() + .sendCode(accountEt.getEditableText().toString(), CodeType.SUPER_ADMIN) + .observeOn(AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + startCountDownTimer(); + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + Logger.e(TAG, "获取短信失败!"); + } + }); + }else { + AuthModel.get() + .sendLoginCode(accountEt.getEditableText().toString(), deviceId) + .observeOn(AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + startCountDownTimer(); + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + Logger.e(TAG, "获取短信失败!"); + } + }); + } + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(getCodeButton, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + + @Override + protected void onDestroy() { + accountEt = null; + passwordEt = null; + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + /** + * 注册成功后发送过来的事件 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginEvent(LoginEvent event) { + getDialogManager().dismissDialog(); + finish(); + } + + @SuppressLint("CheckResult") + private void showLoginTip() { + MarketVerifyModel.get().loadLoginTip() + .compose(bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(LoginTipsInfo loginTipsInfo, Throwable throwable) throws Exception { + if (throwable == null) { + String tips = loginTipsInfo.getTips(); + + if (!TextUtils.isEmpty(tips)) { + SpannableStringBuilder builder = new SpannableStringBuilder(tips); + int start = tips.indexOf("如何登录"); + + if (start > -1) { + builder.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.color_FE4C62)), start, start + 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + builder.setSpan(new OriginalDrawStatusClickSpan() { + @Override + public void onClick(@NonNull View widget) { + CommonWebViewActivity.start(LoginActivity.this, UriProvider.JAVA_WEB_URL + XChatConstants.LOGIN_ERBAN_ACCOUNT_URL); + } + }, start, start + 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + } + + + tvDesc.setText(builder); + tvDesc.setHighlightColor(Color.TRANSPARENT); + tvDesc.setMovementMethod(new LinkMovementMethod()); + + } else { +// isCheckingState = true; + } + + tvLoginTip.setVisibility(loginTipsInfo.isShowWechat() || loginTipsInfo.isShowQq() ? View.VISIBLE : View.GONE); + wxLogin.setVisibility(loginTipsInfo.isShowWechat() ? View.VISIBLE : View.GONE); + qqLogin.setVisibility(loginTipsInfo.isShowQq() ? View.VISIBLE : View.GONE); + + } else { + tvLoginTip.setVisibility(View.GONE); + wxLogin.setVisibility(View.GONE); + qqLogin.setVisibility(View.GONE); + + } + } + }); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + View view = getCurrentFocus(); + boolean isPressEdit = false; + if (view instanceof EditText) { + if (event.getRawX() >= view.getX() && event.getRawX() <= view.getX() + view.getWidth() && event.getRawY() >= view.getY() && event.getRawY() <= view.getY() + view.getHeight()) { + isPressEdit = true; + } + } + if (!isPressEdit) { + hideIME(); + } + return super.onTouchEvent(event); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/ModifyInfoActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/ModifyInfoActivity.java new file mode 100644 index 000000000..7ddb16229 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/ModifyInfoActivity.java @@ -0,0 +1,182 @@ +package com.yizhuan.erban.ui.login; + +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.Snackbar; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + * Created by zhouxiangfeng on 2017/5/13. + */ + +public class ModifyInfoActivity extends BaseActivity implements View.OnClickListener{ + public static final int CONTENT_MODIFY = 1; + public static final int NICK_MODIFY = 2; + public static final String MODIFY_TYPE = "modify_type"; + private int modifyType = CONTENT_MODIFY; + + private EditText etEditText; + private RelativeLayout rlContentGroup; + + private EditText etEditTextNick; + private RelativeLayout rlNickGroup; + + private TextView tvCountDown; + + public static final String CONTENT = "content"; + public static final String CONTENT_NICK = "contentNick"; + private CoordinatorLayout layout_coordinator; + + TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + + int subCount = 0; + if (modifyType == CONTENT_MODIFY) + subCount = 60 - s.length(); + else if (modifyType == NICK_MODIFY) + subCount = 15 - s.length(); + + tvCountDown.setText(String.valueOf(subCount)); + + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_modify_info); + onFindViews(); + onSetListener(); + init(); + initData(); + } + + private void initData() { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + if (modifyType == CONTENT_MODIFY) { + etEditText.setText(userInfo.getUserDesc()); + } else if (modifyType == NICK_MODIFY){ + etEditTextNick.setText(userInfo.getNick()); + } + } + } + + private void init() { + modifyType = getIntent().getIntExtra(MODIFY_TYPE, CONTENT_MODIFY); + + if (modifyType == CONTENT_MODIFY) { + etEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(60)}); + etEditText.addTextChangedListener(textWatcher); + rlNickGroup.setVisibility(View.GONE); + initTitleBar("修改个人介绍"); + + } else if (modifyType == NICK_MODIFY) { + rlNickGroup.setVisibility(View.VISIBLE); + rlContentGroup.setVisibility(View.GONE); + etEditTextNick.setFilters(new InputFilter[]{new InputFilter.LengthFilter(15)}); + etEditTextNick.addTextChangedListener(textWatcher); + initTitleBar("修改昵称"); + + } else + initTitleBar(""); + + } + + @Override + public void initTitleBar(String title) { + super.initTitleBar(title); + TitleBar titleBar = findViewById(R.id.title_bar); + titleBar.setActionTextColor(R.color.text_color_primary); + titleBar.addAction(new TitleBar.TextAction(getString(R.string.label_modify_info_confirm)) { + @Override + public void performAction(View view) { + + // 个人简介允许为空,nick不能为空 + if (modifyType == CONTENT_MODIFY) { + String content = etEditText.getText().toString(); + Intent intent = new Intent(); + intent.putExtra(CONTENT, content); + setResult(RESULT_OK, intent); + finish(); + + } else if (modifyType == NICK_MODIFY) { + String contentNick = etEditTextNick.getText().toString(); + + if (!contentNick.trim().isEmpty()) { + Intent intent = new Intent(); + intent.putExtra(CONTENT_NICK, contentNick); + setResult(RESULT_OK, intent); + finish(); + } else { + Snackbar.make(layout_coordinator, "所填内容为空!", Snackbar.LENGTH_SHORT).show(); + } + } + + } + }); + } + + private void onSetListener() { + findViewById(R.id.iv_nick_delete).setOnClickListener(this); + findViewById(R.id.iv_content_delete).setOnClickListener(this); + } + + private void onFindViews() { + + etEditText = findViewById(R.id.et_content); + rlContentGroup = findViewById(R.id.rl_content_group); + + etEditTextNick = findViewById(R.id.et_content_nick); + rlNickGroup = findViewById(R.id.rl_nick_group); + + tvCountDown = findViewById(R.id.tv_count_down); + + layout_coordinator = findViewById(R.id.layout_coordinator); + } + + public boolean isValid() { + return etEditText.length() > 60; + } + + @Override + public void onClick(View v) { + + switch (v.getId()) { + case R.id.iv_nick_delete: + etEditTextNick.setText(""); + break; + + case R.id.iv_content_delete: + etEditText.setText(""); + break; + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/PasswordValidator.java b/app/src/main/java/com/yizhuan/erban/ui/login/PasswordValidator.java new file mode 100644 index 000000000..9c9b57d0d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/PasswordValidator.java @@ -0,0 +1,73 @@ +package com.yizhuan.erban.ui.login; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by zhouxiangfeng on 2017/5/3. + */ + +public class PasswordValidator { + + // private static final String REG = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,15}$"; +// [a-z_A-Z0-9-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'<>~\·`\?:;|] + private static final String REG = "^(?![0-9]+$)(?![a-zA-Z]+$)[a-z_A-Z0-9-\\.!@#\\$%\\\\\\^&\\*\\)\\(\\+=\\{\\}\\[\\]\\/\",'<>~\\·`\\?:;|]{6,16}$"; +// private static final String REG = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z,.?!':@;\"/()-_=+]{6,15}$"; + + private String errorMessage; + + public PasswordValidator() { + } + + public PasswordValidator(@NonNull String errorMessage) { + this.errorMessage = errorMessage; + } + + public boolean isValid(@NonNull String text) { + if (!TextUtils.isEmpty(text)) { + if (16 >= text.length() && text.length() >= 6) { + if (checkPwdFormat(text)) { + return true; + } else { + errorMessage = "密码同时需要是字母,数字的组合哦!"; + return false; + } + } else { + errorMessage = "密码长度6-16个字符"; + return false; + } + } else { + errorMessage = "密码不能为空!"; + } + return false; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + + + /** + * 检查密码是否同时包含数字和字母 + * + * @param psw + * @return + */ + public static boolean checkPwdFormat(String psw) { + if (psw == null || psw.isEmpty()) { + return false; + } + Pattern p = Pattern.compile(REG); + Matcher m = p.matcher(psw); + return m.matches(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/QQLoginSelectMemberTypeActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/QQLoginSelectMemberTypeActivity.java new file mode 100644 index 000000000..8253189a8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/QQLoginSelectMemberTypeActivity.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.ui.login; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.view.View; + +import com.ishumei.smantifraud.SmAntiFraud; +import com.netease.mobsec.rjsb.watchman; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityQqLoginSelectMemberTypeBinding; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.exception.BanAccountException; +import com.yizhuan.xchat_android_core.auth.exception.OldMemberException; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.activity_qq_login_select_member_type) +public class QQLoginSelectMemberTypeActivity extends BaseBindingActivity { + + private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault()); + + public static void start(Context context) { + context.startActivity(new Intent(context, QQLoginSelectMemberTypeActivity.class)); + } + + @Override + protected void init() { + mBinding.setClick(this); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.tv_erban_member: + getDialogManager().showProgressDialog(this, "请稍后"); + // 易盾保护 token + String token = watchman.getToken(XChatConstants.YI_DUN_BUSINESS_ID); + // 数美天网 deviceId + String shuMeiDeviceId = SmAntiFraud.getDeviceId(); + AuthModel.get() + .qqLoginForErbanOldMember(token, shuMeiDeviceId) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + if (e instanceof OldMemberException) { + OldMemberException exception = (OldMemberException) e; + ErbanQQMemberBindAndLoginActivity.start(QQLoginSelectMemberTypeActivity.this, ((OldMemberException) e).getOpenid()); + finish(); + } else { + dealWithLoginError(e); + } + } + }); + break; + + case R.id.tv_tutu_member: + getDialogManager().showProgressDialog(this, "请稍后"); + // 易盾保护 token + String tokenForQQ = watchman.getToken(XChatConstants.YI_DUN_BUSINESS_ID); + // 数美天网 deviceId + String shuMeiDeviceIdForQQ = SmAntiFraud.getDeviceId(); + AuthModel.get() + .qqLogin(tokenForQQ, shuMeiDeviceIdForQQ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + dealWithLoginError(e); + } + }); + StatisticManager.Instance().onEvent(this, + StatisticsProtocol.Event.EVENT_LOGIN_QQ_CLICK, "点击qq登录", null); + break; + } + } + + private void dealWithLoginError(Throwable e) { + if (e instanceof BanAccountException) { + BanAccountException exception = (BanAccountException) e; + String text = "您的账号因" + exception.getMessage() + "被封禁\n解封时间:"; + int start = text.length(); + text += simpleDateFormat.format(new Date(exception.getDate())); + SpannableString spannableString = new SpannableString(text); + spannableString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(QQLoginSelectMemberTypeActivity.this, R.color.appColor)), + start, text.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + getDialogManager().showOkCancelWithTitleDialog("您被封号了", + spannableString, "确定", "取消", null); + } else { + toast(e.getMessage()); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/RegisterActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/RegisterActivity.java new file mode 100644 index 000000000..8c5fc3d97 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/RegisterActivity.java @@ -0,0 +1,383 @@ +package com.yizhuan.erban.ui.login; + +import android.annotation.SuppressLint; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.ishumei.smantifraud.SmAntiFraud; +import com.netease.mobsec.rjsb.watchman; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.orhanobut.logger.Logger; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.exception.FailReasonException; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; + +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; + +/** + * Created by zhouxiangfeng on 17/3/5. + */ + +public class RegisterActivity extends BaseActivity implements View.OnClickListener { + + + private static final String TAG = "RegisterActivity"; + private ImageView ivBack; + private EditText phoneEt; + private Button getCodeBtn; + private EditText pswEt; + + private EditText codeEt; + private Button btnRegister; + private TextView tvProtocol; + + private String phone; + private String psw; + + private ImageView ivGetRegisterCode; + private ImageView btnGetRegisterCode; + private ImageView registerCodeRefresh; + private EditText registerCode; + + private AccountValidator accountValidator = new AccountValidator(); + private PasswordValidator passwordValidator = new PasswordValidator(); + private SMSCodeValidator smsCodeValidator = new SMSCodeValidator(); + private CodeDownTimer timer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_register); + onFindViews(); + onSetListener(); + } + + @SuppressLint("CheckResult") + public void onFindViews() { + ivBack = findViewById(R.id.iv_back); + phoneEt = findViewById(R.id.et_phone); + pswEt = findViewById(R.id.et_password); + codeEt = findViewById(R.id.et_code); + getCodeBtn = findViewById(R.id.btn_get_code); + btnRegister = findViewById(R.id.btn_register); + tvProtocol = findViewById(R.id.tv_protocol); + + String userAgreementTip = "《轻寻用户协议》"; + String privacyAgreementDescTip = context.getString(R.string.text_login_protocol_2, userAgreementTip); + SpannableString ss = new SpannableString(privacyAgreementDescTip); + int userAgreementTipIndex = privacyAgreementDescTip.indexOf(userAgreementTip); + + ss.setSpan(new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + CommonWebViewActivity.start(context, UriProvider.getUserProtocolUrl()); + } + }, userAgreementTipIndex, userAgreementTipIndex + userAgreementTip.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + ss.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, R.color.design_color)), + userAgreementTipIndex, userAgreementTipIndex + userAgreementTip.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + + tvProtocol.setText(ss); + tvProtocol.setMovementMethod(new LinkMovementMethod()); + + ivGetRegisterCode = findViewById(R.id.iv_get_register_code); + btnGetRegisterCode = findViewById(R.id.btn_get_register_code); + registerCode = findViewById(R.id.et_register_code); + registerCodeRefresh = findViewById(R.id.iv_register_code_refresh); + ivGetRegisterCode.setVisibility(InitialModel.get().isCaptchaSwitch() ? View.VISIBLE : View.GONE); + btnGetRegisterCode.setVisibility(InitialModel.get().isCaptchaSwitch() ? View.VISIBLE : View.GONE); + registerCode.setVisibility(InitialModel.get().isCaptchaSwitch() ? View.VISIBLE : View.GONE); + registerCodeRefresh.setVisibility(InitialModel.get().isCaptchaSwitch() ? View.VISIBLE : View.GONE); + } + + public void onSetListener() { + ivBack.setOnClickListener(this); + btnRegister.setOnClickListener(this); + getCodeBtn.setOnClickListener(this); +// tvProtocol.setOnClickListener(this); + + phoneEt.addTextChangedListener(new CheckInputTextWatcher()); + pswEt.addTextChangedListener(new CheckInputTextWatcher()); + codeEt.addTextChangedListener(new CheckInputTextWatcher()); + + btnGetRegisterCode.setOnClickListener(this); + ivGetRegisterCode.setOnClickListener(this); + registerCodeRefresh.setOnClickListener(this); + registerCode.addTextChangedListener(new CheckInputTextWatcher()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDialogManager().dismissDialog(); + stopCountDownTimer(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_register: + // 校验账号 + if (!accountValidator.isValidToRegister(phoneEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + phone = phoneEt.getText().toString(); + // 校验密码 + if (!passwordValidator.isValid(pswEt.getText().toString())) { + toast(passwordValidator.getErrorMessage()); + return; + } + psw = pswEt.getText().toString(); + // 校验短信验证码 + if (!smsCodeValidator.isValid(codeEt.getText().toString())) { + toast(smsCodeValidator.getErrorMessage()); + return; + } + String sms_code = codeEt.getText().toString(); + // 校验图片验证码 + String verificationCode = null; + if (InitialModel.get().isCaptchaSwitch()) { + if (TextUtils.isEmpty(registerCode.getText().toString())) { + toast(R.string.tips_register_verification_code_empty); + return; + } + verificationCode = registerCode.getText().toString(); + } + // 易盾保护 token + String token = watchman.getToken(XChatConstants.YI_DUN_BUSINESS_ID); + // 易盾保护 token 登录 + String yiDunLoginToken = watchman.getToken(XChatConstants.YI_DUN_LOGIN_BUSINESS_ID); + // 数美天网 deviceId + String shuMeiDeviceId = SmAntiFraud.getDeviceId(); + + getDialogManager().showProgressDialog(RegisterActivity.this, "正在注册..."); + + AuthModel.get().register(phone, sms_code, verificationCode, psw, token, shuMeiDeviceId) + .compose(bindToLifecycle()) + .flatMap(new Function>() { + @Override + public SingleSource apply(String s) throws Exception { + Logger.d(s); + return AuthModel.get().login(phone, psw, yiDunLoginToken, shuMeiDeviceId); + } + }) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + Logger.d(s); + toast("注册成功!"); + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onError(Throwable e) { + String msg = e.getMessage(); + if (!TextUtils.isEmpty(msg)) { + toast(msg); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_LOGIN_REGISTRATION_FAILED_CLICK,"登录注册页-注册失败-" + msg); + } + if (e instanceof FailReasonException) { + FailReasonException failReasonException = (FailReasonException) e; + switch (failReasonException.getCode()) { + case AuthModel.VERIFY_CODE_ERROR: + refreshRegisterVerificationCode(); + break; + } + } + getDialogManager().dismissDialog(); + } + }); + + break; + case R.id.btn_get_code: + if (!accountValidator.isValidToRegister(phoneEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + phone = phoneEt.getText().toString(); + + CodeModel.get().sendCode(phone, CodeType.REGISTER) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + startCountDownTimer(); + toast(s); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + Logger.e(TAG, "获取短信失败!"); + } + }); + + break; + case R.id.iv_back: + finish(); + break; + case R.id.tv_protocol: + CommonWebViewActivity.start(this, UriProvider.getUserProtocolUrl()); + break; + case R.id.iv_register_code_refresh: + case R.id.iv_get_register_code: + case R.id.btn_get_register_code: + refreshRegisterVerificationCode(); + break; + + default: + break; + } + } + + private void refreshRegisterVerificationCode() { + if (!accountValidator.isValidToRegister(phoneEt.getText().toString())) { + toast(accountValidator.getErrorMessage()); + return; + } + phone = phoneEt.getText().toString(); + AuthModel.get() + .getVerificationCode(phone) + .compose(RxHelper.bindActivity(this)) + .subscribe((responseBody, throwable) -> { + if (throwable == null) { + btnGetRegisterCode.setVisibility(View.GONE); + ivGetRegisterCode.setVisibility(View.VISIBLE); + registerCode.setVisibility(View.VISIBLE); + GlideApp.with(RegisterActivity.this) + .load(BitmapFactory.decodeStream(responseBody.byteStream())) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new RoundedCorners(context.getResources().getDimensionPixelOffset(R.dimen.dp_6))) + .into(ivGetRegisterCode); + } else { + toast(throwable.getMessage()); + } + }); + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(getCodeBtn, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + + /** + * 检查值是否有效 + */ + private void checkValueValid() { + String phone = phoneEt.getText().toString(); + if (TextUtils.isEmpty(phone)) { + btnRegister.setEnabled(false); + return; + } + + if (InitialModel.get().isCaptchaSwitch()) { + String registerCodeText = registerCode.getText().toString(); + if (TextUtils.isEmpty(registerCodeText)) { + btnRegister.setEnabled(false); + return; + } + } + + String code = codeEt.getText().toString(); + if (TextUtils.isEmpty(code)) { + btnRegister.setEnabled(false); + return; + } + + String password = pswEt.getText().toString(); + if (TextUtils.isEmpty(password)) { + btnRegister.setEnabled(false); + return; + } + btnRegister.setEnabled(true); + + + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + StatusBarLightModes(true); + } + + /** + * 检查值 + */ + private class CheckInputTextWatcher implements TextWatcher { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + checkValueValid(); + } + + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/SMSCodeValidator.java b/app/src/main/java/com/yizhuan/erban/ui/login/SMSCodeValidator.java new file mode 100644 index 000000000..d3cbf5f7e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/SMSCodeValidator.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.ui.login; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import com.yizhuan.xchat_android_library.utils.StringUtils; + +/** + * Created by zhouxiangfeng on 2017/5/3. + */ + +public class SMSCodeValidator { + + private String errorMessage; + + public SMSCodeValidator() { + } + + public SMSCodeValidator(@NonNull String errorMessage) { + this.errorMessage = errorMessage; + } + + private boolean isValidMobileNumber(String phone) { + if (phone == null || phone.length() != 5 ) + return false; + + if (!isAllDigits(phone)) + return false; + + return true; + } + + private boolean isAllDigits(String str) { + if (StringUtils.isEmpty(str)) return false; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c < '0' || c > '9') { + return false; + } + } + return true; + } + + public boolean isValid(@NonNull CharSequence text) { + if (!TextUtils.isEmpty(text)) { + char c = text.charAt(0); + + if (text.length() != 5) { + errorMessage = "验证码长度为5个字符"; + return false; + } + + } else { + errorMessage = "验证码不能为空!"; + return false; + } + return true; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/ShowBindPhoneActivity.java b/app/src/main/java/com/yizhuan/erban/ui/login/ShowBindPhoneActivity.java new file mode 100644 index 000000000..20d5d47ff --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/ShowBindPhoneActivity.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.ui.login; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.setting.VerifyPhoneActivity; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +public class ShowBindPhoneActivity extends BaseActivity { + + public static void start(Context context) { + Intent intent = new Intent(context, ShowBindPhoneActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_show_bind_phone); + initTitleBar("绑定手机"); + TextView tv_phone = findViewById(R.id.tv_phone); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null && !TextUtils.isEmpty(userInfo.getPhone())) { + tv_phone.setText(userInfo.getPhone()); + } + findViewById(R.id.tv_change_phone).setOnClickListener(v -> { + VerifyPhoneActivity.start(ShowBindPhoneActivity.this, false); + finish(); + } + ); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/fragment/AddUserInfoFragment.java b/app/src/main/java/com/yizhuan/erban/ui/login/fragment/AddUserInfoFragment.java new file mode 100644 index 000000000..391156795 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/fragment/AddUserInfoFragment.java @@ -0,0 +1,391 @@ +package com.yizhuan.erban.ui.login.fragment; + +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.TextInputEditText; +import android.text.InputFilter; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.fourmob.datetimepicker.date.DatePickerDialog; +import com.jph.takephoto.model.TResult; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.sleepbot.datetimepicker.time.RadialPickerLayout; +import com.sleepbot.datetimepicker.time.TimePickerDialog; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.ErbanTakePhotoActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.entity.ThirdUserInfo; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.linked.LinkedModel; +import com.yizhuan.xchat_android_core.linked.bean.LinkedInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.StringUtils; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author jack + * @Description + * @Date 2018/11/23 + */ +public class AddUserInfoFragment extends BaseFragment + implements View.OnClickListener, DatePickerDialog.OnDateSetListener, + TimePickerDialog.OnTimeSetListener, ErbanTakePhotoActivity.TakePhotoCallBack { + + private static final String TAG = "AddUserInfoFragment"; + + private CircleImageView civAvatar; + private TextInputEditText tvNick; + private TextInputEditText tvGender; + private TextInputEditText tvBirthday; + private Button okBtn; +// private TextView tvGenderMen; +// private TextView tvGenderWomen; + + private DatePickerDialog datePickerDialog; + + private String avatarUrl; + private String avatarUrlWX; + private File photoFile; + + private int gender = -1; + + AddUserInfoActivity addUserInfoActivity; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + addUserInfoActivity = (AddUserInfoActivity) activity; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_add_user_info; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + civAvatar = view.findViewById(R.id.civ_avatar); + tvNick = view.findViewById(R.id.tv_nick); + tvGender = view.findViewById(R.id.tv_gender); + tvBirthday = view.findViewById(R.id.tv_birthday); + okBtn = view.findViewById(R.id.ok_btn); +// tvGenderMen = view.findViewById(R.id.tv_gender_men); +// tvGenderWomen = view.findViewById(R.id.tv_gender_women); + } + + @Override + public void initiate() { + gender = -1; + civAvatar.setOnClickListener(this); + tvGender.setOnClickListener(this); + tvBirthday.setOnClickListener(this); + okBtn.setOnClickListener(this); +// tvGenderMen.setOnClickListener(this); +// tvGenderWomen.setOnClickListener(this); + init(); + addWXUserInfo(); + } + + + private void addWXUserInfo() { + ThirdUserInfo thirdUserInfo = AuthModel.get().getThirdUserInfo(); + if (thirdUserInfo != null) { + avatarUrlWX = thirdUserInfo.getUserIcon(); + if (thirdUserInfo.getBirth() > 0) { + tvBirthday.setText(TimeUtils.getDateTimeString(thirdUserInfo.getBirth(), "yyyy-MM-dd")); + } + String nick = thirdUserInfo.getUserName(); + if (!StringUtil.isEmpty(nick)) { + if (nick.length() > 15) { + tvNick.setText(nick.substring(0, 15)); + } else { + tvNick.setText(nick); + } + } + if (!TextUtils.isEmpty(avatarUrlWX)) { + ImageLoadUtils.loadAvatar(getContext(), avatarUrlWX, civAvatar); + } + } + } + + private void init() { + tvNick.setFilters(new InputFilter[]{new InputFilter.LengthFilter(15)}); + Calendar calendar = Calendar.getInstance(); + int year = calendar.get(Calendar.YEAR) - 18; + datePickerDialog = DatePickerDialog.newInstance(this, year, 0, 1, true); + // 给一个默认的生日值 + // 默认给够 18 岁 + tvBirthday.setText(String.format(Locale.getDefault(), "%d-01-01", year)); + // 设置默认昵称 + tvNick.setText(R.string.text_default_nick); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_gender: + ButtonItem maleItem = new ButtonItem("男", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + gender = UserInfo.GENDER_MALE; + tvGender.setText("男"); + } + }); + + ButtonItem femaleItem = new ButtonItem("女", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + gender = UserInfo.GENDER_FEMALE; + tvGender.setText("女"); + } + }); + + List genderList = new ArrayList<>(); + genderList.add(maleItem); + genderList.add(femaleItem); + getDialogManager().showCommonPopupDialog(genderList, "取消", false); + break; + + case R.id.tv_birthday: + if (datePickerDialog.isAdded()) { + datePickerDialog.dismiss(); + } else { + Calendar calendar = Calendar.getInstance(); + datePickerDialog.setVibrate(true); + datePickerDialog.setYearRange(1945, calendar.get(Calendar.YEAR) - 18); + datePickerDialog.show(getChildFragmentManager(), "DATEPICKER_TAG"); + } + break; + + case R.id.ok_btn: + String nick = tvNick.getText().toString(); + if (TextUtils.isEmpty(nick)) { + toast("昵称不能为空!"); + return; + } + + String birth = tvBirthday.getText().toString(); + if (TextUtils.isEmpty(birth)) { + toast("生日不能为空!"); + return; + } + + if (gender == -1) { + toast("必须要选性别哦"); + return; + } + + if (photoFile != null) { + getDialogManager().showProgressDialog(getContext(), "正在上传请稍后..."); + FileModel.get() + .uploadFile(photoFile.getAbsolutePath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + return; + } + + //用户如果自己拍照作为头像就上传,如果为空就代表没拍照,直接拿微信头像上传 +// avatarUrl = avatarUrlWX; + if (avatarUrlWX != null) { + avatarUrl = avatarUrlWX; + } + if (StringUtils.isEmpty(avatarUrl)) { + avatarUrl = "https://img.erbanyy.com/qingxun_default_avatar.png"; + } + commit(); + break; + case R.id.civ_avatar: + ButtonItem upItem = new ButtonItem("拍照上传", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + ErbanTakePhotoActivity.startToTakePhoto(getContext(), AddUserInfoFragment.this); + } + }); + + ButtonItem localItem = new ButtonItem("本地相册", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + ErbanTakePhotoActivity.startToSelectPhoto(getContext(), AddUserInfoFragment.this); + + } + }); + List buttonItemList = new ArrayList<>(); + buttonItemList.add(upItem); + buttonItemList.add(localItem); + getDialogManager().showCommonPopupDialog(buttonItemList, "取消", false); + break; + default: + +// case R.id.tv_gender_men: +// tvGenderMen.setSelected(!tvGenderMen.isSelected()); +// if (tvGenderMen.isSelected()) { +// gender = UserInfo.GENDER_MALE; +// tvGenderWomen.setSelected(false); +// } else { +// gender = -1; +// } +// break; +// +// case R.id.tv_gender_women: +// tvGenderWomen.setSelected(!tvGenderWomen.isSelected()); +// if (tvGenderWomen.isSelected()) { +// gender = UserInfo.GENDER_FEMALE; +// tvGenderMen.setSelected(false); +// } else { +// gender = -1; +// } + break; + } + } + + private void commit() { + String nick = tvNick.getText().toString(); + String birth = tvBirthday.getText().toString(); + + UserInfo userInfo = new UserInfo(); + userInfo.setUid(AuthModel.get().getCurrentUid()); + userInfo.setBirthStr(birth); + userInfo.setNick(nick); + userInfo.setAvatar(avatarUrl); + + if (gender == UserInfo.GENDER_MALE || gender == UserInfo.GENDER_FEMALE) { + userInfo.setGender(gender); + }else { + toast("必须要选性别哦"); + return; + } + + getDialogManager().showProgressDialog(getContext(), "请稍后..."); + LinkedInfo linkedInfo = LinkedModel.get().getLinkedInfo(); + + String channel = ""; + String roomUid = ""; + String uid = ""; + if (linkedInfo != null) { + channel = linkedInfo.getChannel(); + roomUid = linkedInfo.getRoomUid(); + uid = linkedInfo.getUid(); + } + UserModel.get().requestCompleteUserInfo(userInfo, channel, uid, roomUid, null) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(UserInfo userInfo) { + getDialogManager().dismissDialog(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_COMPLETE,"注册完成(提交个人资料)"); + AuthModel.get().setThirdUserInfo(null); + getActivity().finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + + Map attributes = new HashMap<>(4); + attributes.put("userUid", userInfo.getUid() + ""); + attributes.put("shareChannel", channel); + attributes.put("shareUid", uid); + attributes.put("roomUid", roomUid); + StatisticManager.Instance().onEvent(getContext(), + StatisticsProtocol.Event.EVENT_LOGIN_REPARI_SUCCESS_CLICK, "补全", attributes); + } + + + @Override + public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) { + String monthstr; + if ((month + 1) < 10) { + monthstr = "0" + (month + 1); + } else { + monthstr = String.valueOf(month + 1); + } + String daystr; + if (day < 10) { + daystr = "0" + day; + } else { + daystr = String.valueOf(day); + } + tvBirthday.setText(String.valueOf(year) + "-" + monthstr + "-" + daystr); + } + + @Override + public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) { + + } + + + public void onUpload(String url) { + Log.d(TAG, "onUpload: 这是添加用户更改上传"); + avatarUrl = url; + getDialogManager().dismissDialog(); + ImageLoadUtils.loadAvatar(getContext(), url, civAvatar); + commit(); + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + + @Override + public void takeSuccess(TResult result) { + photoFile = new File(result.getImage().getCompressPath()); + if (getContext() != null) { + ImageLoadUtils.loadImage(getContext(), photoFile, civAvatar, R.drawable.tutu_default_avatar_purple); + } + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + @Override + public void takeCancel() { + + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/fragment/GenderSelectFragment.java b/app/src/main/java/com/yizhuan/erban/ui/login/fragment/GenderSelectFragment.java new file mode 100644 index 000000000..cac7b0f82 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/fragment/GenderSelectFragment.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.ui.login.fragment; + +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.ui.login.AddUserInfoActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.auth.entity.ThirdUserInfo; + +/** + * @author jack + * @Description + * @Date 2018/11/23 + */ +@Deprecated +public class GenderSelectFragment extends BaseFragment implements View.OnClickListener { + + private TextView tvGenderMen; + private TextView tvGenderWomen; + private Button btnNext; + + AddUserInfoActivity addUserInfoActivity; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + addUserInfoActivity = (AddUserInfoActivity) activity; + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_gender_select; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + tvGenderMen = (TextView) view.findViewById(R.id.tv_gender_men); + tvGenderWomen = (TextView) view.findViewById(R.id.tv_gender_women); + btnNext = (Button) view.findViewById(R.id.btn_next); + } + + @Override + public void initiate() { + tvGenderMen.setOnClickListener(this); + tvGenderWomen.setOnClickListener(this); + btnNext.setOnClickListener(this); + btnNext.setEnabled(false); + + addWXUserInfo(); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvGenderMen.getId()) { + tvGenderMen.setBackgroundResource(R.mipmap.ic_gender_men_selected); + tvGenderWomen.setBackgroundResource(R.mipmap.ic_gender_women_unselected); + btnNext.setEnabled(true); + } else if (id == tvGenderWomen.getId()) { + tvGenderMen.setBackgroundResource(R.mipmap.ic_gender_men_unselected); + tvGenderWomen.setBackgroundResource(R.mipmap.ic_gender_women_selected); + btnNext.setEnabled(true); + } else if (id == btnNext.getId()) { + addUserInfoActivity.showAddUserInfo(); + } + } + + private void addWXUserInfo() { + ThirdUserInfo thirdUserInfo = AuthModel.get().getThirdUserInfo(); + if (thirdUserInfo != null) { + if (!StringUtil.isEmpty(thirdUserInfo.getUserGender())) { + if (thirdUserInfo.getUserGender().equals("m")) { + onClick(tvGenderMen); + } else { + onClick(tvGenderWomen); + } + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/helper/LogoutHelper.java b/app/src/main/java/com/yizhuan/erban/ui/login/helper/LogoutHelper.java new file mode 100644 index 000000000..6e36d6067 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/helper/LogoutHelper.java @@ -0,0 +1,18 @@ +package com.yizhuan.erban.ui.login.helper; + +import com.yizhuan.xchat_android_core.PreferencesUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.customer_server.CustomerServerModel; + +/** + * create by lvzebiao @2019/12/9 + */ +public class LogoutHelper { + + public static void logout() { + AuthModel.get().logout().subscribe(); + PreferencesUtils.setFristQQ(true); + CustomerServerModel.getInstance().logout(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/presenter/LoginPresenter.java b/app/src/main/java/com/yizhuan/erban/ui/login/presenter/LoginPresenter.java new file mode 100644 index 000000000..3bd10855c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/presenter/LoginPresenter.java @@ -0,0 +1,10 @@ +package com.yizhuan.erban.ui.login.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.ui.login.view.LoginView; + +public class LoginPresenter extends BaseMvpPresenter{ + + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/login/view/LoginView.java b/app/src/main/java/com/yizhuan/erban/ui/login/view/LoginView.java new file mode 100644 index 000000000..9c8c14310 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/login/view/LoginView.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.ui.login.view; + +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +public interface LoginView extends IMvpBaseView{ + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeActivity.java b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeActivity.java new file mode 100644 index 000000000..68763f1b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeActivity.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.ui.patriarch; + +import android.graphics.Paint; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityPatriarchModeBinding; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.activity_patriarch_mode) +public class PatriarchModeActivity extends BaseBindingActivity { + + @Override + protected void init() { + initTitleBar("青少年模式"); + mBinding.tvPlan.setOnClickListener(v -> CommonWebViewActivity.start(PatriarchModeActivity.this, UriProvider.IM_SERVER_URL + "/modules/rule/adult.html")); + mBinding.tvOpen.setOnClickListener(v -> start(PatriarchPwdActivity.class)); + + mBinding.tvPlan.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG); //下划线 + mBinding.tvPlan.getPaint().setAntiAlias(true);//抗锯齿 + } + + @Override + protected void onResume() { + super.onResume(); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null && userInfo.isParentMode()) { + mBinding.tvOpen.setText("关闭青少年模式"); + mBinding.tvOpen.setStrokeColor(getResources().getColor(R.color.color_B3B3B3)); + } else { + mBinding.tvOpen.setText("开启青少年模式"); + mBinding.tvOpen.setStrokeColor(getResources().getColor(R.color.color_333333)); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeDialog.java b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeDialog.java new file mode 100644 index 000000000..9601a5761 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchModeDialog.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.ui.patriarch; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseSdDialog; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * 家长模式 提醒框 + * create by lvzebiao @2019/7/27 + */ +public class PatriarchModeDialog extends BaseSdDialog { + + @BindView(R.id.tv_set_pm) + TextView tvSetPm; + @BindView(R.id.iv_close) + ImageView ivClose; + + public PatriarchModeDialog(Context context) { + super(context); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_patriarch_mode); + ButterKnife.bind(this); + setCancelable(false); + setCanceledOnTouchOutside(false); + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = UIUtil.dip2px(getContext(), 296); + windowParams.height = UIUtil.dip2px(getContext(), 277); + windowParams.dimAmount = 0.4f; + windowParams.gravity = Gravity.CENTER; + window.setAttributes(windowParams); + } + } + + @OnClick({R.id.tv_set_pm, R.id.iv_close}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.tv_set_pm: + context.startActivity(new Intent(context, PatriarchModeActivity.class)); + dismiss(); + break; + case R.id.iv_close: + dismiss(); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchPwdActivity.java b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchPwdActivity.java new file mode 100644 index 000000000..bff0eba33 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/patriarch/PatriarchPwdActivity.java @@ -0,0 +1,115 @@ +package com.yizhuan.erban.ui.patriarch; + +import android.text.Editable; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityPatriarchPwdBinding; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + + +@ActLayoutRes(R.layout.activity_patriarch_pwd) +public class PatriarchPwdActivity extends BaseBindingActivity { + private String firstPwd; + + @Override + protected void init() { + initTitleBar(""); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + toast("用户信息为空,请重新登录"); + finish(); + return; + } + + mBinding.tvClosePmTips.setVisibility(View.GONE); + if (userInfo.isParentMode()) { + mBinding.tvClosePmTips.setVisibility(View.VISIBLE); + mBinding.text.setVisibility(View.GONE); + mBinding.tvTip.setVisibility(View.GONE); + mBinding.tvCommit.setVisibility(View.GONE); + resetEditViewLocation(); + } + + mBinding.tvCommit.setOnClickListener(v -> { + if ("下一步".equals(mBinding.tvCommit.getText().toString())) { + firstPwd = mBinding.etPwd.getText().toString(); + mBinding.etPwd.setText(""); + mBinding.text.setText("再次输入密码"); + mBinding.tvTip.setText("我们将不提供找回密码服务 请您牢记已设置的密码"); + mBinding.tvCommit.setText("完成"); + } else if (firstPwd != null && !firstPwd.equals(mBinding.etPwd.getText().toString())) { + toast("两次密码不一致"); + } else { + commit(); + } + }); + mBinding.etPwd.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (s.length() == 4) { + if (mBinding.tvCommit.getVisibility() == View.GONE) { + commit(); + } else { + setCommitBtnStatus(true); + } + } else { + setCommitBtnStatus(false); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + private void commit() { + UserModel.get().openOrClosePatriarchMode( + DESAndBase64(mBinding.etPwd.getText().toString()), + UserModel.get().getCacheLoginUserInfo().isParentMode() ? 0 : 1) + .subscribe(s -> { + toast(UserModel.get().getCacheLoginUserInfo().isParentMode() ? "青少年模式已关闭" : "青少年模式已开启"); + UserModel.get().getCacheLoginUserInfo().setParentMode(!UserModel.get().getCacheLoginUserInfo().isParentMode()); + UserModel.get().getCacheLoginUserInfo().setHasSetParentPwd(true); + + finish(); + }); + } + + private void setCommitBtnStatus(boolean canClick) { + mBinding.tvCommit.setClickable(canClick); + if (canClick) { + mBinding.tvCommit.setStrokeColor(getResources().getColor(R.color.color_333333)); + mBinding.tvCommit.setTextColor(getResources().getColor(R.color.color_333333)); + } else { + mBinding.tvCommit.setStrokeColor(getResources().getColor(R.color.color_B3B3B3)); + mBinding.tvCommit.setTextColor(getResources().getColor(R.color.color_B3B3B3)); + } + } + + private void resetEditViewLocation() { + ViewGroup.LayoutParams tmp = mBinding.etPwd.getLayoutParams(); + if (tmp instanceof LinearLayout.LayoutParams) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tmp; + params.gravity = Gravity.CENTER_HORIZONTAL; + params.leftMargin = 0; + params.rightMargin = 0; + mBinding.etPwd.setLayoutParams(params); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/LimitEnterRoomHelper.java b/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/LimitEnterRoomHelper.java new file mode 100644 index 000000000..1c467add8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/LimitEnterRoomHelper.java @@ -0,0 +1,77 @@ +package com.yizhuan.erban.ui.patriarch.help; + +import android.app.Dialog; +import android.content.Context; +import android.text.TextUtils; + +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; + +/** + * 进房限制的一些处理,因为main和avroom 基本一样,所以写一起减少冗余 + * + * create by lvzebiao @2019/8/19 + */ +public class LimitEnterRoomHelper { + + /** + * 青少年限制时长的弹窗 + */ + private Dialog pmLimitTimeDialog; + + /** + * + * @param thisContext - + * @param isNeedCheckRoomInfo ture,表示需要检查房间信息是否为空 + */ + public void handleThisContext(Context thisContext, CharSequence tips, + boolean isNeedCheckRoomInfo, OnDialogClickHandle handle) { + if (TextUtils.isEmpty(tips)) { + return; + } + if (!ActivityUtil.isCanShowAppCompatDialog(thisContext)) { + return; + } + if (isNeedCheckRoomInfo) { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + return; + } + } + try { + dismissDialog(); + pmLimitTimeDialog = DialogManager.createDialog(thisContext); + pmLimitTimeDialog.show(); + DialogManager.setDialog( + pmLimitTimeDialog, "提示", tips, "确定", null, false, false, true, + () -> { + if (handle != null) { + handle.clickHandle(); + } + }, () -> { + if (handle != null) { + handle.clickHandle(); + } + }, true); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + public void release() { + dismissDialog(); + } + + public void dismissDialog() { + if (pmLimitTimeDialog != null) { + pmLimitTimeDialog.dismiss(); + pmLimitTimeDialog = null; + } + } + + public interface OnDialogClickHandle { + void clickHandle(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/PmDialogShowMrg.java b/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/PmDialogShowMrg.java new file mode 100644 index 000000000..d45777221 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/patriarch/help/PmDialogShowMrg.java @@ -0,0 +1,170 @@ +package com.yizhuan.erban.ui.patriarch.help; + +import android.content.Context; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.yizhuan.erban.ui.patriarch.PatriarchModeDialog; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import lombok.Getter; +import lombok.Setter; + +/** + * create by lvzebiao @2019/7/27 + */ +public class PmDialogShowMrg { + + private boolean hasShow; + + private final static String KEY_SAVE_PATRIARCH_MODE_STATUS = "key_save_patriarch_mode_status"; + + /** + * 家长模式引导 1-强 2- 弱 + */ + @Setter + @Getter + private int parentMode; + + private PmDialogShowMrg() { + hasShow = false; + } + + private static PmDialogShowMrg instance; + + public static PmDialogShowMrg get() { + if (instance == null) { + instance = new PmDialogShowMrg(); + } + return instance; + } + + private void show(Context context) { + if (!ActivityUtil.isValidContext(context)) { + return; + } + hasShow = true; + new PatriarchModeDialog(context).show(); + saveCache(); + } + + /** + * 延迟弹框处理 + */ + public void handle(WeakReference reference) { + Context context = reference.get(); + if (context == null) { + return; + } + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + return; + } + //开启过,就不用弹窗 + if (userInfo.isParentMode()) { + return; + } + Single.timer(15, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) + .compose(RxHelper.bindContext(context)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(Long aLong, Throwable throwable) { + super.acceptThrowable(aLong, throwable); + if (throwable == null) { + handleCode(reference); + } + } + }); + } + + private void handleCode(WeakReference reference) { + Context context = reference.get(); + if (context == null) { + return; + } + if (hasShow || !ActivityUtil.isValidContext(context)) { + return; + } + long currUid = AuthModel.get().getCurrentUid(); + if (currUid <= 0) { + return; + } + Map map = cacheToMap(); + //判断该用户,今天是不是弹窗过了 + if (map == null) { + map = new HashMap<>(); + } + //如果弱引导,并且该uid已经存在缓存中,说明弹过一次,则不用再弹窗 + if (InitialModel.get().getTeenagerMode() == 2) { + if (map.containsKey(currUid)) { + return; + } + show(context); + return; + } + long currUidTime = 0L; + if (map.containsKey(currUid)) { + Long tmp = map.get(currUid); + if (tmp != null) { + currUidTime = tmp; + } + } + if (!TimeUtils.isTomorrow(currUidTime)) { + return; + } + show(context); + } + + public void onLogout() { + hasShow = false; + } + + public static void saveCache() { + Map map = cacheToMap(); + if (map == null) { + map = new HashMap<>(); + } + if (map.size() > 20) { + map.clear(); + } + map.put(AuthModel.get().getCurrentUid(), System.currentTimeMillis()); + try { + String json = new Gson().toJson(map); + if (!TextUtils.isEmpty(json)) { + SharedPreferenceUtils.put(KEY_SAVE_PATRIARCH_MODE_STATUS, json); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static HashMap cacheToMap() { + try { + String cache = (String) SharedPreferenceUtils.get(KEY_SAVE_PATRIARCH_MODE_STATUS, ""); + if (!TextUtils.isEmpty(cache)) { + return new Gson().fromJson(cache, new TypeToken>() { + }.getType()); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/CDKEYChargeActivity.java b/app/src/main/java/com/yizhuan/erban/ui/pay/CDKEYChargeActivity.java new file mode 100644 index 000000000..291c9b756 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/CDKEYChargeActivity.java @@ -0,0 +1,84 @@ +package com.yizhuan.erban.ui.pay; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; + +import org.greenrobot.eventbus.EventBus; + +/** + * Created by chenran on 2017/11/15. + */ + +public class CDKEYChargeActivity extends BaseActivity implements View.OnClickListener { + private EditText editText; + private Button charge; + + public static void start(Context context) { + if (context == null) return; + Intent intent = new Intent(context, CDKEYChargeActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_cd_key_charge); + initTitleBar("兑换码充值"); + + editText = (EditText) findViewById(R.id.cd_key_edit); + charge = (Button) findViewById(R.id.btn_charge); + charge.setOnClickListener(this); + } + + @Override + protected int setBgColor() { + return R.color.white; + } + + @Override + public void onClick(View v) { + String text = editText.getText().toString(); + if (StringUtil.isEmpty(text)) { + toast("兑换码为空"); + return; + } + + getDialogManager().showProgressDialog(this, "请稍后"); + + PayModel.get().requestCDKeyCharge(editText.getText().toString()) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onSuccess(Integer count) { + onCDKeyCharge(count); + } + + @Override + public void onErrorMsg(String error) { + onCDKeyChargeFail(error); + } + }); + editText.setText(""); + } + + public void onCDKeyCharge(int gold) { + getDialogManager().dismissDialog(); + ChargeDialog dialog = new ChargeDialog(this, gold); + dialog.show(); + } + + public void onCDKeyChargeFail(String error) { + getDialogManager().dismissDialog(); + toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeActivity.java b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeActivity.java new file mode 100644 index 000000000..1fcf78ef7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeActivity.java @@ -0,0 +1,498 @@ +package com.yizhuan.erban.ui.pay; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.StatusBarUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bank_card.activity.AddBankCardAgreementActivity; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.activities.ChargeBillsActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.wallet.ExchangeGoldActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.password.PassWordFragment; +import com.yizhuan.erban.ui.widget.password.PasswordEvent; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.PaymentActivity; +import com.yizhuan.xchat_android_core.pay.bean.ChargeBean; +import com.yizhuan.xchat_android_core.pay.bean.PaymentResult; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.bean.unionpay.UnionPayOrder; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.model.unionpay.UnionPayModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +/** + * 充值界面 + * + * @author zhouxiangfeng + * @date 2017/6/19 + */ +public class ChargeActivity extends BaseActivity { + + private static final String TAG = "ChargeActivity"; + private ImageView mCiv_head; + private TextView mTv_name; + private TextView mTv_gold; + private LinearLayout ll_wx; + private ImageView iv_sel_wx; + private LinearLayout ll_zfb; + private ImageView iv_sel_zfb; + private TextView tvExcharge; + private TextView tvCharge; + private View layoutCdKeyCharge; + private RecyclerView mRecyclerView; + private ChargeAdapter mChargeAdapter; + private TextView mTvGoldNobleNumber; + private LinearLayout unionPayLayout; + private ImageView unionPayImage; + + private ChargeBean mSelectChargeBean; + + private volatile String payChannel = Constants.CHARGE_WX; + + private final int BINDCODE_GOLD = 200; + private boolean isBindPhone; + private CompositeDisposable compositeDisposable = new CompositeDisposable(); + + public static void start(Context context) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (context == null || userInfo == null) return; + Intent intent = new Intent(context, ChargeActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_charge); + initTitleBar(getString(R.string.label_charge_gold)); + bindViews(); + setListener(); + initiate(); + // 默认选中微信 + selectPayChannelDisplay(Constants.CHARGE_WX); + } + + private void setListener() { + ll_wx.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_WX)); + ll_zfb.setOnClickListener(v -> selectPayChannelDisplay(Constants.CHARGE_ALIPAY)); + unionPayLayout.setOnClickListener((view) -> selectPayChannelDisplay(Constants.CHARGE_UNION_PAY)); + tvExcharge.setOnClickListener(v -> { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + return; + } + + if (userInfo.isBindPhone() && userInfo.isBindPaymentPwd()) { + startActivity(new Intent(ChargeActivity.this, ExchangeGoldActivity.class)); + } else { + if (userInfo.isBindPhone() || isBindPhone) { + ModifyPwdActivity.start(ChargeActivity.this, ModifyPwdActivity.FOGERT_PAY_PWD); + } else { + startActivityForResult(new Intent(ChargeActivity.this, BinderPhoneActivity.class), BINDCODE_GOLD); + } + } + }); + tvCharge.setOnClickListener(v -> { + if (mSelectChargeBean == null) return; + getDialogManager().showProgressDialog(this, false); + PaymentActivity.start(this, payChannel, String.valueOf(mSelectChargeBean.chargeProdId)); + }); + + layoutCdKeyCharge.setOnClickListener(v -> { + ButtonItem buttonItem = new ButtonItem(getString(R.string.charge_diamond), () -> { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + return; + } + + if (userInfo.isBindPhone() && userInfo.isBindPaymentPwd()) { + startActivity(new Intent(ChargeActivity.this, ExchangeGoldActivity.class)); + } else { + if (userInfo.isBindPhone()) { + ModifyPwdActivity.start(ChargeActivity.this, ModifyPwdActivity.FOGERT_PAY_PWD); + } else { + startActivity(new Intent(ChargeActivity.this, BinderPhoneActivity.class)); + } + } + }); + ButtonItem buttonItem1 = new ButtonItem(getString(R.string.charge_cd_code), () -> CDKEYChargeActivity.start(ChargeActivity.this)); + + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, getString(R.string.cancel), false); + + }); + + } + + private void bindViews() { + mCiv_head = findViewById(R.id.civ_head); + mTv_name = findViewById(R.id.tv_name); + mTv_gold = findViewById(R.id.tv_gold); + ll_wx = findViewById(R.id.ll_wx); + iv_sel_wx = findViewById(R.id.iv_sel_wx); + ll_zfb = findViewById(R.id.ll_zfb); + iv_sel_zfb = findViewById(R.id.iv_sel_zfb); + tvExcharge = findViewById(R.id.tv_exchange); + tvCharge = findViewById(R.id.tv_charge); + layoutCdKeyCharge = findViewById(R.id.layout_cd_key_charge); + mTvGoldNobleNumber = findViewById(R.id.tv_gold_noble_number); + unionPayLayout = findViewById(R.id.ll_union_pay); + unionPayImage = findViewById(R.id.iv_sel_union_pay); + } + + public void selectPayChannelDisplay(String payChannel) { + this.payChannel = payChannel; + boolean selectWeChatPay = (Objects.equals(this.payChannel, Constants.CHARGE_WX)); + boolean selectAliPay = (Objects.equals(this.payChannel, Constants.CHARGE_ALIPAY)); + boolean selectUnionPay = (Objects.equals(this.payChannel, Constants.CHARGE_UNION_PAY)); + iv_sel_wx.setSelected(selectWeChatPay); + iv_sel_zfb.setSelected(selectAliPay); + unionPayLayout.setSelected(selectUnionPay); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void initTitleBar(String title) { + TitleBar titleBar = findViewById(R.id.title_bar); + if (titleBar != null) { + titleBar.setTitle(title); + titleBar.setImmersive(true); + titleBar.setTitleColor(getResources().getColor(R.color.black)); + titleBar.setLeftImageResource(R.drawable.arrow_left); + titleBar.setCommonBackgroundColor(getResources().getColor(R.color.color_FAFAFA)); + titleBar.setLeftClickListener(v -> finish()); + titleBar.addAction(new TitleBar.TextAction("充值记录") { + @Override + public void performAction(View view) { + startActivity(new Intent(ChargeActivity.this, ChargeBillsActivity.class)); + } + }); + } + } + + private void initiate() { + mRecyclerView = findViewById(R.id.recyclerView); + mRecyclerView.setNestedScrollingEnabled(false); + mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + mChargeAdapter = new ChargeAdapter(); + mRecyclerView.setAdapter(mChargeAdapter); + mChargeAdapter.setOnItemClickListener((baseQuickAdapter, view, position) -> { + List list = mChargeAdapter.getData(); + if (ListUtils.isListEmpty(list)) return; + + // 空对象,不让蒙板遮挡最后一个item; + ChargeBean temp = list.get(position); + if (TextUtils.isEmpty(temp.getProdName())) + return; + + mSelectChargeBean = list.get(position); + int size = list.size(); + for (int i = 0; i < size; i++) { + list.get(i).isSelected = position == i; + } + mChargeAdapter.notifyDataSetChanged(); + int money = mSelectChargeBean.getMoney(); + if (money >= 30000) { + // 大于 3w 的时候,隐藏微信支付的选项 + ll_wx.setVisibility(View.GONE); + // 默认选中支付宝支付的选项 + selectPayChannelDisplay(Constants.CHARGE_ALIPAY); + } else { + ll_wx.setVisibility(View.VISIBLE); + } + }); + onLoadingData(); + onRefreshing(); + } + + public void onLoadingData() { + UserInfo userInfos = UserModel.get().getCacheLoginUserInfo(); + if (userInfos != null) { + mTv_name.setText(getString(R.string.charge_user_name, userInfos.getNick())); + ImageLoadUtils.loadAvatar(this, userInfos.getAvatar(), mCiv_head, true); + PayModel.get().getWalletInfo(userInfos.getUid()).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(WalletInfo walletInfo) { + setWalletData(walletInfo); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + } + + public void onRefreshing() { + PayModel.get().getChargeList(1).subscribe(new BeanObserver>() { + @Override + public void onSuccess(List chargeBeans) { + onGetChargeList(chargeBeans); + } + + @Override + public void onErrorMsg(String error) { + onGetChargeListFail(error); + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + EventBus.getDefault().register(this); + } + + @Override + protected void onPause() { + super.onPause(); + EventBus.getDefault().unregister(this); + } + + public void onGetChargeList(List chargeBeanList) { + if (chargeBeanList != null && chargeBeanList.size() > 0) { + for (int i = 0; i < chargeBeanList.size(); i++) { + ChargeBean chargeBean = chargeBeanList.get(i); + chargeBean.isSelected = chargeBean.getMoney() == 48; + if (48 == chargeBean.getMoney()) { + mSelectChargeBean = chargeBean; + } + } + + ChargeBean chargeBean = new ChargeBean(0); + chargeBean.setChannel(0); + chargeBean.setChargeProdId(0); + chargeBean.setGiftGoldNum(0); + chargeBean.setProdName(""); + chargeBeanList.add(chargeBean); + + mChargeAdapter.setNewData(chargeBeanList); + } + } + + public void onGetChargeListFail(String error) { + toast(error); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + getDialogManager().dismissDialog(); + if (resultCode != RESULT_OK) { + return; + } + //支付页面返回处理 + if (requestCode == PaymentActivity.REQUEST_CODE_PAY) { + if (data != null && data.getExtras() != null) { + PaymentResult paymentResult = data.getParcelableExtra(PaymentActivity.KEY_PAY_RESULT); + if (paymentResult != null) { + // 充值金额超过限定时,就必须先实名认证 + int payResultCode = JavaUtil.str2int(paymentResult.getCode()); + switch (payResultCode) { + case PayModel.NOT_REAL_NAME_BEFORE_CHARGING: + getDialogManager().showTipsDialog(getString(R.string.tips_need_to_certification), + getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(ChargeActivity.this, + UriProvider.getTutuRealNamePage()); + } + }); + break; + + case UnionPayModel.CODE_NEED_BIND_BANK_CARD_FIRST: + getDialogManager().showTipsDialog( + getString(R.string.tips_need_bind_bank_card_first), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去添加银行卡页面 + AddBankCardAgreementActivity.start(ChargeActivity.this); + } + }); + break; + + case PaymentResult.CODE_SHOW_PAYMENT_PSW: + showPaymentConfirmDialog(); + break; + + case PaymentResult.CODE_UNION_PAY_WAITING_FOR_RESULT: + queryingPaymentResult(); + break; + + default: + toast(paymentResult.getMsg()); + //重新获取钱包信息 + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()).subscribe(); + } + } + } + } + if (requestCode == BINDCODE_GOLD) { + isBindPhone = true; + ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + /** + * 银联支付下,弹出确认弹窗,方便用户查看支付金额和支付使用的银行卡,还能切换银行卡 + */ + private void showPaymentConfirmDialog() { + if (mSelectChargeBean == null) { + return; + } + ConfirmPaymentDialog.newInstance(mSelectChargeBean.getMoney(), + selectedBankInfo -> { + UnionPayModel.getInstance().setSelectedBankInfo(selectedBankInfo); + PassWordFragment.newInstance().show(getSupportFragmentManager()); + }) + .show(getSupportFragmentManager(), ConfirmPaymentDialog.class.getName()); + } + + /** + * 银联支付存在一定的延时,所以这里加一个五秒的 loading 动画在前台, + * 后台在每秒轮询服务器获取订单状态 + * 当获取到订单状态为成功或者失败的时候,loading 结束, + * 否则一直 loading,直到五秒结束后 toast 提示用户自行查账单 + */ + private void queryingPaymentResult() { + UnionPayOrder unionPayOrder = UnionPayModel.getInstance().getUnionPayOrder(); + if (unionPayOrder == null) { + getDialogManager().dismissDialog(); + return; + } + // 前台 loading + getDialogManager().showProgressDialog(ChargeActivity.this, + getString(R.string.tips_querying_payment_result), false); + // 轮询订单支付结果 + Observable> stringObservable = + Observable.interval(0, 1, TimeUnit.SECONDS) + .take(5) + .subscribeOn(Schedulers.io()) + .concatMap(aLong -> UnionPayModel.getInstance() + .unionPayResult(unionPayOrder.getOrderNo()) + .toObservable()) + .observeOn(AndroidSchedulers.mainThread()) + .filter(pollingJsonResult -> + pollingJsonResult.getCode() == ServiceResult.SC_SUCCESS || + pollingJsonResult.getCode() == UnionPayModel.CODE_UNION_PAY_FAILED) + .timeout(5, TimeUnit.SECONDS); + compositeDisposable.add( + stringObservable.subscribe(stringServiceResult -> { + getDialogManager().dismissDialog(); + disposeCompositeDisposable(); + if (stringServiceResult != null) { + toast(stringServiceResult.getMessage()); + } + }, throwable -> { + throwable.printStackTrace(); + getDialogManager().dismissDialog(); + toast(throwable.getMessage()); + }, () -> { + getDialogManager().dismissDialog(); + toast(R.string.toast_payment_result_delayed); + }) + ); + } + + private void disposeCompositeDisposable() { + if (compositeDisposable != null && !compositeDisposable.isDisposed()) { + compositeDisposable.dispose(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + disposeCompositeDisposable(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setWalletData(walletInfo); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setWalletData(walletInfo); + } + } + + private void setWalletData(WalletInfo walletInfo) { + mTv_gold.setText(getString(R.string.charge_gold, walletInfo != null ? walletInfo.getGoldNum() : 0)); + mTvGoldNobleNumber.setText(getString(R.string.change_gold_noble_notice, walletInfo != null ? walletInfo.nobleGoldNum : 0)); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetPassword(PasswordEvent event) { + getDialogManager().showProgressDialog(this); + PaymentActivity.startToPay(this, Constants.CHARGE_UNION_PAY, event.getPassword()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeAdapter.java new file mode 100644 index 000000000..a29a52cf8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeAdapter.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.pay; + +import android.text.TextUtils; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.pay.bean.ChargeBean; + +/** + *

充值adapter

+ * Created by Administrator on 2017/11/20. + */ +public class ChargeAdapter extends BaseQuickAdapter { + ChargeAdapter() { + super(R.layout.list_item_charge); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, ChargeBean chargeBean) { + if (chargeBean == null) return; + + baseViewHolder.setVisible(R.id.ll_gold_charge, !TextUtils.isEmpty(chargeBean.getProdName())); + + baseViewHolder.setText(R.id.tv_money_gold, chargeBean.prodName.replace("轻寻", "")) + .setText(R.id.cb_money, mContext.getString(R.string.charge_number, chargeBean.money)); + + RelativeLayout rl_gold_charge = baseViewHolder.getView(R.id.ll_gold_charge); + ImageView iv_gold = baseViewHolder.getView(R.id.iv_gold); + TextView tv_money_gold = baseViewHolder.getView(R.id.tv_money_gold); + TextView cb_money = baseViewHolder.getView(R.id.cb_money); + rl_gold_charge.setSelected(chargeBean.isSelected); + if(chargeBean.isSelected){ + iv_gold.setImageResource(R.mipmap.ic_wallet_gold); + tv_money_gold.setTextColor(mContext.getResources().getColor(R.color.color_333333)); + cb_money.setTextColor(mContext.getResources().getColor(R.color.color_333333)); + } else { + iv_gold.setImageResource(R.mipmap.ic_wallet_gold_unchecked); + tv_money_gold.setTextColor(mContext.getResources().getColor(R.color.color_999999)); + cb_money.setTextColor(mContext.getResources().getColor(R.color.color_999999)); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeDialog.java b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeDialog.java new file mode 100644 index 000000000..369abcf4c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeDialog.java @@ -0,0 +1,62 @@ +package com.yizhuan.erban.ui.pay; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StyleRes; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by chenran on 2017/11/15. + */ + +public class ChargeDialog extends Dialog implements View.OnClickListener{ + private int gold; + private TextView goldText; + private Button btnIKnow; + + public ChargeDialog(@NonNull Context context, int gold) { + super(context, R.style.dialog); + this.gold = gold; + } + + public ChargeDialog(@NonNull Context context, @StyleRes int themeResId, int gold) { + super(context, R.style.dialog); + this.gold = gold; + } + + protected ChargeDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.charge_dialog); + initView(); + setListener(); + } + + private void setListener() { + btnIKnow.setOnClickListener(this); + } + + private void initView() { + goldText = (TextView) findViewById(R.id.gold_text); + btnIKnow = (Button) findViewById(R.id.btn_charge); + goldText.setText(gold + "金币"); + } + + @Override + public void onClick(View v) { + dismiss(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeSuccessDialog.java b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeSuccessDialog.java new file mode 100644 index 000000000..e3a3b8375 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/ChargeSuccessDialog.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.ui.pay; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.View; +import android.view.Window; + +import com.yizhuan.erban.R; + +public class ChargeSuccessDialog extends Dialog { + + public ChargeSuccessDialog(@NonNull Context context) { + super(context, R.style.dialog); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.charge_success_dialog); + findViewById(R.id.tv_dialog_close).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/ConfirmPaymentDialog.java b/app/src/main/java/com/yizhuan/erban/ui/pay/ConfirmPaymentDialog.java new file mode 100644 index 000000000..117ff4559 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/ConfirmPaymentDialog.java @@ -0,0 +1,294 @@ +package com.yizhuan.erban.ui.pay; + +import android.animation.ObjectAnimator; +import android.app.Dialog; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.pay.adapter.ConfirmPaymentSelectBankAdapter; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.bank_card.bean.BankCardBean; +import com.yizhuan.xchat_android_core.pay.model.unionpay.UnionPayModel; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.zyyoona7.lib.EasyPopup; +import com.zyyoona7.lib.HorizontalGravity; +import com.zyyoona7.lib.VerticalGravity; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +public class ConfirmPaymentDialog extends DialogFragment implements View.OnClickListener { + + public static final String CONFIRM_PAYMENT_AMOUNT = "confirm_payment_amount"; + @BindView(R.id.iv_close) + ImageView ivClose; + @BindView(R.id.tv_amount) + TextView tvAmount; + @BindView(R.id.iv_selected_bank_img) + ImageView ivSelectedBankImg; + @BindView(R.id.tv_selected_bank_name) + TextView tvSelectedBankName; + @BindView(R.id.iv_select) + ImageView ivSelect; + @BindView(R.id.layout_select_way) + LinearLayout layoutSelectWay; + @BindView(R.id.btn_pay) + Button btnPay; + + Unbinder unbinder; + private Context context; + + private EasyPopup easyPopup; + private ObjectAnimator objectAnimatorUp, objectAnimatorDown; + + // 参数 + private double amount; + private OnConfirmPaymentSelectBankListener onConfirmPaymentSelectBankListener; + + // 选中的银行卡信息 + private BankCardBean selectedBankInfo; + + public static ConfirmPaymentDialog newInstance(double amount, OnConfirmPaymentSelectBankListener listener) { + + Bundle args = new Bundle(); + args.putDouble(CONFIRM_PAYMENT_AMOUNT, amount); + ConfirmPaymentDialog fragment = new ConfirmPaymentDialog(); + fragment.setArguments(args); + if (listener != null) { + fragment.setOnConfirmPaymentSelectBankListener(listener); + } + return fragment; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.context = context; + if (getArguments() != null) { + amount = getArguments().getDouble(CONFIRM_PAYMENT_AMOUNT); + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NO_TITLE, R.style.ErbanBottomSheetDialog); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Dialog dialog = super.onCreateDialog(savedInstanceState); + dialog.setCanceledOnTouchOutside(true); + dialog.setCancelable(true); + return dialog; + } + + @Override + public void onStart() { + super.onStart(); + Window window = getDialog().getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparent))); + WindowManager.LayoutParams layoutParams = getDialog().getWindow().getAttributes(); + DisplayMetrics dm = new DisplayMetrics(); + Display display = window.getWindowManager().getDefaultDisplay(); + display.getRealMetrics(dm); + if (getActivity() != null && getActivity().getWindowManager() != null) { + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + } + layoutParams.width = dm.widthPixels; + layoutParams.height = ScreenUtil.dip2px(400); + layoutParams.gravity = Gravity.BOTTOM; + window.setAttributes(layoutParams); + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_confirm_payment, container); + unbinder = ButterKnife.bind(this, view); + + initAnim(); + setListeners(); + setAmountInfo(); + initBankListData(); + return view; + } + + private void initAnim() { + objectAnimatorUp = ObjectAnimator.ofFloat(ivSelect, "rotation", 180f); + objectAnimatorUp.setDuration(600); + objectAnimatorDown = ObjectAnimator.ofFloat(ivSelect, "rotation", 360f); + objectAnimatorDown.setDuration(600); + } + + private void setListeners() { + ivClose.setOnClickListener(this); + btnPay.setOnClickListener(this); + layoutSelectWay.setOnClickListener(this); + } + + private void setAmountInfo() { + tvAmount.setText(String.format("%s", amount)); + changeButtonState();// 金额赋值 + } + + private void initBankListData() { + if (UnionPayModel.getInstance().getUnionPayOrder() != null && !ListUtils.isListEmpty(UnionPayModel.getInstance().getUnionPayOrder().getCardInfos())) { + List bankCardList = UnionPayModel.getInstance().getUnionPayOrder().getCardInfos(); + // 选择银行卡弹出框 + initEasyPop(bankCardList); + // 默认选中银行卡 + for (BankCardBean bankCardBean : bankCardList) { + if (bankCardBean != null && bankCardBean.isDefaultPaymentCard()) { + selectedBankInfo = bankCardBean; + } + } + if (selectedBankInfo == null) { + BankCardBean defaultBankCardBean = bankCardList.get(0); + if (defaultBankCardBean != null) { + selectedBankInfo = defaultBankCardBean; + } + } + setBankInfo(); + } + } + + private void initEasyPop(List list) { + easyPopup = new EasyPopup(context) + .setContentView(R.layout.dialog_confirm_payment_select) + .setFocusAndOutsideEnable(true) + .setBackgroundDimEnable(false) + .setWidth(UIUtil.dip2px(context, 280)) + .setHeight(UIUtil.dip2px(context, 200)) + .createPopup(); + RecyclerView bankRecyclerView = easyPopup.getView(R.id.recycler_bank_list); + bankRecyclerView.setLayoutManager(new LinearLayoutManager(context)); + ConfirmPaymentSelectBankAdapter adapter = new ConfirmPaymentSelectBankAdapter(R.layout.item_confirm_payment_select_bank, list); + bankRecyclerView.setAdapter(adapter); + adapter.setOnItemClickListener((adapter1, view, position) -> { + Object item = adapter1.getItem(position); + if (item instanceof BankCardBean) { + selectedBankInfo = (BankCardBean) item; + setBankInfo(); + } + dismissPopup(); + }); + + easyPopup.setOnDismissListener(() -> { + if (objectAnimatorDown != null) { + objectAnimatorDown.start(); + } + }); + } + + private void setBankInfo() { + if (selectedBankInfo == null) { + return; + } + String bankCardNo = selectedBankInfo.getBankCardNo(); + if (TextUtils.isEmpty(bankCardNo) && bankCardNo.length() < 4) { + bankCardNo = ""; + } else { + bankCardNo = bankCardNo.substring(bankCardNo.length() - 4); + } + String bankName = TextUtils.isEmpty(selectedBankInfo.getBankName()) ? "" : selectedBankInfo.getBankName(); + tvSelectedBankName.setText(String.format("%s(%s)", bankName, bankCardNo)); + ImageLoadUtils.loadImage(context, selectedBankInfo.getBankLogo(), ivSelectedBankImg); + + changeButtonState();// 银行卡信息赋值 + } + + private void changeButtonState() { + if (amount > 0 && selectedBankInfo != null) { + btnPay.setEnabled(true); + } else { + btnPay.setEnabled(false); + } + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.iv_close) {// 关闭 + dismiss(); + } else if (id == R.id.btn_pay) {// 支付 + if (onConfirmPaymentSelectBankListener != null && selectedBankInfo != null) { + onConfirmPaymentSelectBankListener.onSelectFinish(selectedBankInfo); + } + dismiss(); + } else if (id == R.id.layout_select_way) {// 选择支付方式 + showPopup(); + } + } + + private void showPopup() { + if (easyPopup != null) { + easyPopup.showAtAnchorView(layoutSelectWay, + VerticalGravity.BELOW, + HorizontalGravity.ALIGN_RIGHT, + UIUtil.dip2px(context, -15), + UIUtil.dip2px(context, 15)); + if (objectAnimatorUp != null) { + objectAnimatorUp.start(); + } + } + } + + private void dismissPopup() { + if (easyPopup != null) { + easyPopup.dismiss(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + unbinder.unbind(); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + public interface OnConfirmPaymentSelectBankListener { + void onSelectFinish(BankCardBean selectedBankInfo); + } + + public void setOnConfirmPaymentSelectBankListener(OnConfirmPaymentSelectBankListener onConfirmPaymentSelectBankListener) { + this.onConfirmPaymentSelectBankListener = onConfirmPaymentSelectBankListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/pay/adapter/ConfirmPaymentSelectBankAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/pay/adapter/ConfirmPaymentSelectBankAdapter.java new file mode 100644 index 000000000..9fefe8a36 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/pay/adapter/ConfirmPaymentSelectBankAdapter.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.ui.pay.adapter; + +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bank_card.bean.BankCardBean; + +import java.util.List; + +public class ConfirmPaymentSelectBankAdapter extends BaseQuickAdapter { + + public ConfirmPaymentSelectBankAdapter(int layoutResId, @Nullable List data) { + super(layoutResId, data); + } + + @Override + protected void convert(BaseViewHolder helper, BankCardBean item) { + if (item == null) { + return; + } + ImageView bankImage = helper.getView(R.id.iv_bank_image); + ImageLoadUtils.loadImage(mContext, item.getBankLogo(), bankImage); + + TextView tvBankName = helper.getView(R.id.tv_bank_name); + String bankCardNo = item.getBankCardNo(); + if (TextUtils.isEmpty(bankCardNo) && bankCardNo.length() < 4) { + bankCardNo = ""; + } else { + bankCardNo = bankCardNo.substring(bankCardNo.length() - 4); + } + String bankName = TextUtils.isEmpty(item.getBankName()) ? "" : item.getBankName(); + tvBankName.setText(String.format("%s(%s)", bankName, bankCardNo)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/BezierEvaluator.java b/app/src/main/java/com/yizhuan/erban/ui/praise/BezierEvaluator.java new file mode 100644 index 000000000..1ed4befaa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/BezierEvaluator.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.ui.praise; + +import android.animation.TypeEvaluator; +import android.graphics.PointF; + +/** + * @author lim lee + *

+ * 三阶贝塞尔曲线 + */ +public class BezierEvaluator implements TypeEvaluator { + + PointF pointF1; + PointF pointF2; + + public BezierEvaluator(PointF pointF1, PointF pointF2) { + this.pointF1 = pointF1; + this.pointF2 = pointF2; + } + + @Override + public PointF evaluate(float t, PointF pointF0, PointF pointF3) { + PointF pointF = new PointF(); + pointF.x = pointF0.x * (1 - t) * (1 - t) * (1 - t) + 3 * pointF1.x * t + * (1 - t) * (1 - t) + 3 * pointF2.x * t * t * (1 - t) + + pointF3.x * t * t * t; + pointF.y = pointF0.y * (1 - t) * (1 - t) * (1 - t) + 3 * pointF1.y * t + * (1 - t) * (1 - t) + 3 * pointF2.y * t * t * (1 - t) + + pointF3.y * t * t * t; + return pointF; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraise.java b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraise.java new file mode 100644 index 000000000..ee98a2b80 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraise.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.ui.praise; + +import android.graphics.Bitmap; + + +import com.yizhuan.erban.ui.praise.base.IDrawable; +import com.yizhuan.erban.ui.praise.base.IPraise; + +import java.util.Random; + +public class HiPraise implements IPraise { + protected Bitmap bitmap; + public float scale = 1.0f; + public float alpha = 1.0f; + public long duration; + public long startDelay; + public long delayAplhaTime; + + public HiPraise(Bitmap bitmap) { + this.bitmap = bitmap; + final int maxDuration = 2500; + final int minDuration = 2000; + int minDelayAlphaTime = minDuration / 4; + duration = Utils.rondomRange(maxDuration, minDuration); + delayAplhaTime = new Random().nextInt((int) duration) + % (duration - minDelayAlphaTime + 1) + minDelayAlphaTime; + } + + @Override + public IDrawable toDrawable() { + return new PraiseDrawable(bitmap, scale, + alpha, duration, startDelay, delayAplhaTime, 0.45f); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseAnimationView.java b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseAnimationView.java new file mode 100644 index 000000000..0cfbc3ef8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseAnimationView.java @@ -0,0 +1,172 @@ +package com.yizhuan.erban.ui.praise; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.os.Looper; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import com.yizhuan.erban.ui.praise.base.IDrawTask; +import com.yizhuan.erban.ui.praise.base.IDrawable; +import com.yizhuan.erban.ui.praise.base.IPraise; +import com.yizhuan.erban.ui.praise.base.IPraiseView; + + +public class HiPraiseAnimationView extends SurfaceView implements IPraiseView, SurfaceHolder.Callback { + private static final String TAG = HiPraiseAnimationView.class.getSimpleName(); + private static final int MAX_UPDATE_RATE = 25; //刷新频率 + private boolean mIsUpdateThreadStarted; + private volatile boolean mIsSurfaceCreated; + private IDrawTask mDrawTask; + private UpdateThread mUpdateThread; + private int mUpdateRate = MAX_UPDATE_RATE; + private boolean mIsAttached; + private int mSurfaceWidth; + private int mSurfaceHeight; + + public HiPraiseAnimationView(Context context) { + this(context, null); + } + + public HiPraiseAnimationView(Context context, AttributeSet attrs) { + super(context, attrs); + if (!isInEditMode()) { + setZOrderMediaOverlay(true); + setZOrderOnTop(true); + } + setWillNotCacheDrawing(true); + setDrawingCacheEnabled(false); + setWillNotDraw(true); + getHolder().setFormat(PixelFormat.TRANSPARENT);//透明背景 + getHolder().addCallback(this); + mDrawTask = new SimpleDrawTask(new Handler(Looper.getMainLooper())); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mIsAttached = true; + mDrawTask.start(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mIsAttached = false; + mDrawTask.stop(); + stop(); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + mIsSurfaceCreated = true; + clearSurface(); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + mSurfaceWidth = width; + mSurfaceHeight = height; + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + mIsSurfaceCreated = false; + } + + /** + * @return 绘制耗时 + */ + private long drawSurface() { + if (!mIsSurfaceCreated) { + return 0; + } + if (mSurfaceWidth == 0 + || mSurfaceHeight == 0) { + return 0; + } + if (!isShown()) { + mDrawTask.clearDrawable(); //清除绘制对象 + clearSurface(); + return 0; + } + final long startTime = SystemClock.uptimeMillis(); + Canvas canvas = getHolder().lockCanvas(); + if (null != canvas) { + mDrawTask.draw(canvas); //绘制点赞动画 + if (mIsSurfaceCreated) { + getHolder().unlockCanvasAndPost(canvas); + } + } + return SystemClock.uptimeMillis() - startTime; + } + + private void clearSurface() { + if (mIsSurfaceCreated) { + Canvas canvas = getHolder().lockCanvas(); + if (null != canvas) { + canvas.drawColor(Color.TRANSPARENT, + android.graphics.PorterDuff.Mode.CLEAR); + if (mIsSurfaceCreated) { + getHolder().unlockCanvasAndPost(canvas); + } + } + } + } + + public synchronized void start() { + if (mIsUpdateThreadStarted) return; + if (null == mUpdateThread) { + mUpdateThread = new UpdateThread("Update Thread") { + + @Override + public void run() { + try { + while (!isQuited() + && !Thread.currentThread().isInterrupted()) { + final long cost = mUpdateRate - drawSurface(); + if (isQuited()) { + break; + } + if (cost > 0) { + SystemClock.sleep(cost); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + HiPraiseAnimationView.this.stop(); + } + } + }; + } + mIsUpdateThreadStarted = true; + mUpdateThread.start(); + } + + public synchronized void stop() { + mIsUpdateThreadStarted = false; + mDrawTask.clearDrawable(); + if (null != mUpdateThread) { + UpdateThread thread = mUpdateThread; + mUpdateThread = null; + thread.quit(); + thread.interrupt(); + } + } + + @Override + public void addPraise(IPraise praise) { + if (!mIsAttached + || !mIsUpdateThreadStarted) return; + final IDrawable drawable = praise.toDrawable(); + if (null != drawable) { + mDrawTask.addDrawable(drawable); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseWithCallback.java b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseWithCallback.java new file mode 100644 index 000000000..065033e70 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/HiPraiseWithCallback.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.ui.praise; + +import android.graphics.Bitmap; + +import com.yizhuan.erban.ui.praise.base.IDrawable; + + +public class HiPraiseWithCallback extends HiPraise { + + private OnDrawCallback mOnDrawCallback; + + public HiPraiseWithCallback(Bitmap bitmap, OnDrawCallback onDrawCallback) { + super(bitmap); + mOnDrawCallback = onDrawCallback; + } + + @Override + public IDrawable toDrawable() { + return new PraiseWithCallbackDrawable(bitmap, scale, + alpha, duration, startDelay, delayAplhaTime, 0.45f, mOnDrawCallback); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/OnDrawCallback.java b/app/src/main/java/com/yizhuan/erban/ui/praise/OnDrawCallback.java new file mode 100644 index 000000000..b5a517f5f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/OnDrawCallback.java @@ -0,0 +1,13 @@ +package com.yizhuan.erban.ui.praise; + +/** + * Created by apple on 16/10/20. + */ +public interface OnDrawCallback { + + /** + * 主线程回调,不能在这里处理耗时的操作 + */ + void onFinish(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseDrawable.java new file mode 100644 index 000000000..3faf8a673 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseDrawable.java @@ -0,0 +1,253 @@ +package com.yizhuan.erban.ui.praise; + +import android.animation.FloatEvaluator; +import android.animation.TimeInterpolator; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PointF; +import android.support.annotation.NonNull; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; + + +import com.yizhuan.erban.ui.praise.base.IDrawable; + +import java.util.Random; + +public class PraiseDrawable implements IDrawable { + private static final String TAG = PraiseDrawable.class.getSimpleName(); + private static final long MIN_END_POINTY = 16; + private Bitmap bitmap; + private Matrix mMatrix; + private Paint mPaint; + private PointF curPoint; + private PointF startPoint; + private PointF endPoint; + + private int bitmapWidth; + private int bitmapHeight; + private int canvasWidth; + private int canvasHeight; + + private float scale; + private float alpha; + private long duration; + private long startDelay; + private long startFrameTime; + private long startAplhaAnimTime; + private long endFrameTime; + private long delayAphaAnimTime; + private float endYPercentage; + + private BezierEvaluator xFrameEvaluator; + private FloatEvaluator mScaleEvaluator; + private FloatEvaluator mAlphaEvaluator; + private TimeInterpolator mFrameTimeInterpolator; + private TimeInterpolator mScaleTimeInterpolator; + private TimeInterpolator mAlphaTimeInterpolator; + private boolean isFinished; //是否绘制完成了 + private boolean isStarted; //是否开始绘制了 + + public PraiseDrawable(@NonNull Bitmap bitmap, + float scale, float alpha, long duration, long delay, + long delayAphaAnimTime, float endYPercentage) { + mMatrix = new Matrix(); + mPaint = new Paint(); + this.bitmap = bitmap; + this.endYPercentage = Math.min(Math.max(0, endYPercentage), 1); + + /** + * params + * + */ + this.scale = scale; + this.alpha = alpha; + this.duration = duration; + this.startDelay = delay; + this.delayAphaAnimTime = delayAphaAnimTime; + bitmapWidth = (int) (bitmap.getWidth() * scale); + bitmapHeight = (int) (bitmap.getHeight() * scale); + + + /** + * evaluator and interpolator + */ + + mScaleEvaluator = new FloatEvaluator(); + mAlphaEvaluator = new FloatEvaluator(); + mScaleTimeInterpolator = new LinearInterpolator(); + mFrameTimeInterpolator = new AccelerateInterpolator(0.8f); + mAlphaTimeInterpolator = new DecelerateInterpolator(0.5f); + } + + /** + * 绘制起点 + * + * @return + */ + private PointF genStartPoint() { + final float pointX = canvasWidth / 2; + float pointY; + if (bitmapHeight > canvasHeight) { + pointY = canvasHeight; + } else { + pointY = canvasHeight - bitmapHeight; + } + return new PointF(pointX, pointY); + } + + /** + * 绘制终点 + * + * @param point1 + * @param point2 + * @return + */ + private PointF genEndPoint(PointF point1, PointF point2) { + long tempEndY = getEndPointY(); + final float endX = (point1.x + point2.x) / 2; + final float endY = tempEndY; + return new PointF(endX, endY); + } + + /** + * 绘制最后的Y点,获取startPoint后调用 + * + * @return + */ + private long getEndPointY() { + long tempEndY = (long) (startPoint.y * endYPercentage); + if (tempEndY < MIN_END_POINTY) { + tempEndY = MIN_END_POINTY; + } + return tempEndY; + } + + private PointF genRandomPoint2() { + long tempEndY = getEndPointY(); + final float middel = startPoint.x; + final float minX = bitmapWidth / 2; + final int maxX = canvasWidth + bitmapWidth / 2; + float minY = (startPoint.y - tempEndY) / 3 + tempEndY; + final int maxY = (int) ((startPoint.y - tempEndY) / 3 * 2 + tempEndY); + float pointX; + while ((pointX = new Random().nextInt(maxX) % (maxX - minX + 1) + minX) == middel) { + } + final float pointY = new Random().nextInt(maxY) % (maxY - minY + 1) + + minY; + return new PointF(pointX, pointY); + } + + private PointF genRandomPoint1(PointF point2) { + long tempEndY = getEndPointY(); + final float middel = startPoint.x; + final float minX = bitmapWidth / 2; + final int maxX = canvasWidth + bitmapWidth / 2; + final float minY = tempEndY; + final int maxY = (int) ((startPoint.y - tempEndY) / 3 + tempEndY); + float pointX; + if (point2.x > middel) { + while ((pointX = new Random().nextInt(maxX) % (maxX - minX + 1) + + minX) >= middel) { + } + } else { + while ((pointX = new Random().nextInt(maxX) % (maxX - minX + 1) + + minX) <= middel) { + } + } + final float pointY = new Random().nextInt(maxY) % (maxY - minY + 1) + + minY; + return new PointF(pointX, pointY); + } + + @Override + public boolean isFinished() { + return isFinished; + } + + @Override + public void draw(Canvas canvas, long current) { + if (null == bitmap + || duration == 0 + || alpha == 0 + || scale == 0 + || startDelay >= duration) { + isFinished = true; + } + if (!isStarted) { + isStarted = true; + canvasWidth = canvas.getWidth(); + canvasHeight = canvas.getHeight(); + startFrameTime = current + startDelay; + startAplhaAnimTime = startFrameTime + delayAphaAnimTime; + endFrameTime = startFrameTime + duration; + startPoint = genStartPoint(); //动画开始位置 + curPoint = new PointF(startPoint.x, startPoint.y); + PointF point2 = genRandomPoint2(); + PointF point1 = genRandomPoint1(point2); + endPoint = genEndPoint(point1, point2); + xFrameEvaluator = new BezierEvaluator(point2, point1); + } + if (current < startFrameTime) return; + if (current >= endFrameTime) { + isFinished = true; + } + if (!isFinished + && isStarted) { + float fraction = (current - startFrameTime) / (float) duration; + PointF point = drawFrame(fraction, startPoint, endPoint); + mMatrix.setTranslate(curPoint.x = (point.x - bitmapWidth / 2), + curPoint.y = point.y); + float scale = drawScale(fraction); + mMatrix.preScale(scale, scale, bitmapWidth / 2, bitmapHeight); + mPaint.setAlpha((int) (alpha * 255)); + if (current >= startAplhaAnimTime) { + float alphaFraction = (current - startAplhaAnimTime) + / (float) (endFrameTime - startAplhaAnimTime); + mPaint.setAlpha((int) (drawAlpah(alphaFraction) * 255)); + } + canvas.drawBitmap(bitmap, mMatrix, mPaint); + } + } + + /** + * 绘制drawable的缩放 + * + * @param fraction + * @return + */ + private float drawScale(float fraction) { + float newFraction = 4.50f * fraction; + fraction = newFraction > 1 ? 1 : newFraction; + fraction = mScaleTimeInterpolator.getInterpolation(fraction); + return mScaleEvaluator.evaluate(fraction, 0.0f, this.scale); + } + + /** + * 绘制drawable的alpha值 + * + * @param fraction + * @return + */ + private float drawAlpah(float fraction) { + fraction = mAlphaTimeInterpolator.getInterpolation(fraction); + return mAlphaEvaluator.evaluate(fraction, this.alpha, 0.0f); + } + + /** + * 绘制drawable每一帧的移动位置 + * + * @param fraction + * @param start + * @param end + * @return + */ + private PointF drawFrame(float fraction, PointF start, PointF end) { + fraction = mFrameTimeInterpolator.getInterpolation(fraction); + return xFrameEvaluator.evaluate(fraction, start, end); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseWithCallbackDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseWithCallbackDrawable.java new file mode 100644 index 000000000..454b21bcd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/PraiseWithCallbackDrawable.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.ui.praise; + +import android.graphics.Bitmap; +import android.support.annotation.NonNull; + + +public class PraiseWithCallbackDrawable extends PraiseDrawable implements OnDrawCallback { + + private OnDrawCallback mOnDrawCallback; + + public PraiseWithCallbackDrawable(@NonNull Bitmap bitmap, float scale, float alpha, long duration, + long delay, long delayAphaAnimTime, float endYPercentage, OnDrawCallback onDrawCallback) { + super(bitmap, scale, alpha, duration, delay, delayAphaAnimTime, endYPercentage); + mOnDrawCallback = onDrawCallback; + } + + @Override + public void onFinish() { + if (null != mOnDrawCallback) { + mOnDrawCallback.onFinish(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/SimpleDrawTask.java b/app/src/main/java/com/yizhuan/erban/ui/praise/SimpleDrawTask.java new file mode 100644 index 000000000..4765cbcaf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/SimpleDrawTask.java @@ -0,0 +1,132 @@ +package com.yizhuan.erban.ui.praise; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.SystemClock; + + +import com.yizhuan.erban.ui.praise.base.IDrawTask; +import com.yizhuan.erban.ui.praise.base.IDrawable; + +import java.util.Iterator; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + + +public class SimpleDrawTask implements IDrawTask { + private static final String TAG = SimpleDrawTask.class.getSimpleName(); + private static final int MAX_DRAWABLES = 128; //最多显示绘制对象 + private static RectF RECT = new RectF(); + private static Paint PAINT = new Paint(); + private int mDrawables = MAX_DRAWABLES; + private BlockingQueue mDrawableQueue; + private Handler mCallbackHandler; + private Handler mHandler; + private HandlerThread mHandlerThread; + private boolean mIsStarted; + + static { + PAINT.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + PAINT.setColor(Color.TRANSPARENT); + } + + public SimpleDrawTask(Handler callbackHandler) { + mCallbackHandler = callbackHandler; + mDrawableQueue = new ArrayBlockingQueue<>(mDrawables); + } + + @Override + public void start() { + if (mIsStarted) return; + if (null == mHandlerThread) { + mHandlerThread = new HandlerThread("DrawTask HandlerThread"); + mHandlerThread.start(); + } + if (null == mHandler) { + mHandler = new Handler(mHandlerThread.getLooper()); + } + mIsStarted = true; + } + + @Override + public void stop() { + mIsStarted = false; + if (null != mCallbackHandler) { + mCallbackHandler.removeCallbacksAndMessages(null); + } + mHandler.removeCallbacksAndMessages(null); + HandlerThread handlerThread = mHandlerThread; + mHandlerThread = null; + handlerThread.quit(); + try { + handlerThread.join(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + handlerThread.interrupt(); + } + + @Override + public void draw(Canvas canvas) { + clearCanvas(canvas); + consumeDrawableQueue(canvas); + } + + private void clearCanvas(Canvas canvas) { + canvas.drawColor(Color.TRANSPARENT, + PorterDuff.Mode.CLEAR); + RECT.set(0, 0, canvas.getWidth(), canvas.getHeight()); + canvas.drawRect(RECT, PAINT); + } + + @Override + public void addDrawable(final IDrawable drawable) { + if (mIsStarted + && null != mHandler) { + mHandler.post(new Runnable() { + @Override + public void run() { + try { + mDrawableQueue.offer(drawable); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + }); + } + } + + @Override + public void clearDrawable() { + mDrawableQueue.clear(); + } + + private void consumeDrawableQueue(Canvas canvas) { + Iterator drawableIterator = mDrawableQueue.iterator(); + while (drawableIterator.hasNext()) { + final IDrawable drawable = drawableIterator.next(); + if (null != drawable) { + long currentTime = SystemClock.uptimeMillis(); + drawable.draw(canvas, currentTime); + if (drawable.isFinished()) { + if (null != mCallbackHandler + && drawable instanceof OnDrawCallback) { + mCallbackHandler.post(new Runnable() { + @Override + public void run() { + ((OnDrawCallback) drawable).onFinish(); + } + }); + } + drawableIterator.remove(); + } + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/UpdateThread.java b/app/src/main/java/com/yizhuan/erban/ui/praise/UpdateThread.java new file mode 100644 index 000000000..d126c2eb6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/UpdateThread.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.ui.praise; + +/** + * @author lim lee 2017/3/10 + */ +public class UpdateThread extends Thread { + volatile boolean mIsQuited; + + public UpdateThread(String name) { + super(name); + } + + public void quit() { + mIsQuited = true; + } + + public boolean isQuited() { + return mIsQuited; + } + + @Override + public void run() { + if (mIsQuited) return; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/Utils.java b/app/src/main/java/com/yizhuan/erban/ui/praise/Utils.java new file mode 100644 index 000000000..a17ed7cd5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/Utils.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.ui.praise; + +import java.util.Random; + +public class Utils { + private static final Random RANDOM = new Random(); + + private Utils() { + } + + public static int rondomRange(int max, int min) { + return RANDOM.nextInt(max) + % (max - min + 1) + min; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawTask.java b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawTask.java new file mode 100644 index 000000000..386cadd50 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawTask.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.ui.praise.base; + +import android.graphics.Canvas; + +public interface IDrawTask { + + void start(); + + void stop(); + + void draw(Canvas canvas); + + void addDrawable(IDrawable drawable); + + void clearDrawable(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawable.java new file mode 100644 index 000000000..de42669dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IDrawable.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.ui.praise.base; + +import android.graphics.Canvas; + +public interface IDrawable { + + /** + * 是否已经绘制完成 + * + * @return + */ + boolean isFinished(); + + /** + * 如果绘制当前动画 + * + * @param canvas + * @param current 当前绘制的时间 + */ + void draw(Canvas canvas, long current); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraise.java b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraise.java new file mode 100644 index 000000000..e8dd58d3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraise.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.ui.praise.base; + +public interface IPraise { + + /** + * 转换成可以绘制的对象 + * + * @return + */ + IDrawable toDrawable(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraiseView.java b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraiseView.java new file mode 100644 index 000000000..304592b1f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/praise/base/IPraiseView.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.ui.praise.base; + +public interface IPraiseView { + + /** + * 添加一个点赞的对象,这个对象用来描述这个点赞的动画,但它并不是一个动画对象 + * + * @param praise + */ + void addPraise(IPraise praise); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/radish/RadishRecordFragment.java b/app/src/main/java/com/yizhuan/erban/ui/radish/RadishRecordFragment.java new file mode 100644 index 000000000..e859ce9cd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/radish/RadishRecordFragment.java @@ -0,0 +1,151 @@ +package com.yizhuan.erban.ui.radish; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.bills.adapter.BillBaseAdapter; +import com.yizhuan.erban.bills.fragmemt.BaseBillsFragment; +import com.yizhuan.erban.radish.adapter.RadishRecordAdapter; +import com.yizhuan.erban.radish.presenter.RadishRecordFrgPresenter; +import com.yizhuan.erban.radish.view.IRadishRecordFrgView; +import com.yizhuan.erban.ui.widget.RecyclerViewNoBugLinearLayoutManager; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.bills.bean.BillItemEntity; +import com.yizhuan.xchat_android_core.bills.bean.RadishRecordInfo; +import com.yizhuan.xchat_android_core.bills.bean.RadishRecordListInfo; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@CreatePresenter(RadishRecordFrgPresenter.class) +public class RadishRecordFragment extends BaseBillsFragment implements IRadishRecordFrgView{ + + public static final byte TYPE_RADISH_EXPAND = 1; + public static final byte TYPE_RADISH_INCOME = 2; + private static final String TYPE = "type_radish"; + private BillBaseAdapter mAdapter; + + private byte mType = TYPE_RADISH_INCOME; + + public static Fragment newInstance(byte type) { + Fragment fragment = new RadishRecordFragment(); + Bundle bundle = new Bundle(); + bundle.putByte(TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void loadData() { + getMvpPresenter().getRadishRecord(mCurrentCounter, PAGE_SIZE, mTime, mType); + } + + private void firstLoadDate() { + mCurrentCounter = Constants.PAGE_START; + showLoading(); + loadData(); + } + + @Override + public void initiate() { + super.initiate(); + + setRlyDateBackground(ContextCompat.getColor(mContext, R.color.color_F8F9FB)); + Bundle bundle = getArguments(); + if (bundle != null) { + mType = bundle.getByte(TYPE, TYPE_RADISH_INCOME); + } + + mAdapter = new RadishRecordAdapter(mBillItemEntityList, mType); + mAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mCurrentCounter++; + loadData(); + } + }, mRecyclerView); + + RecyclerViewNoBugLinearLayoutManager manager = new RecyclerViewNoBugLinearLayoutManager(mContext); + mRecyclerView.setLayoutManager(manager); + mRecyclerView.setAdapter(mAdapter); + firstLoadDate(); + + } + + @Override + public void getRadishRecordSuccess(RadishRecordListInfo list) { + mRefreshLayout.setRefreshing(false); + if (null != list) { + if (mCurrentCounter == Constants.PAGE_START) { + hideStatus(); + mBillItemEntityList.clear(); + mAdapter.setNewData(mBillItemEntityList); + } else { + mAdapter.loadMoreComplete(); + } + List>> billList = list.getBillList(); + if (!billList.isEmpty()) { + int size = mBillItemEntityList.size(); + List billItemEntities = new ArrayList<>(); + BillItemEntity billItemEntity; + for (int i = 0; i < billList.size(); i++) { + Map> map = billList.get(i); + for (String key : map.keySet()) { + // key ---日期 value:list集合记录 + List incomeInfos = map.get(key); + if (ListUtils.isListEmpty(incomeInfos)) continue; + + //标题 + if (size > 0) { + BillItemEntity lastBillItem = mBillItemEntityList.get(size - 1); + //时间不一致才会添加标题 + if (!TextUtils.equals(lastBillItem.time, key)) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + } else { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_DATE, key); + billItemEntities.add(billItemEntity); + } + + //正常item + for (RadishRecordInfo temp : incomeInfos) { + billItemEntity = new BillItemEntity(BillItemEntity.ITEM_NORMAL); + billItemEntity.mRadishRecordInfo = temp; + //目的是为了比较 + billItemEntity.time = key; + billItemEntities.add(billItemEntity); + } + } + } + if (billItemEntities.size() < Constants.BILL_PAGE_SIZE && mCurrentCounter == Constants.PAGE_START) { + mAdapter.setEnableLoadMore(false); + } + mAdapter.addData(billItemEntities); + } else { + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, mContext.getString(R.string.tips_radish_record_empty)); + } else { + mAdapter.loadMoreEnd(true); + } + } + } + + } + + @Override + public void getRadishRecordFail(String message) { + if (mCurrentCounter == Constants.PAGE_START) { + showNetworkErr(); + } else { + mAdapter.loadMoreFail(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/AttentionListActivity.java b/app/src/main/java/com/yizhuan/erban/ui/relation/AttentionListActivity.java new file mode 100644 index 000000000..4246ed43d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/AttentionListActivity.java @@ -0,0 +1,232 @@ +package com.yizhuan.erban.ui.relation; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.ui.relation.adapter.AttentionListAdapter; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_library.coremanager.CoreEvent; + + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.erban.R.id.swipe_refresh; + +/** + * 关注列表 + */ +public class AttentionListActivity extends BaseActivity { + + private RecyclerView mRecylcerView; + private SwipeRefreshLayout swipeRefreshLayout; + private AttentionListActivity mActivity; + private AttentionListAdapter adapter; + private List mAttentionInfoList = new ArrayList<>(); + + private int mPage = Constants.PAGE_START; + + public static void start(Context context) { + Intent intent = new Intent(context, AttentionListActivity.class); + context.startActivity(intent); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_list_attention); + initTitleBar(getString(R.string.my_attention)); + initView(); + setListener(); + initData(); + EventBus.getDefault().register(this); + } + + private void setListener() { + swipeRefreshLayout.setOnRefreshListener(onRefreshLisetener); + adapter = new AttentionListAdapter(mAttentionInfoList); + adapter.setRylListener(new AttentionListAdapter.onClickListener() { + @Override + public void rylListeners(AttentionInfo attentionInfo) { + UserInfoActivity.Companion.start(mActivity, attentionInfo.getUid()); + } + + @Override + public void findHimListeners(AttentionInfo attentionInfo) { + if (attentionInfo.getUserInRoom() != null) + AVRoomActivity.start(mActivity, attentionInfo.getUserInRoom().getUid()); + } + + @Override + public void sendListener(AttentionInfo attentionInfo) { + } + }); + adapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + mPage++; + onRefreshing(); + } + }, mRecylcerView); + } + + private void initData() { + mRecylcerView.setAdapter(adapter); + showLoading(); + onRefreshing(); + } + + private void initView() { + mActivity = this; + mRecylcerView = findViewById(R.id.recyclerView); + swipeRefreshLayout = findViewById(swipe_refresh); + mRecylcerView.setLayoutManager(new LinearLayoutManager(mActivity)); + + } + + SwipeRefreshLayout.OnRefreshListener onRefreshLisetener = new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mPage = Constants.PAGE_START; + onRefreshing(); + } + }; + + private void onRefreshing() { + AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + mPage, + Constants.PAGE_SIZE + ) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List attentionInfos) { + onGetAttentionList(attentionInfos,mPage); + } + + @Override + public void onError(Throwable e) { + onGetAttentionListFail(e.getMessage(),mPage); + } + }); + } + + public void onGetAttentionList(List attentionInfoList, int page) { + mPage = page; + if (!ListUtils.isListEmpty(attentionInfoList)) { + if (mPage == Constants.PAGE_START) { + hideStatus(); + swipeRefreshLayout.setRefreshing(false); + mAttentionInfoList.clear(); + adapter.setNewData(attentionInfoList); + if (attentionInfoList.size() < Constants.PAGE_SIZE) { + adapter.setEnableLoadMore(false); + } + } else { + adapter.loadMoreComplete(); + adapter.addData(attentionInfoList); + } + } else { + if (mPage == Constants.PAGE_START) { + showNoData(R.drawable.icon_common_failure, getString(R.string.no_attention_text)); + } else { + adapter.loadMoreEnd(true); + } + + } + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(int drawable, CharSequence charSequence) { + if (!checkActivityValid()) { + return; + } + + View status = findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.fragment_no_data_large_iv, drawable, charSequence); + fragment.setListener(getLoadListener()); + getSupportFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + public void onGetAttentionListFail(String error, int page) { + mPage = page; + if (mPage == Constants.PAGE_START) { + swipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + adapter.loadMoreFail(); + toast(error); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCanceledPraise(PraiseEvent event) { +// long uid = event.getData(); +// List data = adapter.getData(); +// if (!ListUtils.isListEmpty(data)) { +// ListIterator iterator = data.listIterator(); +// for (; iterator.hasNext(); ) { +// AttentionInfo attentionInfo = iterator.next(); +// if (attentionInfo.isValid() && attentionInfo.getUid() == uid) { +// iterator.remove(); +// } +// } +// adapter.notifyDataSetChanged(); +// } + } + + @Override + public View.OnClickListener getLoadListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + mPage = Constants.PAGE_START; + showLoading(); + onRefreshing(); + } + }; + } +} + + diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/FansListActivity.java b/app/src/main/java/com/yizhuan/erban/ui/relation/FansListActivity.java new file mode 100644 index 000000000..1123d85fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/FansListActivity.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.ui.relation; + +import android.os.Bundle; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.home.fragment.AttentionFragment; +import com.yizhuan.xchat_android_core.Constants; + +/** + * 粉丝列表 + */ +public class FansListActivity extends BaseActivity { + + public static final String IS_ATTENT = "is_attent"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_fans); + + + if (getIntent().getBooleanExtra(IS_ATTENT, false)) { + initTitleBar(getString(R.string.my_attention)); + getSupportFragmentManager().beginTransaction() + .add(R.id.fragment_container, AttentionFragment.newInstance( + Constants.FAN_NO_MAIN_PAGE_TYPE), AttentionFragment.class.getSimpleName()) + .commitAllowingStateLoss(); + return; + } + initTitleBar(getString(R.string.my_fan)); + getSupportFragmentManager().beginTransaction() + .add(R.id.fragment_container, FansListFragment.newInstance(Constants.FAN_NO_MAIN_PAGE_TYPE), + FansListFragment.class.getSimpleName()) + .commitAllowingStateLoss(); + + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/FansListFragment.java b/app/src/main/java/com/yizhuan/erban/ui/relation/FansListFragment.java new file mode 100644 index 000000000..e658bdcd3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/FansListFragment.java @@ -0,0 +1,281 @@ +package com.yizhuan.erban.ui.relation; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.NoDataFragment; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.relation.adapter.FansViewAdapter; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.tutu.room_chat.activity.NimRoomP2PMessageActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; +import com.yizhuan.xchat_android_core.user.bean.FansListInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +import static com.yizhuan.erban.friend.action.AbstractSelectFriendAction.ROOM_MSG; + + +/** + * 粉丝列表 + * Created by chenran on 2017/10/2. + */ +public class FansListFragment extends BaseFragment { + private RecyclerView mRecyclerView; + private SwipeRefreshLayout mSwipeRefreshLayout; + private FansViewAdapter adapter; + private int mCurrentCounter = Constants.PAGE_START; + private List mFansInfoList = new ArrayList<>(); + private Context mContext; + private int mPageType; + private int type; + private SelectFriendActivity friendActivity; + + public static FansListFragment newInstanceForSelect(int type) { + FansListFragment fragment = new FansListFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(AbstractSelectFriendAction.KEY_TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + + public static FansListFragment newInstance(int pageType) { + FansListFragment fragment = new FansListFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(Constants.KEY_PAGE_TYPE, pageType); + fragment.setArguments(bundle); + return fragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + mPageType = bundle.getInt(Constants.KEY_PAGE_TYPE); + type = bundle.getInt(AbstractSelectFriendAction.KEY_TYPE); + } + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof SelectFriendActivity) { + friendActivity = (SelectFriendActivity) activity; + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = getContext(); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + mRecyclerView = mView.findViewById(R.id.recycler_view); + mSwipeRefreshLayout = mView.findViewById(R.id.swipe_refresh); + } + + @Override + public void onSetListener() { + mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + adapter = new FansViewAdapter(mFansInfoList); + adapter.setType(type); + adapter.setOnLoadMoreListener(() -> { + mCurrentCounter++; + onRefreshing(); + }, mRecyclerView); + mRecyclerView.setAdapter(adapter); + mSwipeRefreshLayout.setOnRefreshListener(() -> { + mCurrentCounter = Constants.PAGE_START; + onRefreshing(); + }); + adapter.setRylListener(new FansViewAdapter.OnItemClickListener() { + @Override + public void onItemClick(FansInfo fansInfo) { + if (NimP2PMessageActivity.SECRETARY_UID == fansInfo.getUid()) { + return; + } + if (type == ROOM_MSG) { + NimRoomP2PMessageActivity.start(getActivity(), String.valueOf(fansInfo.getUid())); + } else { + UserInfoActivity.Companion.start(mContext, fansInfo.getUid()); + } + } + + @Override + public void onAttentionBtnClick(FansInfo fansInfo) { + if (!IMFriendModel.get().isMyFriend(String.valueOf(fansInfo.getUid()))) { + getDialogManager().showProgressDialog(mContext, getString(R.string.waiting_text)); + PraiseModel.get().praise(fansInfo.getUid(), true).subscribe(); + } + } + + @Override + public void sendListener(FansInfo attentionInfo) { + if (friendActivity != null) { + friendActivity.showSureDialog(String.valueOf(attentionInfo.getUid()), attentionInfo.getAvatar(), attentionInfo.getNick()); + } + } + }); + } + + + private void onRefreshing() { + AttentionModel.get().getFansList( + AuthModel.get().getCurrentUid(), + mCurrentCounter, + Constants.PAGE_SIZE + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FansListInfo fansListInfo) { + onGetMyFansList(fansListInfo, mPageType, mCurrentCounter); + } + + @Override + public void onError(Throwable e) { + onGetMyFansListFail(e.getMessage(), mPageType, mCurrentCounter); + } + }); + } + + @Override + public void initiate() { + mSwipeRefreshLayout.setRefreshing(true); + mCurrentCounter = Constants.PAGE_START; + onRefreshing(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_fans_list; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + getDialogManager().dismissDialog(); + if (event.isFailed()) { + toast(event.getError()); + return; + } + //该界面关注后,关注按钮消失,所有没有取消操作 + toast(getString(R.string.fan_success)); + } + + public void onGetMyFansList(FansListInfo fansListInfo, int pageType, int page) { + mCurrentCounter = page; + if (pageType == mPageType) { + mSwipeRefreshLayout.setRefreshing(false); + if (fansListInfo == null || ListUtils.isListEmpty(fansListInfo.getFansList())) { + //第一页 + if (mCurrentCounter == Constants.PAGE_START) { + if (adapter != null) { + mFansInfoList.clear(); + adapter.setNewData(mFansInfoList); + } + showNoData(R.drawable.icon_common_failure, getString(R.string.no_fan_text)); + } else { + adapter.loadMoreEnd(true); + } + } else { + hideStatus(); + if (mCurrentCounter == Constants.PAGE_START) { + mFansInfoList.clear(); + List fansList = fansListInfo.getFansList(); + mFansInfoList.addAll(fansList); + adapter.setNewData(mFansInfoList); + if (fansList.size() < Constants.PAGE_SIZE) { + adapter.setEnableLoadMore(false); + } + return; + } + adapter.loadMoreComplete(); + adapter.addData(fansListInfo.getFansList()); + } + } + } + + @SuppressLint("ResourceType") + @Override + public void showNoData(View view, int drawable, CharSequence charSequence) { + if (!checkActivityValid()) + return; + + if (view == null) { + return; + } + View status = view.findViewById(R.id.status_layout); + if (status == null || status.getId() <= 0) { + return; + } + NoDataFragment fragment = NoDataFragment.newInstance(R.layout.frg_no_data_large_iv_transparent, drawable, charSequence); + fragment.setListener(getLoadListener()); + getChildFragmentManager().beginTransaction().replace(status.getId(), fragment, STATUS_TAG).commitAllowingStateLoss(); + } + + public void onGetMyFansListFail(String error, int pageType, int page) { + mCurrentCounter = page; + if (pageType == mPageType) { + if (mCurrentCounter == Constants.PAGE_START) { + mSwipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + adapter.loadMoreFail(); + toast(error); + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + mCurrentCounter = Constants.PAGE_START; + onRefreshing(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + mCurrentCounter = Constants.PAGE_START; + showLoading(); + onRefreshing(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionListAdapter.java new file mode 100644 index 000000000..8136b80fa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionListAdapter.java @@ -0,0 +1,127 @@ +package com.yizhuan.erban.ui.relation.adapter; + +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + +import java.util.List; + +/** + *

关注列表

+ * Created by Administrator on 2017/11/17. + */ +public class AttentionListAdapter extends BaseQuickAdapter { + + private int type = AbstractSelectFriendAction.TYPE_NORMAL; + + public AttentionListAdapter(List attentionInfoList) { + super(R.layout.attention_item_new, attentionInfoList); + } + + public void setType(int type) { + this.type = type; + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, final AttentionInfo attentionInfo) { + if (attentionInfo == null) return; + boolean isSend = (type == AbstractSelectFriendAction.TYPE_WEAR || + type == AbstractSelectFriendAction.TYPE_CAR); + baseViewHolder.setText(R.id.tv_userName, attentionInfo.getNick()) + .setText(R.id.tv_user_desc, attentionInfo.getUserDesc() != null ? + attentionInfo.getUserDesc() + : baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) + .setGone(R.id.tv_find_him, attentionInfo.getUserInRoom() != null && type == AbstractSelectFriendAction.TYPE_NORMAL) + .setGone(R.id.tv_send, isSend) + .setOnClickListener(R.id.tv_find_him, v -> { + if (rylListener != null) + rylListener.findHimListeners(attentionInfo); + }) + .setOnClickListener(R.id.tv_send, v -> { + if (rylListener != null) + rylListener.sendListener(attentionInfo); + }) + .setOnClickListener(R.id.rly, v -> { + if (rylListener != null) + switch (type) { + case AbstractSelectFriendAction.ROOM_MSG: + case AbstractSelectFriendAction.TYPE_NORMAL: + rylListener.rylListeners(attentionInfo); + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + rylListener.sendListener(attentionInfo); + break; + + case Constants.FAN_NO_MAIN_PAGE_TYPE: + rylListener.rylListeners(attentionInfo); + break; + } + }); + + AppCompatImageView ivGender = baseViewHolder.getView(R.id.iv_gender); + if (attentionInfo.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + baseViewHolder.getView(R.id.iv_user_official).setVisibility(attentionInfo.isOfficial() ? View.VISIBLE : View.GONE); + + AppCompatImageView ivNobleLevel = baseViewHolder.getView(R.id.iv_noble_level); + if (attentionInfo.nobleUsers != null) { + ivNobleLevel.setVisibility(View.VISIBLE); + String badgeByLevel = NobleUtil.getBadgeByLevel(attentionInfo.nobleUsers.getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } else { + ivNobleLevel.setVisibility(View.GONE); + } + } else { + ivNobleLevel.setVisibility(View.GONE); + } + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(55, 75, 15); + nobleAvatarView.setData(attentionInfo.avatar, attentionInfo.nobleUsers); + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (attentionInfo.userLevelVo != null && !TextUtils.isEmpty(attentionInfo.userLevelVo.getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, attentionInfo.userLevelVo.getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = baseViewHolder.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (attentionInfo.userLevelVo != null && !TextUtils.isEmpty(attentionInfo.userLevelVo.getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, attentionInfo.userLevelVo.getCharmUrl(), ivCharmLevel); + } + } + + private onClickListener rylListener; + + public interface onClickListener { + void rylListeners(AttentionInfo attentionInfo); + + void findHimListeners(AttentionInfo attentionInfo); + + void sendListener(AttentionInfo attentionInfo); + } + + public void setRylListener(onClickListener onClickListener) { + rylListener = onClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserAdapter.java new file mode 100644 index 000000000..6d39ac202 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserAdapter.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.ui.relation.adapter; + +import android.app.Activity; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + +import java.util.List; + +/** + * Created by chenran on 2017/9/21. + */ + +public class AttentionUserAdapter extends RecyclerView.Adapter { + private List attentionInfoList; + private Activity context; + + public AttentionUserAdapter(Activity context) { + this.context = context; + } + + public void setAttentionInfoList(List attentionInfoList) { + this.attentionInfoList = attentionInfoList; + } + + @Override + public AttentionUserAdapter.AttentionUserHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_attention_user, parent, false); + return new AttentionUserHolder(item); + } + + @Override + public void onBindViewHolder(final AttentionUserAdapter.AttentionUserHolder holder, final int position) { + final AttentionInfo attentionInfo = attentionInfoList.get(position); + ImageLoadUtils.loadAvatar(holder.avatar.getContext(), attentionInfo.getAvatar(), holder.avatar, true); + holder.avatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AttentionInfo attentionInfo = attentionInfoList.get(holder.getAdapterPosition()); + UserInfoActivity.Companion.start(context, attentionInfo.getUid()); + } + }); + } + + @Override + public int getItemCount() { + if (attentionInfoList == null) { + return 0; + } else { + return attentionInfoList.size(); + } + } + + + public static class AttentionUserHolder extends RecyclerView.ViewHolder { + private ImageView avatar; + + public AttentionUserHolder(View itemView) { + super(itemView); + avatar = (ImageView) itemView.findViewById(R.id.avatar); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserLiveAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserLiveAdapter.java new file mode 100644 index 000000000..323e7f322 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/AttentionUserLiveAdapter.java @@ -0,0 +1,110 @@ +package com.yizhuan.erban.ui.relation.adapter; + +import android.app.Activity; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + +import java.util.List; + + +/** + * 关注用户在线列表 + * Created by chenran on 2017/9/21. + */ +public class AttentionUserLiveAdapter extends RecyclerView.Adapter implements View.OnClickListener { + private List attentionInfoList; + private Activity context; + + public AttentionUserLiveAdapter(Activity context) { + this.context = context; + } + + public void setAttentionInfoList(List attentionInfoList) { + this.attentionInfoList = attentionInfoList; + } + + @Override + public AttentionUserLiveAdapter.AttentionUserLiveHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_attention_user_live, parent, false); + return new AttentionUserLiveAdapter.AttentionUserLiveHolder(item); + } + + @Override + public void onBindViewHolder(AttentionUserLiveAdapter.AttentionUserLiveHolder holder, int position) { + final AttentionInfo attentionInfo = attentionInfoList.get(position); + holder.liveAnimation.setBackgroundResource(R.drawable.attention_live_anim); + AnimationDrawable anima = (AnimationDrawable) holder.liveAnimation.getBackground(); + anima.start(); + holder.nick.setText(attentionInfo.getNick()); + if (attentionInfo.getType() == RoomInfo.ROOMTYPE_AUCTION) { + holder.flagImage.setImageResource(R.drawable.icon_attention_flag_auction); + } else if (attentionInfo.getType() == RoomInfo.ROOMTYPE_LIGHT_CHAT) { + holder.flagImage.setImageResource(R.drawable.icon_attention_flag_light_chat); + } else { + holder.flagImage.setImageResource(R.drawable.icon_attention_flag_homeparty); + } + + Drawable drawable; + if (attentionInfo.getGender() == 1) { + drawable = context.getResources().getDrawable(R.drawable.ic_male); + } else { + drawable = context.getResources().getDrawable(R.drawable.ic_female); + } + + holder.nick.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); + holder.relativeLayout.setTag(position); + holder.relativeLayout.setOnClickListener(this); + + ImageLoadUtils.loadAvatar(holder.imageBg.getContext(), attentionInfo.getAvatar(), holder.avatar, true); + ImageLoadUtils.loadImageWithBlurTransformationAndCorner(holder.imageBg.getContext(), attentionInfo.getAvatar(), holder.imageBg); + } + + @Override + public int getItemCount() { + if (attentionInfoList == null) { + return 0; + } else { + return attentionInfoList.size(); + } + } + + @Override + public void onClick(View v) { + Integer position = (Integer) v.getTag(); + AttentionInfo attentionInfo = attentionInfoList.get(position); + AVRoomActivity.start(v.getContext(), attentionInfo.getUid()); + } + + public static class AttentionUserLiveHolder extends RecyclerView.ViewHolder { + private ImageView avatar; + private ImageView imageBg; + private ImageView flagImage; + private ImageView liveAnimation; + private TextView nick; + private RelativeLayout relativeLayout; + + public AttentionUserLiveHolder(View itemView) { + super(itemView); + avatar = (ImageView) itemView.findViewById(R.id.avatar); + imageBg = (ImageView) itemView.findViewById(R.id.image_bg); + flagImage = (ImageView) itemView.findViewById(R.id.flag_logo); + liveAnimation = (ImageView) itemView.findViewById(R.id.live_animation); + nick = (TextView) itemView.findViewById(R.id.nick); + relativeLayout = (RelativeLayout) itemView.findViewById(R.id.rly_home); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/FansViewAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/FansViewAdapter.java new file mode 100644 index 000000000..773b03349 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/relation/adapter/FansViewAdapter.java @@ -0,0 +1,136 @@ +package com.yizhuan.erban.ui.relation.adapter; + +import android.graphics.drawable.GradientDrawable; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; + +import java.util.List; + +/** + * @author chenran + * @date 2017/10/2 + */ +public class FansViewAdapter extends BaseQuickAdapter { + + private OnItemClickListener onItemClickListener; + private int type = AbstractSelectFriendAction.TYPE_NORMAL; + + public void setType(int type) { + this.type = type; + } + + public interface OnItemClickListener { + void onItemClick(FansInfo fansInfo); + + void onAttentionBtnClick(FansInfo fansInfo); + + void sendListener(FansInfo attentionInfo); + } + + public void setRylListener(OnItemClickListener onClickListener) { + onItemClickListener = onClickListener; + } + + public FansViewAdapter(List fansInfoList) { + super(R.layout.fans_list_item_new, fansInfoList); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, final FansInfo fansInfo) { + if (fansInfo == null) return; + boolean isSend = (type == AbstractSelectFriendAction.TYPE_CAR || + type == AbstractSelectFriendAction.TYPE_WEAR); + baseViewHolder.setText(R.id.tv_userName, fansInfo.getNick()) + .setText(R.id.tv_user_desc, fansInfo.getUserDesc() != null ? + fansInfo.getUserDesc() + : baseViewHolder.itemView.getContext().getResources().getString(R.string.msg_no_user_desc)) +// .setVisible(R.id.view_line, baseViewHolder.getLayoutPosition() != getItemCount() - 1) + .setVisible(R.id.tv_send, isSend) + .setOnClickListener(R.id.tv_send, v -> { + if (onItemClickListener != null) { + onItemClickListener.sendListener(fansInfo); + } + }) + .setOnClickListener(R.id.rly, v -> { + if (onItemClickListener != null) { + switch (type) { + case AbstractSelectFriendAction.ROOM_MSG: + case AbstractSelectFriendAction.TYPE_NORMAL: + onItemClickListener.onItemClick(fansInfo); + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + onItemClickListener.sendListener(fansInfo); + break; + } + } + }) + .setOnClickListener(R.id.attention_img, v -> { + if (onItemClickListener != null) { + onItemClickListener.onAttentionBtnClick(fansInfo); + } + }); + + TextView tvAttention = baseViewHolder.getView(R.id.attention_img); + GradientDrawable attentionBg = (GradientDrawable) tvAttention.getBackground(); + baseViewHolder.setVisible(R.id.attention_img, type == AbstractSelectFriendAction.TYPE_NORMAL); + if (IMFriendModel.get().isMyFriend(String.valueOf(fansInfo.getUid()))) { + tvAttention.setText("互相关注"); + attentionBg.setColor(mContext.getResources().getColor(R.color.color_CCCCCC)); + } else { + tvAttention.setText("+关注"); + attentionBg.setColor(mContext.getResources().getColor(R.color.appColor)); + } + + AppCompatImageView ivGender = baseViewHolder.getView(R.id.iv_gender); + if (fansInfo.getGender() == 1) { + ivGender.setImageResource(R.drawable.ic_male); + } else { + ivGender.setImageResource(R.drawable.ic_female); + } + + // 官字 + baseViewHolder.getView(R.id.iv_user_official).setVisibility(fansInfo.isOfficial() ? View.VISIBLE : View.GONE); + + NobleAvatarView nobleAvatarView = baseViewHolder.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(55, 75, 15); + nobleAvatarView.setData(fansInfo.getAvatar(), fansInfo.getNobleUsers()); + + AppCompatImageView ivUserLevel = baseViewHolder.getView(R.id.iv_user_level); + ivUserLevel.setVisibility(View.GONE); + if (fansInfo.getUserLevelVo() != null && !TextUtils.isEmpty(fansInfo.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, fansInfo.getUserLevelVo().getExperUrl(), ivUserLevel); + } + + AppCompatImageView ivCharmLevel = baseViewHolder.getView(R.id.iv_charm_level); + ivCharmLevel.setVisibility(View.GONE); + if (fansInfo.getUserLevelVo() != null && !TextUtils.isEmpty(fansInfo.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, fansInfo.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + + AppCompatImageView ivBadge = baseViewHolder.getView(R.id.iv_noble_level); + ivBadge.setVisibility(View.GONE); + if (fansInfo.getNobleUsers() != null) { + String badgeByLevel = NobleUtil.getBadgeByLevel(fansInfo.getNobleUsers().getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + ivBadge.setVisibility(View.VISIBLE); + NobleUtil.loadResource(badgeByLevel, ivBadge); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/RoomHistoryAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/search/RoomHistoryAdapter.java new file mode 100644 index 000000000..724dddb3e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/RoomHistoryAdapter.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.ui.search; + +import android.support.annotation.Nullable; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.xchat_android_core.bean.RoomHistoryInfo; + +import java.util.List; + +public class RoomHistoryAdapter extends BaseQuickAdapter { + + public RoomHistoryAdapter(@Nullable List data) { + super(R.layout.item_room_history, data); + } + + @Override + protected void convert(BaseViewHolder helper, RoomHistoryInfo item) { + if (item == null) { + return; + } + + CircleImageView circleImageView = helper.getView(R.id.civ_room_avatar); + ImageLoadUtilsV2.loadImage(circleImageView, item.getAvatar()); + + helper.setText(R.id.tv_room_name, item.getTitle()); + helper.setGone(R.id.iv_living, item.isValid()); + helper.addOnClickListener(R.id.container_item_room_history); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/SearchActivity.java b/app/src/main/java/com/yizhuan/erban/ui/search/SearchActivity.java new file mode 100644 index 000000000..02aa7f6c9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/SearchActivity.java @@ -0,0 +1,545 @@ +package com.yizhuan.erban.ui.search; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nimlib.sdk.msg.model.IMMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.decoration.helper.DecorationDialogHelper; +import com.yizhuan.erban.decoration.helper.DecorationSaleType; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.friend.view.SelectFriendActivity; +import com.yizhuan.erban.ui.search.presenter.SearchPresenter; +import com.yizhuan.erban.ui.search.view.ISearchView; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.VerticalDecoration; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomHistoryInfo; +import com.yizhuan.xchat_android_core.community.dynamic.DynamicModel; +import com.yizhuan.xchat_android_core.community.im.DynamicImMsg; +import com.yizhuan.xchat_android_core.community.im.WorldDynamicAttachment; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.room.bean.SearchRoomInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ImeUtil; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + * 搜索界面 + * + * @author chenran + * @date 2017/10/3 + *

+ * jack 修改于 2018/5/2 + */ +@CreatePresenter(SearchPresenter.class) +public class SearchActivity extends BaseMvpActivity implements ISearchView, View.OnClickListener { + private static final String MARK = "isCar"; + private static final String CAR_INFO = "carInfo"; + private static final String WEAR_INFO = "wearInfo"; + private static final String SHOW_HISTORY = "show_history"; + + public static final int CODE_REQUEST_TO_SEARCH = 200; + + private RecyclerView recyclerView; + private SearchAdapter searchAdapter; + protected EditText searchEdit; + private ImageView ivBack; + private TextView tvSearch; + private ImageView ivClearText; + + private View clSearchHistoryContainer; + private RecyclerView rvSearchHistory; + private View flClearSearchHistory; + + private View clRoomHistoryContainer; + private RecyclerView rvRoomHistory; + private View flClearRoomHistory; + + private CarInfo carInfo; + private HeadWearInfo wearInfo; + protected int type = AbstractSelectFriendAction.TYPE_NORMAL; + private int secondOperator = -1; + private boolean mShowHistory = false; + + private SearchHistoryAdapter mSearchHistoryAdapter; + private RoomHistoryAdapter mRoomHistoryAdapter; + private List mSearchHistoryList = new ArrayList<>(20); + + public static void start(Context context, CarInfo carInfo) { + Intent intent = new Intent(context, SearchActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_CAR); + intent.putExtra(CAR_INFO, carInfo); + context.startActivity(intent); + } + + public static void start(Context context, HeadWearInfo wearInfo) { + Intent intent = new Intent(context, SearchActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_WEAR); + intent.putExtra(WEAR_INFO, wearInfo); + context.startActivity(intent); + } + + public static void start(Context context) { + Intent intent = new Intent(context, SearchActivity.class); + intent.putExtra(SHOW_HISTORY, true); + context.startActivity(intent); + } + + public static void startForSharing(Activity activity, int shareType) { + Intent intent = new Intent(activity, SearchActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_SHARE); + intent.putExtra(SelectFriendActivity.KEY_SECOND_OPERATOR, shareType); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SEARCH); + } + + public static void startForShareDynamic(Activity activity, DynamicImMsg msg) { + Intent intent = new Intent(activity, SearchActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC); + intent.putExtra(SelectFriendActivity.EXTRA_DYNAMIC_DATA, msg); + activity.startActivityForResult(intent, CODE_REQUEST_TO_SEARCH); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_search); + initView(); + } + + private void initView() { + mShowHistory = getIntent().getBooleanExtra(SHOW_HISTORY, false); + + type = getIntent().getIntExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_NORMAL); + secondOperator = getIntent().getIntExtra(SelectFriendActivity.KEY_SECOND_OPERATOR,-1); + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + carInfo = (CarInfo) getIntent().getSerializableExtra(CAR_INFO); + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + wearInfo = (HeadWearInfo) getIntent().getSerializableExtra(WEAR_INFO); + break; + } + + clSearchHistoryContainer = findViewById(R.id.cl_search_history_container); + rvSearchHistory = findViewById(R.id.rv_search_history); + flClearSearchHistory = findViewById(R.id.fl_clear_search_history); + flClearSearchHistory.setOnClickListener(this); + + clRoomHistoryContainer = findViewById(R.id.cl_room_history_container); + rvRoomHistory = findViewById(R.id.rv_room_history); + flClearRoomHistory = findViewById(R.id.fl_clear_room_history); + flClearRoomHistory.setOnClickListener(this); + + recyclerView = findViewById(R.id.recycler_view); + searchEdit = findViewById(R.id.search_edit); + searchEdit.addTextChangedListener(textWatcher); + searchEdit.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + searchEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + toSearch(); + return true; + } + return false; + + } + }); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + searchAdapter = new SearchAdapter(this, null); + searchAdapter.setType(type); + searchAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + SearchRoomInfo item = (SearchRoomInfo) adapter.getData().get(position); + showSureDialog(item.getUid() + "",item.getAvatar(), item.getNick()); + } + }); + recyclerView.setAdapter(searchAdapter); + + ivBack = findViewById(R.id.iv_back); + ivBack.setOnClickListener(this); + + tvSearch = findViewById(R.id.tv_search); + tvSearch.setOnClickListener(this); + + ivClearText = findViewById(R.id.iv_clear_text); + ivClearText.setOnClickListener(this); + ivClearText.setVisibility(View.GONE); + + if (mShowHistory) { + showSearchHistory(); + showRoomHistory(); + } + + } + + private void addHistory(String record) { + if (mShowHistory) { + for (String sub : mSearchHistoryList) { + if (sub.equals(record)) { + mSearchHistoryList.remove(record); + break; + } + } + + mSearchHistoryList.add(0, record); + while (mSearchHistoryList.size() > 20) { + mSearchHistoryList.remove(20); + } + mSearchHistoryAdapter.notifyDataSetChanged(); + } + } + + private void showSearchHistory() { + + mSearchHistoryAdapter = new SearchHistoryAdapter(mSearchHistoryList); + rvSearchHistory.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rvSearchHistory.addItemDecoration(new VerticalDecoration(SizeUtils.dp2px(this, 10), false, true)); + mSearchHistoryAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SEARCH_RECENT_SEARCH, "最近搜索记录"); + + List list = adapter.getData(); + if (position >= 0 && position < list.size()) { + String record = list.get(position); + searchEdit.setText(record); + } + + } + }); + rvSearchHistory.setAdapter(mSearchHistoryAdapter); + + String strSearchHistory = (String) SharedPreferenceUtils.get(SharedPreferenceUtils.SEARCH_HISTORY + AuthModel.get().getCurrentUid(), + ""); + + if (TextUtils.isEmpty(strSearchHistory)) { + clSearchHistoryContainer.setVisibility(View.GONE); + } else { + clSearchHistoryContainer.setVisibility(View.VISIBLE); + String[] split = strSearchHistory.split(","); + + for (String sub : split) { + mSearchHistoryList.add(sub); + } + + mSearchHistoryAdapter.notifyDataSetChanged(); + } + } + + private void showRoomHistory() { + mRoomHistoryAdapter = new RoomHistoryAdapter(null); + rvRoomHistory.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); + rvRoomHistory.addItemDecoration(new VerticalDecoration(SizeUtils.dp2px(this, 10), false, true)); + mRoomHistoryAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SEARCH_RECENT_ENTER_ROOM, "最近进房记录"); + + List list = adapter.getData(); + if (position >= 0 && position < list.size()) { + ImeUtil.hideIME(SearchActivity.this, tvSearch); + RoomHistoryInfo record = list.get(position); + if (record.isValid()) { + list.remove(position); + list.add(0, record); + mRoomHistoryAdapter.setNewData(list); + } + AVRoomActivity.start(SearchActivity.this, record.getRoomUid()); + + + } + + } + }); + rvRoomHistory.setAdapter(mRoomHistoryAdapter); + getMvpPresenter().getInRoomRecord(); + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s.toString())) { + ivClearText.setVisibility(View.GONE); + showHistory(); + } else { + ivClearText.setVisibility(View.VISIBLE); + } + } + }; + + + @Override + public void update(List homeRooms) { + if (homeRooms != null && homeRooms.size() > 0) { + hideStatus(); + searchAdapter.setNewData(homeRooms); + searchAdapter.notifyDataSetChanged(); + } else { + searchAdapter.setNewData(null); + showNoData(R.drawable.icon_common_failure, getString(R.string.dearch_no_data)); + } + } + + @Override + public void showToast(String msg) { + toast(msg); + } + + @Override + public void getInRoomRecordSuccess(List list) { + if (list != null && list.size() > 0) { + clRoomHistoryContainer.setVisibility(View.VISIBLE); + mRoomHistoryAdapter.setNewData(list); + + } else { + clRoomHistoryContainer.setVisibility(View.GONE); + } + + } + + @Override + public void getInRoomRecordFail(String error) { + clRoomHistoryContainer.setVisibility(View.GONE); + } + + @Override + public void deleteInRoomRecordSuccess() { + clRoomHistoryContainer.setVisibility(View.GONE); + } + + @Override + public void deleteInRoomRecordFail(String error) { + toast(error); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_back: + finish(); + break; + + case R.id.tv_search: + toSearch(); + break; + + case R.id.iv_clear_text: + searchEdit.setText(""); + showHistory(); + break; + + case R.id.fl_clear_search_history: + getDialogManager().showOkCancelDialog("确定清空搜索记录吗?", "清空", "手滑了", new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + clearSearchHistory(); + } + }); + break; + + case R.id.fl_clear_room_history: + getDialogManager().showOkCancelDialog("确定清空进房记录吗?", "清空", "手滑了", new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + getMvpPresenter().deleteInRoomRecord(); + } + }); + break; + } + + } + + private void toSearch() { + String str = searchEdit.getText().toString(); + if (TextUtils.isEmpty(str)) { + SingleToastUtil.showToastShort("请输入搜索内容!"); + showHistory(); + return; + } else { + clSearchHistoryContainer.setVisibility(View.GONE); + clRoomHistoryContainer.setVisibility(View.GONE); + } + addHistory(str); + ImeUtil.hideIME(this, tvSearch); + getMvpPresenter().searchRooms(str); + + } + + private void clearSearchHistory() { + clSearchHistoryContainer.setVisibility(View.GONE); + mSearchHistoryList.clear(); + mSearchHistoryAdapter.notifyDataSetChanged(); + SharedPreferenceUtils.put(SharedPreferenceUtils.SEARCH_HISTORY + AuthModel.get().getCurrentUid(), ""); + } + + public void showSureDialog(String targetId, String avatar, String nick) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + if (carInfo == null) { + return; + } + long targetUid = JavaUtil.str2long(targetId); + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setTargetUid(targetUid) + .setNick(nick) + .setType(DecorationSaleType.SEND_CAR) + .setDecoration(carInfo) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(context, getDialogManager(), + options); + helper.showBuyOrDonateDialog(); + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + if (wearInfo == null) { + return; + } + targetUid = JavaUtil.str2long(targetId); + options = new DecorationDialogHelper.Builder() + .setTargetUid(targetUid) + .setNick(nick) + .setType(DecorationSaleType.SEND_HEAD_WEAR) + .setDecoration(wearInfo) + .create(); + helper = new DecorationDialogHelper(context, getDialogManager(), + options); + helper.showBuyOrDonateDialog(); + break; + + case AbstractSelectFriendAction.TYPE_SHARE: + String msg = ""; + if (SelectFriendActivity.CODE_REQUEST_TO_SHARE_FAMILY == secondOperator){ + msg = getResources().getString(R.string.family_invite_friends_slogan); + } + getDialogManager().showInAppSharingConfirmDialog(avatar, nick, msg, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + Intent intent = new Intent(); + intent.putExtra(SelectFriendActivity.EXTRA_TARGET_UID, targetId); + intent.putExtra(SelectFriendActivity.EXTRA_TARGET_NAME, nick); + setResult(Activity.RESULT_OK, intent); + finish(); + } + }); + break; + case AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC: + DynamicImMsg dynamicImMsg = (DynamicImMsg) getIntent().getSerializableExtra( + SelectFriendActivity.EXTRA_DYNAMIC_DATA); + if (dynamicImMsg == null) { + return; + } + getDialogManager().showOkCancelDialog("确认分享给" + nick + "?", () -> { + //发出自定义消息 + IMMessage message = WorldDynamicAttachment.createShareMsg(dynamicImMsg, targetId); + IMNetEaseManager.get().sendMessage(message) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Boolean aBoolean, String error) { + super.accept(aBoolean, error); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + SingleToastUtil.showToast("分享成功"); + DynamicModel.get().reportShare(dynamicImMsg.getPublishUid(), + dynamicImMsg.getWorldId(), dynamicImMsg.getDynamicId()) + .subscribe(); + } + } + }); + setResult(RESULT_OK); + finish(); + }); + break; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mShowHistory && mSearchHistoryList.size() > 0) { + StringBuilder builder = new StringBuilder(); + for (String sub : mSearchHistoryList) { + builder.append(sub); + builder.append(","); + } + + if (builder.length() > 0) { + builder.deleteCharAt(builder.length() - 1); + SharedPreferenceUtils.put(SharedPreferenceUtils.SEARCH_HISTORY + AuthModel.get().getCurrentUid(), builder.toString()); + } + + } + } + + private void showHistory() { + hideStatus(); + if (searchAdapter != null) { + searchAdapter.setNewData(null); + } + if (mShowHistory) { + clSearchHistoryContainer.setVisibility(mSearchHistoryList != null && mSearchHistoryList.size() > 0 ? + View.VISIBLE : View.GONE); + + if (mRoomHistoryAdapter != null) { + List roomHistoryInfos = mRoomHistoryAdapter.getData(); + clRoomHistoryContainer.setVisibility(roomHistoryInfos.size() > 0 ? + View.VISIBLE : View.GONE); + + } else { + clRoomHistoryContainer.setVisibility(View.GONE); + } + + } else { + clSearchHistoryContainer.setVisibility(View.GONE); + clRoomHistoryContainer.setVisibility(View.GONE); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/SearchAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/search/SearchAdapter.java new file mode 100644 index 000000000..6f14dfc1d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/SearchAdapter.java @@ -0,0 +1,159 @@ +package com.yizhuan.erban.ui.search; + +import android.content.Context; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.coorchice.library.SuperTextView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.SearchRoomInfo; +import com.yizhuan.xchat_android_core.user.UserModel; + +import java.util.List; + +/** + * @author chenran + * @date 2017/10/3 + */ +public class SearchAdapter extends BaseQuickAdapter { + + private Context context; + private int type; + + public void setType(int type) { + this.type = type; + } + + public SearchAdapter(Context context, List homeRoomList) { + super(R.layout.list_item_search); + this.context = context; + } + + @Override + protected void convert(ViewHolder holder, SearchRoomInfo item) { + holder.userName.setText(item.getNick() != null ? item.getNick().replaceAll(RegexUtil.getNotPrintableStringReg(), "?"):""); + + holder.mNobleAvatarView.setSize(40, 58, 15); + holder.mNobleAvatarView.setData(item.getAvatar(), item.nobleUsers); + + holder.erbanNo.setText(context.getString(R.string.me_user_id, item.getErbanNo())); + holder.mIvGoodNumber.setVisibility(item.hasPrettyErbanNo ? View.VISIBLE : View.GONE); + holder.officialView.setVisibility(item.isOfficial() ? View.VISIBLE : View.GONE); + + if (item.nobleUsers != null) { + String badgeByLevel = NobleUtil.getBadgeByLevel(item.nobleUsers.getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) + NobleUtil.loadResource(badgeByLevel, holder.mIvNobleLevel); + holder.mIvNobleLevel.setVisibility(TextUtils.isEmpty(badgeByLevel) ? View.GONE : View.VISIBLE); + } + holder.mIvNobleLevel.setVisibility(item.nobleUsers == null ? View.GONE : View.VISIBLE); + + holder.container.setOnClickListener(v -> { + if (type == AbstractSelectFriendAction.TYPE_NORMAL) { + UserInfoActivity.Companion.start(context, item.getUid()); + } + }); + if (item.getGender() == 1) { + holder.mIvSex.setVisibility(View.VISIBLE); + holder.mIvSex.setImageResource(R.drawable.ic_male); + } else if (item.getGender() == 2) { + holder.mIvSex.setVisibility(View.VISIBLE); + holder.mIvSex.setImageResource(R.drawable.ic_female); + } else { + holder.mIvSex.setVisibility(View.GONE); + } + + holder.mIvUserLevel.setVisibility(View.GONE); + UserLevelVo userLevelVo = item.userLevelVo; + if (userLevelVo != null && !TextUtils.isEmpty(userLevelVo.getExperUrl())) { + holder.mIvUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(context, userLevelVo.getExperUrl(), holder.mIvUserLevel); + } + //魅力等级,只在模厅情况下显示,原来逻辑不修改 + holder.mIvUserCharm.setVisibility(View.GONE); + if ((type == AbstractSelectFriendAction.TYPE_CAR || type == AbstractSelectFriendAction.TYPE_WEAR) && AuthModel.get().getCurrentUid()!=item.getUid()){ + holder.flOpLayout.setVisibility(View.VISIBLE); + holder.tvSend.setVisibility(View.VISIBLE); + holder.stvOp.setVisibility(View.GONE); + } else if (type == AbstractSelectFriendAction.TYPE_MODULE_HALL) { + //模厅搜索 + holder.tvSend.setVisibility(View.GONE); + holder.stvOp.setVisibility(View.VISIBLE); + holder.stvOp.setText("添加"); + holder.addOnClickListener(R.id.stv_op); + if (!UserModel.get().isMyseft(item.getUid())) { + holder.flOpLayout.setVisibility(View.VISIBLE); + } else { + holder.flOpLayout.setVisibility(View.GONE); + } + if (userLevelVo != null && !TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + holder.mIvUserCharm.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(context, userLevelVo.getCharmUrl(), holder.mIvUserCharm); + } else { + holder.mIvUserCharm.setVisibility(View.GONE); + } + //贵族不显示 + holder.mIvNobleLevel.setVisibility(View.GONE); + //靓号不显示 + holder.mIvGoodNumber.setVisibility(View.GONE); + } else { + holder.flOpLayout.setVisibility(View.GONE); + } + holder.addOnClickListener(R.id.tv_send); + if (type == AbstractSelectFriendAction.TYPE_SHARE + || type == AbstractSelectFriendAction.TYPE_WORLD_DYNAMIC) { + holder.addOnClickListener(R.id.container); + } + } + + static class ViewHolder extends BaseViewHolder { + TextView userName; + TextView tvSend; + TextView roomTitle; + TextView erbanNo; + RelativeLayout container; + ImageView mIvGoodNumber; + ImageView officialView; + private NobleAvatarView mNobleAvatarView; + private AppCompatImageView mIvNobleLevel; + private AppCompatImageView mIvUserLevel; + private AppCompatImageView mIvUserCharm; + private ImageView mIvSex; + private FrameLayout flOpLayout; + private SuperTextView stvOp; + + public ViewHolder(View itemView) { + super(itemView); + userName = (TextView) itemView.findViewById(R.id.user_name); + roomTitle = (TextView) itemView.findViewById(R.id.room_title); + tvSend = (TextView) itemView.findViewById(R.id.tv_send); + erbanNo = (TextView) itemView.findViewById(R.id.erban_no); + container = (RelativeLayout) itemView.findViewById(R.id.container); + mIvGoodNumber = itemView.findViewById(R.id.iv_good_number); + officialView = itemView.findViewById(R.id.iv_user_official); + mNobleAvatarView = itemView.findViewById(R.id.noble_avatar_view); + mIvNobleLevel = itemView.findViewById(R.id.iv_noble_level); + mIvSex = itemView.findViewById(R.id.sex); + mIvUserLevel = itemView.findViewById(R.id.iv_user_level); + flOpLayout = itemView.findViewById(R.id.fl_op_layout); + stvOp = itemView.findViewById(R.id.stv_op); + mIvUserCharm = itemView.findViewById(R.id.iv_user_charm); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/SearchHistoryAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/search/SearchHistoryAdapter.java new file mode 100644 index 000000000..09d641c36 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/SearchHistoryAdapter.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.ui.search; + +import android.support.annotation.Nullable; +import android.text.TextUtils; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; + +import java.util.List; + +public class SearchHistoryAdapter extends BaseQuickAdapter { + + public SearchHistoryAdapter(@Nullable List data) { + super(R.layout.item_search_history, data); + } + + @Override + protected void convert(BaseViewHolder helper, String item) { + if (TextUtils.isEmpty(item)) { + return; + } + + if (item.length() < 15) { + helper.setText(R.id.tv_search_history, item); + } else { + helper.setText(R.id.tv_search_history, item.substring(0, 14) + "..."); + } + helper.addOnClickListener(R.id.tv_search_history); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/presenter/SearchPresenter.java b/app/src/main/java/com/yizhuan/erban/ui/search/presenter/SearchPresenter.java new file mode 100644 index 000000000..c26719513 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/presenter/SearchPresenter.java @@ -0,0 +1,108 @@ +package com.yizhuan.erban.ui.search.presenter; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.ui.search.view.ISearchView; +import com.yizhuan.xchat_android_core.room.bean.SearchRoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.utils.NetworkUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/2 + */ + +public class SearchPresenter extends BaseMvpPresenter { + + + public SearchPresenter() { + + } + + @Override + public void onCreatePresenter(@Nullable Bundle saveState) { + super.onCreatePresenter(saveState); + + } + + private void onSearchRoom(List homeRooms) { + getMvpView().update(homeRooms); + } + + private void onSearchRoomFail(String msg) { + if (NetworkUtils.isNetworkAvailable(BasicConfig.INSTANCE.getAppContext())) { + getMvpView().showToast(msg); + getMvpView().showNoData(); + } else { + getMvpView().showNetworkErr(); + } + } + + /** + * 搜索房间 + * @param str + */ + @SuppressLint("CheckResult") + public void searchRooms(String str) { + AvRoomModel.get() + .roomSearch(str) + .compose(bindToLifecycle()) + .subscribe((homeTabResult, throwable) -> { + if (throwable != null) { + onSearchRoomFail(throwable.getMessage()); + } else if (homeTabResult != null && homeTabResult.isSuccess()) { + onSearchRoom(homeTabResult.getData()); + } else if (homeTabResult != null && !homeTabResult.isSuccess()){ + onSearchRoomFail(homeTabResult.getError()); + } else { + onSearchRoomFail("未知错误"); + } + }); + } + + @SuppressLint("CheckResult") + public void getInRoomRecord() { + UserModel.get() + .getInRoomRecord() + .compose(bindToLifecycle()) + .subscribe((homeTabResult, throwable) -> { + if (throwable != null) { + if (mMvpView != null) { + mMvpView.getInRoomRecordFail(throwable.getMessage()); + } + } else { + if (mMvpView != null) { + mMvpView.getInRoomRecordSuccess(homeTabResult); + } + } + }); + } + + @SuppressLint("CheckResult") + public void deleteInRoomRecord() { + UserModel.get() + .deleteInRoomRecord() + .compose(bindToLifecycle()) + .subscribe((homeTabResult, throwable) -> { + if (homeTabResult.isSuccess()) { + if (mMvpView != null) { + mMvpView.deleteInRoomRecordSuccess(); + } + + } else { + if (mMvpView != null) { + mMvpView.deleteInRoomRecordFail(homeTabResult.getError()); + } + + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/search/view/ISearchView.java b/app/src/main/java/com/yizhuan/erban/ui/search/view/ISearchView.java new file mode 100644 index 000000000..7c100f89e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/search/view/ISearchView.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.ui.search.view; + +import com.yizhuan.xchat_android_core.bean.RoomHistoryInfo; +import com.yizhuan.xchat_android_core.room.bean.SearchRoomInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + * @author jack + * @Description + * @Date 2018/5/2 + */ + +public interface ISearchView extends IMvpBaseView { + + void update(List homeRooms); + + void showNoData(); + + void showNetworkErr(); + + void showToast(String msg); + + void getInRoomRecordSuccess(List list); + void getInRoomRecordFail(String error); + + void deleteInRoomRecordSuccess(); + void deleteInRoomRecordFail(String error); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/FeedbackActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/FeedbackActivity.java new file mode 100644 index 000000000..9932dce62 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/FeedbackActivity.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.ui.setting; + +import android.os.Bundle; +import android.widget.Button; +import android.widget.EditText; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.home.model.HomeModel; + + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class FeedbackActivity extends BaseActivity { + + private EditText edtContent; + private EditText edtContact; + private Button btnCommit; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_feedback); + initTitleBar("反馈"); + initView(); + initData(); + SetListener(); + } + + private void SetListener() { + btnCommit.setOnClickListener(v -> + HomeModel.get().commitFeedback(AuthModel.get().getCurrentUid(), + edtContent.getText().toString(), + edtContact.getText().toString() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onCommitFeedback(); + } + + @Override + public void onError(Throwable e) { + onCommitFeedbackFail(e.getMessage()); + } + }) + + ); + } + + private void initData() { + + } + + private void initView() { + edtContent = findViewById(R.id.edt_content); + edtContact = findViewById(R.id.edt_contact); + btnCommit = findViewById(R.id.btn_commit); + } + + public void onCommitFeedback(){ + getDialogManager().showProgressDialog(FeedbackActivity.this, "正在上传请稍后..."); + toast("提交成功"); + finish(); + + } + + public void onCommitFeedbackFail(String error){ +// toast(error); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/LabActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/LabActivity.java new file mode 100644 index 000000000..8c2d7f491 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/LabActivity.java @@ -0,0 +1,75 @@ +package com.yizhuan.erban.ui.setting; + +import android.os.Bundle; +import android.view.View; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.DemoCache; +import com.yizhuan.xchat_android_core.Env; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.domain.model.DomainModel; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.pref.CommonPref; + +import java.util.ArrayList; + +/** + * Created by chenran on 2017/10/16. + */ + +public class LabActivity extends BaseActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_lab); + + int enviroment = CommonPref.instance(BasicConfig.INSTANCE.getAppContext()).getInt(Env.KEY_ENVIRONMENT); + //根据ID找到RadioGroup实例 + RadioGroup group = (RadioGroup) this.findViewById(R.id.radioGroup); + RadioButton rbRelease = (RadioButton) findViewById(R.id.rb_release); + rbRelease.setTag(Env.EnvType.Release); + RadioButton rbStaging = (RadioButton) findViewById(R.id.rb_staging); + rbStaging.setTag(Env.EnvType.Staging); + RadioButton rbDebug = (RadioButton) findViewById(R.id.rb_debug); + rbDebug.setTag(Env.EnvType.Debug); + Env.EnvType envType = Env.getCurrentEnv(); + if (envType == null) { + toast("发生了一个错误,请找开发"); + return; + } + //设置选中 + for (int i = 0; i < group.getChildCount(); i++) { + View view = group.getChildAt(i); + if (view.getTag() == envType) { + group.check(view.getId()); + break; + } + } + + + //绑定一个匿名监听器 + group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(RadioGroup arg0, int arg1) { + //获取变更后的选中项的ID + Object obj = findViewById(arg1).getTag(); + if (!(obj instanceof Env.EnvType)) { + toast("发生了一些错误,请找开发或者重新打开app"); + return; + } + toast("请手动关闭APP重新打开!!"); + Env.changeEnv((Env.EnvType) obj); + // 清理缓存 + SharedPreferenceUtils.remove(DomainModel.KEY_AVAILABLE_HOST); + DemoCache.saveInitDataApiHost(new ArrayList<>()); + AuthModel.get().logout().subscribe(); + finish(); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/ModifyPwdActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/ModifyPwdActivity.java new file mode 100644 index 000000000..9edaf2238 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/ModifyPwdActivity.java @@ -0,0 +1,272 @@ +package com.yizhuan.erban.ui.setting; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.text.InputFilter; +import android.text.TextUtils; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityModifyPwdBinding; +import com.yizhuan.erban.ui.login.PasswordValidator; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.activity_modify_pwd) +public class ModifyPwdActivity extends BaseBindingActivity { + public static final int LOGIN_PWD = 1; + public static final int SET_LOGIN_PWD = 4; + public static final int PAY_PWD = 2; + public static final int FOGERT_PAY_PWD = 3; + public static final int RESET_PAY_PWD = 5; + + private int type; + + private PasswordValidator passwordValidator = new PasswordValidator(); + + public static void start(Context context, int type) { + Intent intent = new Intent(context, ModifyPwdActivity.class); + intent.putExtra("type", type); + context.startActivity(intent); + } + + @Override + protected void init() { + type = getIntent().getIntExtra("type", 1); + if (type == PAY_PWD && !UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()) { + type = FOGERT_PAY_PWD; + } + if (type == LOGIN_PWD) { + if (UserModel.get().getCacheLoginUserInfo().isBindPasswd()) { + setModifyPwdUI(); + } else { + setLoginPwdUI(); + } + } else if (type == PAY_PWD) { + setModifyPayPwdUI(); + setEditStyle(); + + } else if (type == FOGERT_PAY_PWD) { + setPayPwdUI("设置支付密码"); + setEditStyle(); + } else if (type == RESET_PAY_PWD) { + setPayPwdUI("重置支付密码"); + setEditStyle(); + } + mBinding.setClick(this); + + } + + private void setModifyPwdUI() { + initTitleBar("修改登录密码"); + + mBinding.edCurrentPwd.setTitleHint("原密码"); + mBinding.edCurrentPwd.setEditHint("请输入当前登录密码"); + mBinding.edPwd.setTitleHint("新密码"); + mBinding.edPwd.setEditHint("请输入新的登录密码"); + mBinding.edSurePwd.setTitleHint("确认密码"); + mBinding.edSurePwd.setEditHint("再次确认新的登录密码"); + mBinding.tvPasswordTip.setVisibility(View.VISIBLE); + } + + private void setLoginPwdUI() { + type = SET_LOGIN_PWD; + initTitleBar("设置登录密码"); + + mBinding.edCurrentPwd.setVisibility(View.GONE); + mBinding.btnForget.setVisibility(View.GONE); + + mBinding.edPwd.setTitleHint("设置密码"); + mBinding.edPwd.setEditHint("输入登录密码"); + mBinding.edSurePwd.setTitleHint("确认密码"); + mBinding.edSurePwd.setEditHint("再次输入登录密码"); + mBinding.tvPasswordTip.setVisibility(View.VISIBLE); + } + + private void setModifyPayPwdUI() { + initTitleBar("修改支付密码"); + mBinding.edCurrentPwd.setTitleHint("原密码"); + mBinding.edCurrentPwd.setEditHint("请输入当前支付密码"); + mBinding.edPwd.setTitleHint("新密码"); + mBinding.edPwd.setEditHint("请输入新的支付密码"); + mBinding.edSurePwd.setTitleHint("确认密码"); + mBinding.edSurePwd.setEditHint("再次确认新的支付密码"); + mBinding.tvPasswordTip.setVisibility(View.GONE); + + } + + private void setPayPwdUI(String title) { + initTitleBar(title); + mBinding.edCurrentPwd.setVisibility(View.GONE); + mBinding.btnForget.setVisibility(View.GONE); + mBinding.edPwd.setTitleHint("设置密码"); + mBinding.edPwd.setEditHint("输入支付密码"); + mBinding.edSurePwd.setTitleHint("确认密码"); + mBinding.edSurePwd.setEditHint("再次输入支付密码"); + mBinding.tvPasswordTip.setVisibility(View.GONE); + } + + private void setEditStyle() { + mBinding.edPwd.setIntegerType(); + mBinding.edSurePwd.setIntegerType(); + mBinding.edPwd.getEditText().setFilters(new InputFilter[]{new InputFilter.LengthFilter(6)}); + mBinding.edSurePwd.getEditText().setFilters(new InputFilter[]{new InputFilter.LengthFilter(6)}); + mBinding.edPwd.setPay(true); + mBinding.edSurePwd.setPay(true); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.btn_commit: + commit(); + break; + case R.id.btn_forget: + if (type == PAY_PWD) { + VerifyPhoneActivity.startForResult(this, true); + } else { + UIHelper.showForgetPswAct(ModifyPwdActivity.this); + } + break; + } + } + + @SuppressLint("CheckResult") + private void commit() { + if ((TextUtils.isEmpty(mBinding.edPwd.getText()) && type != FOGERT_PAY_PWD && type != RESET_PAY_PWD) || TextUtils.isEmpty(mBinding.edSurePwd.getText())) { + toast("密码不能为空"); + return; + } + if (!mBinding.edPwd.getText().equals(mBinding.edSurePwd.getText())) { + toast("两次密码不一致"); + return; + } + if (type == PAY_PWD || type == FOGERT_PAY_PWD || type == RESET_PAY_PWD) { + if (mBinding.edPwd.getText().length() != 6) { + toast("密码长度必须为6位"); + return; + } + } else { + if (!passwordValidator.isValid(mBinding.edPwd.getText())) { + toast(passwordValidator.getErrorMessage()); + return; + } + } + + if (type == LOGIN_PWD) { + getDialogManager().showProgressDialog(ModifyPwdActivity.this, "处理中..."); + AuthModel.get().modifyLoginPwd( + UserModel.get().getCacheLoginUserInfo().getPhone(), + DESAndBase64(mBinding.edCurrentPwd.getText()), + DESAndBase64(mBinding.edPwd.getText()) + ) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + UserModel.get().updateCurrentUserInfo().subscribe(); + toast("修改成功"); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + + } else if (type == PAY_PWD) { + getDialogManager().showProgressDialog(ModifyPwdActivity.this, "处理中..."); + UserModel.get().resetPayPwd(mBinding.edCurrentPwd.getText(), + mBinding.edPwd.getText()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + UserModel.get().updateCurrentUserInfo().subscribe(); + toast("修改成功"); + finish(); + } + }); + } else if (type == FOGERT_PAY_PWD || type == RESET_PAY_PWD) { + getDialogManager().showProgressDialog(ModifyPwdActivity.this, "处理中..."); + UserModel.get().setPayPwd(mBinding.edPwd.getText()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + UserModel.get().updateCurrentUserInfo().subscribe(); + toast("修改成功"); + finish(); + } + }); + } else if (type == SET_LOGIN_PWD) { + getDialogManager().showProgressDialog(ModifyPwdActivity.this, "处理中..."); + AuthModel.get().setLoginPwd( + UserModel.get().getCacheLoginUserInfo().getPhone(), + DESAndBase64(mBinding.edPwd.getText()) + ) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + UserModel.get().updateCurrentUserInfo().subscribe(); + toast("修改成功"); + finish(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == VerifyPhoneActivity.REQUEST_CHECK_VALID_PHONE && resultCode == RESULT_OK) { + type = FOGERT_PAY_PWD; + setPayPwdUI("重置支付密码"); + setEditStyle(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/NoticeSettingActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/NoticeSettingActivity.java new file mode 100644 index 000000000..a974f1096 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/NoticeSettingActivity.java @@ -0,0 +1,122 @@ +package com.yizhuan.erban.ui.setting; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.TutuSwitchView; +import com.yizhuan.xchat_android_core.settings.SettingsModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * create by lvzebiao @2019/12/23 + */ +public class NoticeSettingActivity extends BaseActivity { + + @BindView(R.id.ll_container) + LinearLayout llContainer; + + public static void start(Context context) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_NOTICE, + "点击进入通知提醒设置的次数"); + Intent intent = new Intent(context, NoticeSettingActivity.class); + context.startActivity(intent); + } + + private View systemNoticeView; + + private TutuSwitchView switchSystemNotice; + + private UserInfo.Location userExpand; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_notice_setting); + ButterKnife.bind(this); + initTitleBar(R.string.notice_setting); + + userExpand = UserModel.get().getUserExpand(); + if (userExpand == null) { + return; + } + + initSystemNotice(); + + } + + private void initSystemNotice() { + + if (systemNoticeView == null) { + systemNoticeView = LayoutInflater.from(context).inflate(R.layout.item_system_notice, null); + switchSystemNotice = systemNoticeView.findViewById(R.id.switch_notice); + llContainer.addView(systemNoticeView, new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + getResources().getDimensionPixelOffset(R.dimen.dp_setting_sys_notice_item_height)) + ); + setName(systemNoticeView, "系统通知"); + setDesc(systemNoticeView, "关闭后,系统消息和官方小秘书不再提示"); + } + switchSystemNotice.setOn(userExpand.isSysMsgNotify()); + + switchSystemNotice.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_SYSTEM_NOTICE, + "点击设置系统消息提醒的次数" + isOn); + SettingsModel.get().setSysMsgNotify(isOn) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error == null) { + userExpand.setSysMsgNotify(isOn); + } else { + toast(error); + } + } + }); + + } + }); + + } + + private void setName(View targetView, String name) { + if (targetView == null) { + return; + } + TextView tvName = targetView.findViewById(R.id.tv_name); + if (tvName != null) { + tvName.setText(name); + } + } + + private void setDesc(View targetView, String desc) { + if (targetView == null) { + return; + } + TextView tvDesc = targetView.findViewById(R.id.tv_desc); + if (tvDesc != null) { + tvDesc.setText(desc); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/PrivacySettingActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/PrivacySettingActivity.java new file mode 100644 index 000000000..f20ef253e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/PrivacySettingActivity.java @@ -0,0 +1,264 @@ +package com.yizhuan.erban.ui.setting; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.v4.app.ActivityCompat; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.TutuSwitchView; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.settings.SettingsModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.widget.IOSSwitchView; + +import java.util.concurrent.CancellationException; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Function; + +/** + * create by lvzebiao @2019/12/23 + */ +public class PrivacySettingActivity extends BaseActivity { + + @BindView(R.id.switch_location) + TutuSwitchView switchLocation; + @BindView(R.id.switch_age) + TutuSwitchView switchAge; + @BindView(R.id.switch_match_chat) + TutuSwitchView switchMatchChat; + + private Disposable locationDisposable; + private Disposable ageDisposable; + private Disposable matchDisposable; + + public static void start(Context context) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_SECRET, + "点击进入隐私设置的次数"); + Intent intent = new Intent(context, PrivacySettingActivity.class); + context.startActivity(intent); + } + + @SuppressLint("CheckResult") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_privacy_setting); + ButterKnife.bind(this); + initTitleBar(R.string.privacy_setting); + initData(); + initListener(); + } + + + @SuppressLint("CheckResult") + private void initData() { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + finish(); + return; + } + boolean isShowLocation = true; + boolean isShowAge = true; + boolean isMatchChat = true; + if (userInfo.getUserExpand() != null) { + isShowLocation = userInfo.getUserExpand().isShowLocation(); + isShowAge = userInfo.getUserExpand().isShowAge(); + isMatchChat = userInfo.getUserExpand().isMatchChat(); + } + if (ageDisposable == null || ageDisposable.isDisposed()) { + switchAge.setOn(isShowAge); + } + if (matchDisposable == null || matchDisposable.isDisposed()) { + switchMatchChat.setOn(isMatchChat); + } + + if (isShowLocation) { + if (ActivityCompat.checkSelfPermission(context, + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED + && + ActivityCompat.checkSelfPermission(context, + Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED + ) { + switchLocation.setOn(true); + + } else { + //noinspection ResultOfMethodCallIgnored + SettingsModel.get().showLocation(AuthModel.get().getCurrentUid(), false) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()) + .subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (throwable == null) { + switchLocation.setOn(false); + } else { + switchLocation.setOn(true); + } + + } + }); + + } + + } else if (locationDisposable == null || locationDisposable.isDisposed()) { + switchLocation.setOn(false); + } + } + + private void initListener() { + switchLocation.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + long uid = AuthModel.get().getCurrentUid(); + //如果上一次正在请求,关闭上次请求 + if (locationDisposable != null && !locationDisposable.isDisposed()) { + locationDisposable.dispose(); + } + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_LOCATION, + "点击设置地理位置的次数" + isOn); + locationDisposable = Single.just(isOn) + //检查权限 + .flatMap(new Function>() { + @Override + public SingleSource apply(Boolean aBoolean) throws Exception { + //判断是否开启权限,只有只有打开地理位置才判断,如果是关闭的时候,不需要判断 + if (aBoolean) { + return checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION).compose(bindUntilEvent(ActivityEvent.DESTROY)).singleOrError(); + } else { + return Single.just(true); + } + } + }) + //判断是否有权限去做 + .flatMap(new Function>() { + @Override + public SingleSource apply(Boolean b) throws Exception { + if (b) { + return SettingsModel.get().showLocation(uid, isOn) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()); + } else { + throw new SettingActivity.MissingPermissionException("未获取定位权限,如需在个人资料页展示位置信息,请先打开位置权限"); + } + } + }).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + //过滤关闭请求 + if (throwable instanceof CancellationException) { + return; + } + //缺少权限的时候 + else if (throwable instanceof SettingActivity.MissingPermissionException) { + switchLocation.setOn(false); + } + if (throwable != null && !TextUtils.isEmpty(throwable.getMessage())) { + toast(throwable.getMessage()); + switchLocation.setOn(!isOn); + } + } + }); + + + } + }); + + switchAge.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + long uid = AuthModel.get().getCurrentUid(); + //如果上一次正在请求,关闭上次请求 + if (ageDisposable != null && !ageDisposable.isDisposed()) { + ageDisposable.dispose(); + } + ageDisposable = Single.just(isOn) + .flatMap(new Function>() { + @Override + public SingleSource apply(Boolean b) throws Exception { + return SettingsModel.get().showAge(uid, isOn) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()); + } + }).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + //过滤关闭请求 + if (throwable instanceof CancellationException) { + return; + } + if (throwable != null && !TextUtils.isEmpty(throwable.getMessage())) { + toast(throwable.getMessage()); + switchAge.setOn(!isOn); + } + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_SHOW_AGE, + isOn ? "年龄展示:开" : "年龄展示:关"); + + } + }); + + + } + }); + + switchMatchChat.setOnSwitchStateChangeListener(new IOSSwitchView.OnSwitchStateChangeListener() { + @Override + public void onStateSwitched(boolean isOn) { + long uid = AuthModel.get().getCurrentUid(); + //如果上一次正在请求,关闭上次请求 + if (matchDisposable != null && !matchDisposable.isDisposed()) { + matchDisposable.dispose(); + } + matchDisposable = Single.just(isOn) + .flatMap(new Function>() { + @Override + public SingleSource apply(Boolean b) throws Exception { + return SettingsModel.get().showMatchChat(uid, isOn) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .compose(RxHelper.singleMainResult()) + .compose(RxHelper.handleSchAndExce()); + } + }).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + //过滤关闭请求 + if (throwable instanceof CancellationException) { + return; + } + if (throwable != null && !TextUtils.isEmpty(throwable.getMessage())) { + toast(throwable.getMessage()); + switchMatchChat.setOn(!isOn); + } + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_SETTING_CHAT_MATCHING, + isOn ? "匹配聊天:开" : "匹配聊天:关"); + } + }); + + + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java new file mode 100644 index 000000000..aa7e3e989 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/SettingActivity.java @@ -0,0 +1,317 @@ +package com.yizhuan.erban.ui.setting; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Environment; +import android.support.v4.content.ContextCompat; +import android.text.SpannableString; +import android.text.TextUtils; +import android.view.View; + +import com.tongdaxing.erban.upgrade.AppUpgradeHelper; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.bank_card.activity.BankCardListActivity; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivitySettingBinding; +import com.yizhuan.erban.ui.im.avtivity.BlackListManageActivity; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.login.ShowBindPhoneActivity; +import com.yizhuan.erban.ui.login.helper.LogoutHelper; +import com.yizhuan.erban.ui.user.AboutActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity; +import com.yizhuan.erban.ui.withdraw.bankcard.BindWithdrawBankCardActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrawInfo; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; + +import java.io.File; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * Created by zhouxiangfeng on 2017/4/16. + */ +public class SettingActivity extends BaseActivity implements View.OnClickListener { + + private ActivitySettingBinding settingBinding; + private WithdrawInfo withdrawInfos; + private UserInfo userInfo; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + settingBinding = DataBindingUtil.setContentView(this, R.layout.activity_setting); + settingBinding.setClick(this); + initTitleBar("设置"); + initView(); + initData(); + initListeners(); + } + + private void initListeners() { + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @SuppressLint("CheckResult") + @Override + protected void onResume() { + super.onResume(); + UserModel.get().updateCurrentUserInfo() + .compose(bindToLifecycle()) + .subscribe(info -> { + userInfo = info; + //刷新下界面 + initView(); + if (info != null && info.isBindPhone()) { + setPhoneUI(info.getPhone()); + } else { + setPhoneUI(""); + } + }); + WithdrawModel.get().getWithdrawUserInfo(AuthModel.get().getCurrentUid()) + .subscribe(withdrawInfo -> { + withdrawInfos = withdrawInfo; + if (withdrawInfo != null) { + if (!TextUtils.isEmpty(withdrawInfo.alipayAccount) && !withdrawInfo.alipayAccount.equals("null")) { + setAlipayUI(withdrawInfo.alipayAccount + "(" + withdrawInfo.alipayAccountName + ")"); + } else { + setAlipayUI(""); + } + } + }); + } + + private void setPhoneUI(String phone) { + settingBinding.tvPhone.setText(TextUtils.isEmpty(phone) ? "未绑定" : phone); + settingBinding.tvPhone.setTextColor(TextUtils.isEmpty(phone) ? Color.parseColor("#34EBDE") : ContextCompat.getColor(this, R.color.color_999999)); + } + + private void setAlipayUI(String name) { + settingBinding.tvAlipay.setText(TextUtils.isEmpty(name) ? "未绑定" : name); + settingBinding.tvAlipay.setTextColor(TextUtils.isEmpty(name) ? Color.parseColor("#34EBDE") : ContextCompat.getColor(this, R.color.color_999999)); + } + + private void initData() { + settingBinding.versions.setText("V" + BasicConfig.getLocalVersionName(getApplicationContext())); + + } + + @Override + public void onClick(View view) { + //super.onClick(view); + switch (view.getId()) { + case R.id.rly_content://反馈 + startActivity(new Intent(getApplicationContext(), FeedbackActivity.class)); + break; + case R.id.rly_binder://绑定手机 + getDialogManager().showProgressDialog(SettingActivity.this, "正在查询请稍后..."); + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + ShowBindPhoneActivity.start(SettingActivity.this); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + startActivity(new Intent(SettingActivity.this, BinderPhoneActivity.class)); + } + }); + break; + case R.id.rly_alipay_binder://绑定支付宝 + if (UserModel.get().getCacheLoginUserInfo() == null) { + toast("无当前登录用户信息."); + return; + } + if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) { + Intent intent = new Intent(getApplicationContext(), BinderAlipayActivity.class); + Bundle mBundle = new Bundle(); + mBundle.putSerializable("withdrawInfo", withdrawInfos); + intent.putExtras(mBundle); + startActivity(intent); + } else { + startActivity(new Intent(this, BinderPhoneActivity.class)); + } + break; + case R.id.tv_bank_card: + // 跳转到银行卡列表页面 + BankCardListActivity.start(this); + break; + case R.id.rly_contact_us: + UIHelper.openContactUs(this); + break; + case R.id.rly_help: + UIHelper.showUsinghelp(this); + break; + case R.id.rly_update://关于我们 + startActivity(new Intent(getApplicationContext(), AboutActivity.class)); + break; + case R.id.rly_check://检查更新 + AppUpgradeHelper.checkAppUpgrade(this, true); + + break; + case R.id.rly_lab: + startActivity(new Intent(getApplicationContext(), LabActivity.class)); + break; + case R.id.tv_black_manager: + BlackListManageActivity.start(this); + break; + case R.id.rly_login_pwd: + if (UserModel.get().getCacheLoginUserInfo() == null) { + toast("无当前登录用户信息."); + return; + } + if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) { + ModifyPwdActivity.start(this, ModifyPwdActivity.LOGIN_PWD); + } else { + startActivity(new Intent(this, BinderPhoneActivity.class)); + } + break; + case R.id.rly_pay_pwd: + if (UserModel.get().getCacheLoginUserInfo() == null) { + toast("无当前登录用户信息."); + return; + } + if (UserModel.get().getCacheLoginUserInfo().isBindPhone()) { + ModifyPwdActivity.start(this, ModifyPwdActivity.PAY_PWD); + } else { + startActivity(new Intent(this, BinderPhoneActivity.class)); + } + break; + case R.id.btn_login_out://退出登录 + LogoutHelper.logout(); + finish(); + break; + + case R.id.tv_community_norms: + CommonWebViewActivity.start(this, UriProvider.getCommnunityNorms()); + break; + + case R.id.rly_clear_cache: + getDialogManager().showOkCancelWithTitleDialog("提示", + new SpannableString("确定清除缓存?"), + "确定", "取消", new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + clearCache(); + } + }); + + break; + case R.id.tv_privacy_setting: + PrivacySettingActivity.start(context); + break; + case R.id.tv_notice_setting: + NoticeSettingActivity.start(context); + break; + case R.id.vg_withdraw_bank_card: + start(context, BindWithdrawBankCardActivity.class); + break; + } + } + + private void clearCache() { + try { + + SharedPreferenceUtils.remove(SharedPreferenceUtils.SEARCH_HISTORY + AuthModel.get().getCurrentUid()); + + File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"); + File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache"); + JXFileUtils.deleteFile(appCacheDir); + + toast("清除成功"); + + } catch (Exception ex) { + ex.printStackTrace(); + + } + } + + private void initView() { + //实验室模式只要真实的debug模式 + if (XChatApplication.isRealDebug()) { + settingBinding.rlyLab.setVisibility(View.VISIBLE); + } else { + settingBinding.rlyLab.setVisibility(View.GONE); + } + UserInfo cacheLoginUserInfo = UserModel.get().getCacheLoginUserInfo(); + if (cacheLoginUserInfo == null) return; + if (cacheLoginUserInfo.getBindType() == 1) { + settingBinding.tvThird.setText("微信"); + settingBinding.tvWx.setText("已绑定"); + } else if (cacheLoginUserInfo.getBindType() == 2) { + settingBinding.tvThird.setText("QQ"); + settingBinding.tvWx.setText("已绑定"); + } else { + settingBinding.rlThird.setVisibility(View.GONE); + } + + if (!cacheLoginUserInfo.isBindPasswd()) { + settingBinding.tvModify.setText("设置"); + } else { + settingBinding.tvModify.setText("修改"); + } + if (!cacheLoginUserInfo.isBindPaymentPwd()) { + settingBinding.tvPayModify.setText("设置"); + } else { + settingBinding.tvPayModify.setText("修改"); + } + + //提现银行卡信息 + settingBinding.vgWithdrawBankCard.setVisibility(View.GONE); + if (cacheLoginUserInfo.isBindBankCard()) { + settingBinding.vgWithdrawBankCard.setVisibility(View.VISIBLE); + String wdBankCardNum = cacheLoginUserInfo.getBankCardNum(); + if (wdBankCardNum == null) { + wdBankCardNum = ""; + } + String wdBankCardName = cacheLoginUserInfo.getBankCardName(); + if (wdBankCardName == null) { + wdBankCardName = ""; + } + settingBinding.tvWithdrawBankCard.setText(getString(R.string.text_setting_withdraw_format_bank_card_info, + wdBankCardNum, wdBankCardName)); + } + + } + + public static class MissingPermissionException extends RuntimeException { + public MissingPermissionException(String message) { + super(message); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/setting/VerifyPhoneActivity.java b/app/src/main/java/com/yizhuan/erban/ui/setting/VerifyPhoneActivity.java new file mode 100644 index 000000000..7724abb89 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/setting/VerifyPhoneActivity.java @@ -0,0 +1,259 @@ +package com.yizhuan.erban.ui.setting; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityVerifyPhoneBinding; +import com.yizhuan.erban.ui.login.BindSuccessDialog; +import com.yizhuan.erban.ui.login.CodeDownTimer; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Action; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + + +@ActLayoutRes(R.layout.activity_verify_phone) +public class VerifyPhoneActivity extends BaseBindingActivity implements View.OnClickListener, + BindSuccessDialog.BindSuccessDialogListener { + + public static final int REQUEST_CHECK_VALID_PHONE = 1001; + + private boolean isVerify; + private boolean resetPwd; + private boolean isForgetPwd; + private CodeDownTimer timer; + private int type = CodeType.UNBIND_PHONE; + + public static void start(Context context, boolean resetPwd) { + Intent intent = new Intent(context, VerifyPhoneActivity.class); + intent.putExtra("resetPwd", resetPwd); + context.startActivity(intent); + } + + public static void startForResult(Activity context, boolean isForgetPwd) { + Intent intent = new Intent(context, VerifyPhoneActivity.class); + intent.putExtra("isForgetPwd", isForgetPwd); + context.startActivityForResult(intent, REQUEST_CHECK_VALID_PHONE); + } + + @Override + protected void init() { + initTitleBar("验证已绑定手机号码"); + isForgetPwd = getIntent().getBooleanExtra("isForgetPwd", false); + resetPwd = getIntent().getBooleanExtra("resetPwd", false); + if (UserModel.get().getCacheLoginUserInfo() != null + && !TextUtils.isEmpty(UserModel.get().getCacheLoginUserInfo().getPhone())) { + mBinding.etPhone.setText(UserModel.get().getCacheLoginUserInfo().getPhone()); + mBinding.etPhone.setEnabled(false); + } + + mBinding.btnGetCode.setOnClickListener(this); + mBinding.btnRegist.setOnClickListener(this); + mBinding.ivCodeDelete.setOnClickListener(this); + } + + private void getCode() { + if (isForgetPwd) { + type = CodeType.RESET_PAY_PSW; + } + CodeModel.get().sendCode(mBinding.etPhone.getText().toString(), type) + .compose(bindToLifecycle()) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + toast(throwable.getMessage()); + } + }) + .doOnSubscribe(new Consumer() { + @Override + public void accept(Disposable disposable) throws Exception { + getDialogManager().showProgressDialog(VerifyPhoneActivity.this, "加载中..."); + } + }) + .doAfterTerminate(new Action() { + @Override + public void run() throws Exception { + getDialogManager().dismissDialog(); + } + }) + .subscribe((s, throwable) -> { + if (throwable != null) { + return; + } + toast("验证码已发送到您的手机,请注意查收"); + startCountDownTimer(); + }); + + } + + private void clickRegistButton() { + if (TextUtils.isEmpty(mBinding.etPhone.getText().toString())) { + toast("手机号不能为空"); + return; + } + if (TextUtils.isEmpty(mBinding.etCode.getText().toString())) { + toast("验证码不能为空"); + return; + } + if (isVerify) { + getDialogManager().showProgressDialog(this, "加载中..."); + PayModel.get().bindPhone( + AuthModel.get().getCurrentUid() + "", + mBinding.etPhone.getText().toString(), + mBinding.etCode.getText().toString(), + AuthModel.get().getTicket() + ) + .compose(bindToLifecycle()) + .flatMap(new Function, SingleSource>() { + @Override + public SingleSource apply(ServiceResult stringServiceResult) throws Exception { + if (stringServiceResult.isSuccess()) { + return Single.just("修改成功"); + } else { + return Single.error(new Throwable(stringServiceResult.getMessage())); + } + } + }) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + bindSuccessDialog(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }); + } else { + getDialogManager().showProgressDialog(this, "加载中..."); + PayModel.get().verifyCode( + mBinding.etPhone.getText().toString(), + mBinding.etCode.getText().toString() + ) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + type = CodeType.BIND_PHONE; + if (resetPwd) { + ModifyPwdActivity.start(VerifyPhoneActivity.this, ModifyPwdActivity.RESET_PAY_PWD); + finish(); + } else if (isForgetPwd) { + setResult(RESULT_OK); + finish(); + } else { + showModifyView(); + } + } + }); + } + + } + + private void showModifyView() { + isVerify = true; + initTitleBar("更改绑定手机"); + + if (timer != null) { + timer.cancel(); + } + + mBinding.text.setVisibility(View.GONE); + + mBinding.btnGetCode.setText("获取验证码"); + mBinding.btnGetCode.setTextColor(ContextCompat.getColor(this, R.color.appColor)); + mBinding.btnGetCode.setClickable(true);//重新获得点击 + + mBinding.btnRegist.setText("提交"); + mBinding.etPhone.setText(""); + mBinding.etPhone.setEnabled(true); + mBinding.etPhone.requestFocus(); + mBinding.etCode.setText(""); + + mBinding.vsPhoneCountry.getViewStub().inflate(); + mBinding.vDividerOne.setVisibility(View.VISIBLE); + + } + + private void bindSuccessDialog() { + BindSuccessDialog dialog = new BindSuccessDialog(); + dialog.setmListener(this); + dialog.show(getSupportFragmentManager(), "bindSuccess"); + } + + @Override + public void onClick(View v) { + super.onClick(v); + + switch (v.getId()) { + case R.id.iv_code_delete: + mBinding.etCode.setText(""); + break; + + case R.id.btn_regist: + clickRegistButton(); + break; + + case R.id.btn_get_code: + getCode(); + break; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stopCountDownTimer(); + } + + @Override + public void close() { + finish(); + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(mBinding.btnGetCode, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivity.java new file mode 100644 index 000000000..a1624861f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivity.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.ui.user; + +import android.os.Bundle; +import android.widget.TextView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +public class AboutActivity extends BaseActivity { + + private TextView mTvVersions; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_about); + initTitleBar("关于轻寻"); + initView(); + initData(); + } + + private void initData() { + mTvVersions.setText(getString(R.string.setting_version, BasicConfig.getLocalVersionName(getApplicationContext()))); + } + + private void initView() { + mTvVersions = findViewById(R.id.versions); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivityKotlin.kt b/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivityKotlin.kt new file mode 100644 index 000000000..4170ffbd4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/AboutActivityKotlin.kt @@ -0,0 +1,34 @@ +//package com.yizhuan.erban.ui.user +// +//import android.os.Bundle +//import com.yizhuan.erban.R +//import com.yizhuan.erban.base.BaseActivity +//import com.yizhuan.xchat_android_library.utils.config.BasicConfig +//import kotlinx.android.synthetic.main.activity_about.* +// +//class AboutActivityKotlin : BaseActivity() { +// +// override fun onCreate(savedInstanceState: Bundle?) { +// super.onCreate(savedInstanceState) +// setContentView(R.layout.activity_about) +// initTitleBar("关于轻寻") +// initView() +// initData() +// } +// +// private fun initData() { +// versions!!.text = getString(R.string.setting_version, BasicConfig.getLocalVersionName(applicationContext)) +// +// } +// +// private fun initView() { +// } +//} +fun a(map: Map?) { + if (map == null) { + return + } + map["123"] + println("".javaClass) + (("".toDoubleOrNull() ?: 0.0) > 100) +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/GiftWallAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/GiftWallAdapter.java new file mode 100644 index 000000000..1003c64ce --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/GiftWallAdapter.java @@ -0,0 +1,74 @@ +package com.yizhuan.erban.ui.user; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.user.bean.GiftWallInfo; + +import java.util.List; + +/** + * @author chenran + */ +public class GiftWallAdapter extends RecyclerView.Adapter { + private List giftWallInfoList; + private Context context; + private int mTextColor; + + public GiftWallAdapter(Context context, int textColor) { + this.context = context; + mTextColor = textColor; + } + + public void setGiftWallInfoList(List giftWallInfoList) { + this.giftWallInfoList = giftWallInfoList; + } + + @Override + public GiftWallHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_gift_wall_info, parent, false); + return new GiftWallHolder(item, mTextColor); + } + + @Override + public void onBindViewHolder(GiftWallHolder holder, int position) { + GiftWallInfo giftWallInfo = giftWallInfoList.get(position); + holder.giftName.setText(giftWallInfo.getGiftName()); + holder.giftNum.setText(String.valueOf(giftWallInfo.getReciveCount())); + ImageLoadUtils.loadImage(context, giftWallInfo.getPicUrl(), holder.giftPic); + } + + @Override + public int getItemCount() { + if (giftWallInfoList == null) + return 0; + else { + return giftWallInfoList.size(); + } + } + + class GiftWallHolder extends RecyclerView.ViewHolder { + private ImageView giftPic; + private TextView giftName; + private TextView giftNum; + + GiftWallHolder(View itemView, int textColor) { + super(itemView); + giftPic = itemView.findViewById(R.id.gift_img); + giftName = itemView.findViewById(R.id.gift_name); + giftNum = itemView.findViewById(R.id.gift_num); + + giftName.setTextColor(textColor); + giftNum.setTextColor(textColor); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/PhotoAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/PhotoAdapter.java new file mode 100644 index 000000000..024133f0e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/PhotoAdapter.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.ui.user; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; + +import java.util.ArrayList; + +/** + * Created by ${Seven} on 2017/8/14. + */ + +public class PhotoAdapter extends PagerAdapter { + private final Context context; + private final ArrayList bigImagesList; + + private PhotoAdapter.imageOnclickListener mImageOnclickListener; + + public void setmImageOnclickListener(PhotoAdapter.imageOnclickListener imageOnclickListener){ + mImageOnclickListener=imageOnclickListener; + } + public interface imageOnclickListener{ + void onClick(); + } + + //传进来的photolist用于设置进imageview里面去 + public PhotoAdapter(Context Context, ArrayList photoList) { + context = Context; + this.bigImagesList = photoList; + } + @Override + public int getCount() { + return bigImagesList == null ? 0 : bigImagesList.size(); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + final ImageView imageView = new ImageView(context); + //拿到userphoto对象 + UserPhoto userPhoto = bigImagesList.get(position); + //把对象设置到imageview里面去 + ImageLoadUtils.loadImage(context, userPhoto.getPhotoUrl(), imageView); + //然后把imageview添加到容器里面去 + container.addView(imageView); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mImageOnclickListener.onClick(); + } + }); + return imageView; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/ScrollAwareBehavior.java b/app/src/main/java/com/yizhuan/erban/ui/user/ScrollAwareBehavior.java new file mode 100644 index 000000000..c78539d18 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/ScrollAwareBehavior.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.ui.user; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.design.widget.CoordinatorLayout; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewPropertyAnimatorListener; +import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +public class ScrollAwareBehavior extends CoordinatorLayout.Behavior { + private static final android.view.animation.Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); + private boolean mIsAnimatingOut = false; + private boolean mIsAnimatingIn = false; + + public ScrollAwareBehavior(Context context, AttributeSet attrs){ + super(context, attrs); + } + + @Override + public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull LinearLayout child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) { + return (axes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; + } + + @Override + public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull LinearLayout child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { + super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); + //向上滚动进入,向下滚动隐藏 + if (dyUnconsumed > 0 && !this.mIsAnimatingOut){ + //animateOut()和animateIn()都是私有方法,需要重新实现 + animateOut(child); + } else if (dyUnconsumed < 0 && !mIsAnimatingIn){ + animateIn(child); + } + } + + private void animateOut(final LinearLayout button){ + ViewCompat.animate(button).translationY(500) + .setInterpolator(INTERPOLATOR).withLayer() + .setListener(new ViewPropertyAnimatorListener() { + @Override + public void onAnimationStart(View view) { + ScrollAwareBehavior.this.mIsAnimatingOut = true; + } + + @Override + public void onAnimationEnd(View view) { + ScrollAwareBehavior.this.mIsAnimatingOut = false; + } + + @Override + public void onAnimationCancel(View view) { + ScrollAwareBehavior.this.mIsAnimatingOut = false; + } + }).start(); + } + + private void animateIn(LinearLayout button){ + ViewCompat.animate(button).translationY(0) + .setInterpolator(INTERPOLATOR).withLayer().setListener(new ViewPropertyAnimatorListener() { + @Override + public void onAnimationStart(View view) { + mIsAnimatingIn = true; + } + + @Override + public void onAnimationEnd(View view) { + mIsAnimatingIn = false; + } + + @Override + public void onAnimationCancel(View view) { + mIsAnimatingIn = false; + } + }) + .start(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/ScrollingActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/ScrollingActivity.java new file mode 100644 index 000000000..a4a504a2e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/ScrollingActivity.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.ui.user; + +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; + +import com.yizhuan.erban.R; + +public class ScrollingActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_scrolling); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + fab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/ShowPhotoActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/ShowPhotoActivity.java new file mode 100644 index 000000000..71fe80bea --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/ShowPhotoActivity.java @@ -0,0 +1,100 @@ +package com.yizhuan.erban.ui.user; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.view.ViewPager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; + +import java.util.ArrayList; + +import io.realm.RealmList; + +public class ShowPhotoActivity extends BaseActivity { + private ImageView mImageView; + private TextView imgCount; + private ViewPager viewPager; + private UserPhoto userPhoto; + private PhotoAdapter photoAdapter; + private ShowPhotoActivity mActivity; + private int position; + private ArrayList photoUrls; + private RealmList userPhotos = new RealmList<>(); +// private RealmList userPhotoRealmList; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_show_photo); + mActivity = this; + initView(); + initData(); + setListener(); + } + + private void setListener() { +// mImageView.setOnTouchListener(new View.OnTouchListener() { +// @Override +// public boolean onTouch(View v, MotionEvent event) { +// return false; +// } +// }); + viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { +// viewPager.setCurrentItem(position); +// imgCount.setText((position + 1) + "/" + photoAdapter.getCount()); + } + + @Override + public void onPageSelected(int position) { + if (position == 0) { + imgCount.setText((position + 1) + "/" + photoAdapter.getCount()); + } + imgCount.setText((position + 1) + "/" + photoAdapter.getCount()); + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + photoAdapter.setmImageOnclickListener(new PhotoAdapter.imageOnclickListener() { + @Override + public void onClick() { + finish(); + } + }); + } + + private void initData() { + position = getIntent().getIntExtra("position",1); + System.out.println("position==="+position); +// userPhoto = (UserPhoto) getIntent().getSerializableExtra("userPhoto"); + photoUrls = (ArrayList) getIntent().getSerializableExtra("photoList"); +// UserInfo userInfo = UserModel.get().getCacheUserInfoByUid(AuthModel.get().getCurrentUid()); +// RealmList userPhotos = userInfo.getPrivatePhoto(); + if (photoUrls != null) { + photoAdapter = new PhotoAdapter(mActivity, photoUrls); + viewPager.setAdapter(photoAdapter); + viewPager.setCurrentItem(position); + imgCount.setText((position + 1) + "/" + photoAdapter.getCount()); + } + } + private void initView() { +// mImageView = (ImageView) findViewById(R.id.photoview); + imgCount = (TextView) findViewById(R.id.tv_count); + viewPager = (ViewPager) findViewById(R.id.viewpager); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserGiftAchievementFrg.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserGiftAchievementFrg.java new file mode 100644 index 000000000..ca3b7907b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserGiftAchievementFrg.java @@ -0,0 +1,228 @@ +package com.yizhuan.erban.ui.user; + +import android.arch.lifecycle.Observer; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseMvpFragment; +import com.yizhuan.erban.ui.user.adapter.GiftAchievementAdapter; +import com.yizhuan.erban.ui.user.presenter.UserGiftAchievementPresenter; +import com.yizhuan.erban.ui.user.view.IUserGiftAchievement; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserInfoUiMgr; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementInfo; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementInfoSub; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementItem; +import com.yizhuan.xchat_android_library.base.factory.CreatePresenter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +@CreatePresenter(UserGiftAchievementPresenter.class) +public class UserGiftAchievementFrg extends BaseMvpFragment + implements IUserGiftAchievement{ + + @BindView(R.id.recycler_view) + RecyclerView recyclerView; + + private Observer mObserver; + private long mUserId; + + private Unbinder unbinder; + + public static UserGiftAchievementFrg newInstance() { + return new UserGiftAchievementFrg(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mObserver = new Observer() { + @Override + public void onChanged(@Nullable Long o) { + if (o != null) { + mUserId = o; + } + + } + }; + UserInfoUiMgr.get().registerUid(this, mObserver); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + unbinder = ButterKnife.bind(this, mView); + return mView; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + UserInfoUiMgr.get().unregisterUid(mObserver); + if (unbinder != null) { + unbinder.unbind(); + } + } + + @Override + public void onFindViews() { + + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + mAdapter = new GiftAchievementAdapter(null); + recyclerView.setLayoutManager(new GridLayoutManager(mContext, 4)); + recyclerView.setAdapter(mAdapter); + mAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + List list = mAdapter.getData(); + if (ListUtils.isListEmpty(list)) + return 4; + + GiftAchievementItem userInfoItem = list.get(position); + int type = userInfoItem.getItemType(); + if (type == GiftAchievementItem.TYPE_TITILE || type == GiftAchievementItem.TYPE_BLOCK_DIVIDER) { + return 4; + + } else + return 1; + + } + }); + + mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + long currentClick = System.currentTimeMillis(); + if (currentClick - lastClick > 2000) { + lastClick = currentClick; + List list = adapter.getData(); + + if (position >=0 && position < list.size()) { + GiftAchievementItem info = list.get(position); + if (info != null && info.getItemType() == GiftAchievementItem.TYPE_ITEM) { + GiftAchievementInfoSub infoSub = (GiftAchievementInfoSub) info.getData(); + if (infoSub != null && !TextUtils.isEmpty(infoSub.getTip())) { + SingleToastUtil.showToastShort(infoSub.getTip()); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_GIFT_TIP, "有礼物提示卡片-" + infoSub.getGiftName()); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_GIFT_NO_TIP, "无礼物提示卡片-" + infoSub.getGiftName()); + } + } + } + + } + + } + }); + + Long uid = UserInfoUiMgr.get().getUid(); + if (uid != null) { + mUserId = uid; + } + getMvpPresenter().getAchievementList(mUserId); + } + + private long lastClick; + + @Override + public int getRootLayoutId() { + return R.layout.gift_achievement_recyclerview; + } + + private List mList = new ArrayList<>(); + private GiftAchievementAdapter mAdapter; + + @Override + public void getAchievementListSuccess(List list) { + mList.clear(); + + if (list == null || list.size() == 0) { + if (mUserGiftNoDataListener != null) { + mUserGiftNoDataListener.noData(UserInfoGiftGroupFrg.TAG_GIFT); + } + return; + } + + if (mUserGiftNoDataListener != null) { + mUserGiftNoDataListener.hasData(UserInfoGiftGroupFrg.TAG_ACHIEVEMENT); + } + + for (GiftAchievementInfo info : list) { + String title; + if (AuthModel.get().getCurrentUid() == mUserId) { + title = info.getTypeName() + " (" + info.getAttainNum() + "/" + info.getTotalNum() + ")"; + } else { // 客态页不显示集卡进度 + title = info.getTypeName(); + } + + GiftAchievementItem item; + + // 模块间距 + if (mList.size() > 1) { + item = new GiftAchievementItem(GiftAchievementItem.TYPE_BLOCK_DIVIDER, null); + mList.add(item); + } + + item = new GiftAchievementItem(GiftAchievementItem.TYPE_TITILE, title); + mList.add(item); + + + List subs = info.getGiftList(); + if (subs != null && subs.size() > 0) { + for (GiftAchievementInfoSub temp : subs) { + item = new GiftAchievementItem(GiftAchievementItem.TYPE_ITEM, temp, + info.getBackgroundUrl(), info.getMaskUrl(), info.getGrayBgUrl()); + mList.add(item); + } + } + } + mAdapter.setNewData(mList); + } + + @Override + public void getAchievementListFail(Throwable error) { + if (mUserGiftNoDataListener != null) { + mUserGiftNoDataListener.noData(UserInfoGiftGroupFrg.TAG_GIFT); + } + } + + public void setmUserGiftNoDataListener(UserGiftNoDataListener mUserGiftNoDataListener) { + this.mUserGiftNoDataListener = mUserGiftNoDataListener; + } + + private UserGiftNoDataListener mUserGiftNoDataListener; + + + public interface UserGiftNoDataListener { + void noData(byte type); + void hasData(byte type); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivity.java new file mode 100644 index 000000000..b671b7ff4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivity.java @@ -0,0 +1,916 @@ +package com.yizhuan.erban.ui.user; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.support.design.widget.AppBarLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewPager; +import android.support.v4.widget.NestedScrollView; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.target.ViewTarget; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.impl.cache.NimUserInfoCache; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; +import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.RecordingVoiceActivity; +import com.yizhuan.erban.avroom.ButtonItemFactory; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.common.widget.dialog.CommonPopupDialog; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.ActivityUserInfoBinding; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.family.view.activity.FamilyMemberListActivity; +import com.yizhuan.erban.family.view.activity.FamilyMemberSearchActivity; +import com.yizhuan.erban.community.user_dynamic.UserDynamicFrg; +import com.yizhuan.erban.ui.im.avtivity.NimFriendModel; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.relation.FansListActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.ui.widget.ObservableScrollView; +import com.yizhuan.erban.ui.widget.UserMagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.erban.utils.AppBarStateChangeListener; +import com.yizhuan.erban.utils.BlurTransformation; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.praise.event.IsLikedEvent; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserInfoUiMgr; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_core.utils.StarUtils; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * create by lvzebiao on 2018/8/31 + */ + +@ActLayoutRes(R.layout.activity_user_info) +public class UserInfoActivity extends BaseBindingActivity + implements UserPhotoAdapter.ImageClickListener, ObservableScrollView.ScrollViewListener, + UserMagicIndicator.OnItemSelectListener { + + public static final int REQUEST_CODE_UPDATE_VOICE = 1; + + private int TAB_SIZE = 4; + private int TAB_DYNAMIC = 0; + private int TAB_INFORMATION = 1; + private int TAB_GIFT = 2; + private int TAB_CAR = 3; + + @Override + public void onItemSelect(int position) { + Log.i("onItemselect", "position:" + position); + mBinding.vpUserInfo.setCurrentItem(position); + } + + public interface IdentityState { + int NON = 0; // 无法识别 + int OWN = 1; // 自己 + int OTHER = 2; // 其他人 + } + + private int identityState = IdentityState.NON; + + private UserInfoActivity mActivity; + private long userId; + private UserInfo userInfo; + private SVGAParser mSVGAParser; + Drawable mAttenDrawable; + Drawable mAttenedDrawable; + + private boolean mIslike = false; + private RoomInfo mRoomInfo = null; + private int flag = 0; + private boolean isNoble; + private LinearLayout bottomViewLayout = null; + private TextView sendMsgLayout; + private TextView attentionLayout; + + UserInfoFragment mUserInfoFragment; + UserInfoGiftGroupFrg mUserInfoGiftGroupFrg; + UserInfoCarFragment mUserInfoCarFragment; + UserDynamicFrg mUserDynamicFrg; + + private void onSetListener() { + mBinding.ivUserBack.setOnClickListener(this); + mBinding.ivEdit.setOnClickListener(this); + mBinding.llUserRoom.setOnClickListener(this); + mBinding.llWhere.setOnClickListener(this); + mBinding.imageView.setOnClickListener(this); + + mBinding.ablUserInfo.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, State state) { + if (state == State.EXPANDED) { + //展开状态 + setEditButton(identityState, true); + setBackBottom(true); + setTitleVisible(false); + + } else if (state == State.COLLAPSED) { + //折叠状态 + setEditButton(identityState, false); + setBackBottom(false); + setTitleVisible(true); + + } else { + //中间状态 + } + + } + }); + + } + + @Override + protected void init() { + mActivity = this; + userId = getIntent().getLongExtra("userId", 0); + UserInfoUiMgr.get().setUid(userId); + + onFindViews(); + onSetListener(); + EventBus.getDefault().register(this); + + mSVGAParser = new SVGAParser(this); + UserModel.get().getUserInfoFromServer(userId) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(UserInfo Info) { + userInfo = Info; + //这里座驾只显示一次 + if (userInfo.getCarInfo() != null && userInfo.getCarInfo().isUsing()) { + try { + mSVGAParser.parse(new URL(userInfo.getCarInfo().getEffect()), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity videoItem) { + mBinding.userInfoSvgaCar.setVisibility(View.VISIBLE); + mBinding.userInfoSvgaCar.setLoops(1); + Drawable drawable = new SVGADrawable(videoItem); + mBinding.userInfoSvgaCar.setImageDrawable(drawable); + mBinding.userInfoSvgaCar.startAnimation(); + } + + @Override + public void onError() { + mBinding.userInfoSvgaCar.setVisibility(View.GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + initData(userInfo); + } + }); + + mBinding.userInfoSvgaCar.setCallback(new SVGACallback() { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + }); + + mAttenDrawable = ContextCompat.getDrawable(this, R.mipmap.icon_new_attention); + mAttenedDrawable = ContextCompat.getDrawable(this, R.drawable.ic_attened); + + mBinding.userInfoSvgaCar.clearAnimation(); + mBinding.userInfoSvgaCar.setVisibility(View.GONE); + mSVGAParser = new SVGAParser(this); + + if (AuthModel.get().getCurrentUid() == userId) { + identityState = IdentityState.OWN; + mBinding.tvAttentionCount.setOnClickListener(this); + mBinding.tvUserAttentionText.setOnClickListener(this); + mBinding.tvFansCount.setOnClickListener(this); + mBinding.tvUserFanText.setOnClickListener(this); + setWhereVisible(false); + + if (bottomViewLayout != null) + bottomViewLayout.setVisibility(View.GONE); + } else { + if (userId == NimP2PMessageActivity.SECRETARY_UID || userId == NimP2PMessageActivity.SYSTEM_MESSAGE_UID) { + identityState = IdentityState.NON; + } else { + identityState = IdentityState.OTHER; + } + setWhereVisible(true); + + if (bottomViewLayout == null) { + View view = mBinding.vsBottomLayout.getViewStub().inflate(); + bottomViewLayout = view.findViewById(R.id.bottom_view_layout); + sendMsgLayout = view.findViewById(R.id.send_msg_layout); + attentionLayout = view.findViewById(R.id.attention_layout); + sendMsgLayout.setOnClickListener(this); + attentionLayout.setOnClickListener(this); + } + + bottomViewLayout.setVisibility(View.VISIBLE); + } + + setEditButton(identityState, true); + setBackBottom(true); + setTitleVisible(false); + + mCompositeDisposable.add(IMNetEaseManager.get().getChatRoomEventObservable() + .subscribe(roomEvent -> { + if (roomEvent != null) { + switch (roomEvent.getEvent()) { + case RoomEvent.KICK_OUT_ROOM: + ChatRoomKickOutEvent reason = roomEvent.getReason(); + if (reason != null) { + ChatRoomKickOutEvent.ChatRoomKickOutReason kickOutReason = reason.getReason(); + if (kickOutReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + setUserRoomVisible(false); + } + } + break; + } + } + })); + } + + private void setEditButton(int identityState, boolean isExpanded) { + + if (identityState == IdentityState.OWN) { + mBinding.ivEdit.setVisibility(View.VISIBLE); + mBinding.ivEdit.setImageResource(isExpanded ? R.drawable.icon_user_info_edit : R.drawable.icon_edit_black); + + } else if (identityState == IdentityState.OTHER) { + mBinding.ivEdit.setVisibility(View.VISIBLE); + mBinding.ivEdit.setImageResource(isExpanded ? R.drawable.icon_home_page_more : R.drawable.icon_home_page_more_black); + + } else { + mBinding.ivEdit.setVisibility(View.GONE); + } + + } + + private void setBackBottom(boolean isExpanded) { + mBinding.ivUserBack.setImageResource(isExpanded ? R.drawable.icon_user_back : R.drawable.icon_user_back_black); + } + + private void setTitleVisible(boolean visible) { + mBinding.tvUserInfoTitle.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + /** + * 找到TA, 主态不展示 + */ + private void setWhereVisible(boolean visible) { + mBinding.viewLineTwo.setVisibility(visible ? View.VISIBLE : View.GONE); + mBinding.llWhere.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + /** + * TA的房间, 主态不展示 + */ + private void setUserRoomVisible(boolean visible) { + mBinding.viewLineThree.setVisibility(visible ? View.VISIBLE : View.GONE); + mBinding.llUserRoom.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + private void onFindViews() { + mBinding.tbUserInfo.setTitle(""); + + List tabInfoList = new ArrayList<>(TAB_SIZE); + tabInfoList.add(new TabInfo(TAB_DYNAMIC, "动态")); + tabInfoList.add(new TabInfo(TAB_INFORMATION, "资料")); + tabInfoList.add(new TabInfo(TAB_GIFT, "礼物")); + tabInfoList.add(new TabInfo(TAB_CAR, "座驾")); + + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + UserMagicIndicator indicator = new UserMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mBinding.miUserInfo.setNavigator(commonNavigator); + mBinding.vpUserInfo.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + mBinding.miUserInfo.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + + @Override + public void onPageSelected(int position) { + mBinding.miUserInfo.onPageSelected(position); + setStatistic(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + mBinding.miUserInfo.onPageScrollStateChanged(state); + } + }); + + mUserDynamicFrg = UserDynamicFrg.newInstance(userId); + mUserInfoFragment = UserInfoFragment.newInstance(userId, getIntent().getIntExtra("from", 1)); + mUserInfoGiftGroupFrg = UserInfoGiftGroupFrg.newInstance(); + mUserInfoCarFragment = UserInfoCarFragment.newInstance(); + + mBinding.vpUserInfo.setOffscreenPageLimit(3); + mBinding.vpUserInfo.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public int getCount() { + return TAB_SIZE; + } + + @Override + public Fragment getItem(int position) { + if (position == TAB_DYNAMIC) { + return mUserDynamicFrg; + } else if (position == TAB_INFORMATION) { + return mUserInfoFragment; + } else if (position == TAB_GIFT) { + return mUserInfoGiftGroupFrg; + } else if (position == TAB_CAR) { + return mUserInfoCarFragment; + } + return mUserInfoFragment; + } + }); + mBinding.vpUserInfo.setCurrentItem(0); + setStatistic(0); + } + + // 埋点 + private void setStatistic(int position) { + String temp = AuthModel.get().getCurrentUid() == userId ? "主态" : "客态"; + switch (position) { + case 0: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_MOMENT, "个人主页动态tab-" + temp); + break; + + case 1: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_DATA, "个人主页资料tab-" + temp); + break; + + case 2: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_GIFT, "个人主页礼物tab-" + temp); + break; + + case 3: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_CAR, "个人主页座驾tab-" + temp); + break; + } + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentUserInfoUpdate(LoginUserInfoUpdateEvent event) { + if (UserModel.get().getCacheLoginUserInfo().getUid() == userId) { + userInfo = UserModel.get().getCacheLoginUserInfo(); + initData(userInfo); + } + } + + private void initData(UserInfo userInfo) { + if (null != userInfo) { + UserInfoUiMgr.get().setValue(userInfo); + + ImageLoadUtils.loadBigAvatar(this, userInfo.getAvatar(), mBinding.imageView, false); + + requestRoomInfo(userInfo); + + String nick = RegexUtil.getPrintableString(userInfo.getNick()); + mBinding.tvNick.setText(nick); + mBinding.tvUserInfoTitle.setText(nick); + Drawable drawable = ContextCompat.getDrawable(this, + (userInfo.getGender() == 1) ? R.drawable.ic_male : R.drawable.ic_female); + mBinding.tvNick.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); + + mBinding.tvAttentionCount.setText(String.valueOf(userInfo.getFollowNum())); + mBinding.tvFansCount.setText(String.valueOf(userInfo.getFansNum())); + + //设置星座 + String star = StarUtils.getConstellation(new Date(userInfo.getBirth())); + if (null == star) { + mBinding.tvConstellation.setVisibility(View.GONE); + } else { + mBinding.tvConstellation.setText(star); + mBinding.tvConstellation.setVisibility(View.VISIBLE); + } + if (userInfo.getUserInfoSkillVo() != null) { + mBinding.iv101.setVisibility(userInfo.getUserInfoSkillVo().isLiveTag() ? View.VISIBLE : View.GONE); + if (!TextUtils.isEmpty(userInfo.getUserInfoSkillVo().getSkillTag())) { + ImageLoadUtils.loadImage(this, userInfo.getUserInfoSkillVo().getSkillTag(), mBinding.ivTag); + mBinding.ivTag.setVisibility(View.VISIBLE); + } else { + mBinding.ivTag.setVisibility(View.GONE); + } + } + mBinding.tvErbanId.setText(getString(R.string.me_user_id, userInfo.getErbanNo())); + setUserLevel(userInfo.getUserLevelVo()); + + NobleInfo nobleInfo = userInfo.getNobleInfo(); + HeadWearInfo headWearInfo = userInfo.getUserHeadwear(); + if (nobleInfo != null) { + setBgByLevel(true); + String zoneBg = nobleInfo.getZoneBg(); + if (TextUtils.isEmpty(zoneBg)) { + ImageLoadUtils.loadImage(this, userInfo.getAvatar(), mBinding.avatarBg); + } else { + ImageLoadUtils.loadImage(this, zoneBg, mBinding.avatarBg); + } + NobleUtil.loadResource( + NobleUtil.getBadgeByLevel(nobleInfo.getLevel()), mBinding.ivUserNobleLevel); + } else { + setBgByLevel(false); + mBinding.ivUserNobleLevel.setImageDrawable(null); + GlideApp.with(this) + .load(userInfo.getAvatar()) + .dontAnimate() + .centerInside() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, + Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, + Target target, DataSource dataSource, boolean b) { + drawable.setColorFilter(context.getResources().getColor(R.color.black_transparent_20), PorterDuff.Mode.DARKEN); + ViewTarget viewTarget = (ViewTarget) target; + viewTarget.getView().setImageDrawable(drawable); + return true; + } + }) + // “23”:设置模糊度(在0.0到25.0之间),默认”25";"4":图片缩放比例,默认“1”。 + .transforms(new BlurTransformation(context, 10, 1)) + .into(mBinding.avatarBg); + } + setHeadWare(headWearInfo, nobleInfo); + + //设置靓号 + boolean hasPrettyErbanNo = userInfo.isHasPrettyErbanNo(); + mBinding.ivGoodNumber.setVisibility(hasPrettyErbanNo ? View.VISIBLE : View.GONE); + // 设置官字 + mBinding.ivUserOfficial.setVisibility(userInfo.isOfficial() ? View.VISIBLE : View.GONE); + // 设置新字 + mBinding.ivUserNew.setVisibility(userInfo.isNewUser() ? View.VISIBLE : View.GONE); + + if (null == star) { + mBinding.tvConstellation.setVisibility(View.GONE); + } else { + mBinding.tvConstellation.setText(star); + mBinding.tvConstellation.setVisibility(View.VISIBLE); + } + //设置地址 + String address = null; + if (null != userInfo.getUserExpand() && userInfo.getUserExpand().isShowLocation()) { + StringBuilder sb = new StringBuilder(); + String province = userInfo.getUserExpand().getProvinceName(); + if (!TextUtils.isEmpty(province)) { + sb.append(" ").append(province); + } + String city = userInfo.getUserExpand().getCityName(); + if (!TextUtils.isEmpty(city)) { + sb.append(" ").append(city); + } + if (sb.length() != 0) { + address = sb.toString(); + } + } + if (TextUtils.isEmpty(address)) { + mBinding.tvAddress.setVisibility(View.GONE); + } else { + mBinding.tvAddress.setText(address); + mBinding.tvAddress.setVisibility(View.VISIBLE); + } + + + if (AuthModel.get().getCurrentUid() != userInfo.getUid()) { + PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), userInfo.getUid()).subscribe(); + } + + mUserInfoFragment.onGetUserInfo(userInfo); + } + } + + private void requestRoomInfo(UserInfo userInfo) { + AvRoomModel.get().requestRoomInfoByUser(String.valueOf(userInfo.getUid())) + .compose(bindToLifecycle()) + .subscribe(roomInfo -> onGetRoomInfo(roomInfo)); + } + + /** + * 自选头饰 -> 贵族头饰 -> 无 + */ + private void setHeadWare(HeadWearInfo headWearInfo, NobleInfo nobleInfo) { + mBinding.ivAvatarHeadWear.setImageDrawable(null); + mBinding.ivAvatarHeadWear.setVisibility(View.GONE); + + if (headWearInfo != null) { + mBinding.ivAvatarHeadWear.setVisibility(View.VISIBLE); + NobleUtil.loadHeadWear(headWearInfo.getPic(), mBinding.ivAvatarHeadWear); + return; + } + + if (nobleInfo != null) { + mBinding.ivAvatarHeadWear.setVisibility(View.VISIBLE); + NobleUtil.loadResource(nobleInfo.getHeadWear(), mBinding.ivAvatarHeadWear); + } + + } + + private void setUserLevel(UserLevelVo userLevelVo) { + mBinding.ivUserCharm.setVisibility(View.GONE); + mBinding.ivUserLevel.setVisibility(View.GONE); + if (userLevelVo != null) { + String userLevelUrl = userLevelVo.getExperUrl(); + String userCharmUrl = userLevelVo.getCharmUrl(); + if (!TextUtils.isEmpty(userLevelUrl)) { + mBinding.ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(this, userLevelUrl, mBinding.ivUserLevel); + } + if (!TextUtils.isEmpty(userCharmUrl)) { + mBinding.ivUserCharm.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(this, userCharmUrl, mBinding.ivUserCharm); + } + } + } + + private void setBgByLevel(boolean isNoble) { + this.isNoble = isNoble; + mBinding.ivUserNobleLevel.setVisibility(isNoble ? View.VISIBLE : View.INVISIBLE); + + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mBinding.ivUserNobleLevel.getLayoutParams(); + layoutParams.width = isNoble ? SizeUtils.dp2px(this, 17f) : 0; + layoutParams.height = isNoble ? SizeUtils.dp2px(this, 17f) : 0; + + int nobleTextColor = ContextCompat.getColor(this, R.color.white_op_30); + mBinding.tvConstellation.setTextColor(isNoble ? nobleTextColor : Color.WHITE); + } + + @Override + public void onScrollChanged(NestedScrollView view, int x, int y, int oldx, int oldy) { + if (flag == 0 && oldy > 300) { + flag = 1; + boolean isNoble = (userInfo != null && userInfo.getNobleInfo() != null); + mBinding.ivEdit.setImageResource( + (isNoble) ? R.drawable.icon_user_info_edit : R.drawable.icon_edit_black); + } else if (flag == 1 && oldy <= 300) { + flag = 0; + mBinding.ivEdit.setImageResource(R.drawable.icon_user_info_edit); + } + } + + @Override + public void click(int position, UserPhoto userPhoto, boolean isOwner) { + if (isOwner) { + if (position > 0) { + showUserPhoto(position - 1); + } else { + UIHelper.showModifyPhotosAct(this, userId); + } + } else { + //创建一个集合拿来做用户所有照片信息 + showUserPhoto(position); + } + } + + private void showUserPhoto(int position) { + //创建一个集合拿来做用户所有照片信息 + ArrayList userPhotos = new ArrayList<>(); + List realmList = userInfo.getPrivatePhoto(); + for (UserPhoto photo : realmList) { + UserPhoto newPhoto = new UserPhoto(); + newPhoto.setPid(photo.getPid()); + newPhoto.setPhotoUrl(photo.getPhotoUrl()); + userPhotos.add(newPhoto); + } + Intent intent = new Intent(mActivity, ShowPhotoActivity.class); + intent.putExtra("position", position); + intent.putExtra("photoList", userPhotos); + startActivity(intent); + } + + private void editClick(int identityState) { + if (identityState == IdentityState.OWN) { + UIHelper.showUserInfoModifyAct(this, REQUEST_CODE_UPDATE_VOICE, userId); + } else if (identityState == IdentityState.OTHER) { + if (userInfo != null) { + String account = String.valueOf(userInfo.getUid()); + boolean inMyBlackList = NimFriendModel.get().isInMyBlackList(account); + List buttonItems = new ArrayList<>(); + if (!inMyBlackList) { + ButtonItem blackListItem = ButtonItemFactory.createAddToBlackListItem( + getDialogManager(), account); + buttonItems.add(blackListItem); + } + ButtonItem reportItem = ButtonItemFactory.createReportItem(context, userInfo.getUid(), XChatConstants.REPORT_TYPE_PERSONAL); + buttonItems.add(reportItem); + new CommonPopupDialog(this, "", buttonItems, "取消", false).show(); + } + + } + } + + private void avatarClick(int identityState) { + if (identityState == IdentityState.OWN) { + UIHelper.showUserInfoModifyAct(this, REQUEST_CODE_UPDATE_VOICE, userId); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_user_back: + finish(); + break; + + case R.id.imageView: + avatarClick(identityState); + break; + + case R.id.iv_edit: + editClick(identityState); + break; + case R.id.tv_attention_count: + case R.id.tv_user_attention_text: + Intent intent = new Intent(mActivity, FansListActivity.class); + intent.putExtra(FansListActivity.IS_ATTENT, true); + startActivity(intent); + break; + + case R.id.tv_fans_count: + case R.id.tv_user_fan_text: + startActivity(new Intent(mActivity, FansListActivity.class)); + break; + + case R.id.ll_user_room: + if (mRoomInfo != null) { + LogUtil.i(Companion.TAG, "进入的房间: " + mRoomInfo.getUid()); + AVRoomActivity.start(this, mRoomInfo.getUid(), mRoomInfo.getType()); + } + break; + + case R.id.send_msg_layout: + NimUserInfo nimUserInfo = NimUserInfoCache.getInstance().getUserInfo(String.valueOf(userId)); + if (nimUserInfo != null) { + NimP2PMessageActivity.start(this, String.valueOf(userId)); + } else { + NimUserInfoCache.getInstance().getUserInfoFromRemote(String.valueOf(userId), new RequestCallbackWrapper() { + @Override + public void onResult(int code, NimUserInfo result, Throwable exception) { + if (code == 200) { + NimP2PMessageActivity.start(mActivity, String.valueOf(userId)); + } else { + toast("网络异常,请重试"); + } + } + }); + } + break; + + case R.id.attention_layout: + if (userInfo == null) { + toast("用户信息为空。"); + return; + } + + if (mIslike) { + boolean isMyFriend = IMFriendModel.get().isMyFriend(String.valueOf(userInfo.getUid())); + String tip = (isMyFriend) ? "取消关注将不再是好友关系,确定取消关注?" : "确定取消关注?"; + getDialogManager().showOkCancelDialog(tip, true, new DialogManager.OkCancelDialogListener() { + + @Override + public void onCancel() { + getDialogManager().dismissDialog(); + } + + @Override + public void onOk() { + getDialogManager().dismissDialog(); + getDialogManager().showProgressDialog(mActivity, getString(R.string.waiting_text)); + PraiseModel.get().praise(userInfo.getUid(), false).subscribe(); + } + }); + } else { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.guest_page_follow, "客态页-关注"); + getDialogManager().showProgressDialog(mActivity, getString(R.string.waiting_text)); + PraiseModel.get().praise(userInfo.getUid(), true).subscribe(); + } + break; + + case R.id.ll_where: + getDialogManager().showProgressDialog(this, "请稍后..."); + AvRoomModel.get() + .getUserRoom(userId) + .compose(bindToLifecycle()) + .subscribe((roomResult, throwable) -> { + if (throwable != null) { + onGetUserRoomFail(throwable.getMessage()); + } else if (roomResult != null && roomResult.isSuccess()) { + onGetUserRoom(roomResult.getData()); + } else if (roomResult != null && !roomResult.isSuccess()) { + onGetUserRoomFail(roomResult.getError()); + } else { + onGetUserRoomFail("未知错误"); + } + }); +// /**************** 测试代码 **************/ +// AVRoomActivity.start(this, 91, mRoomInfo!!.type) + break; + } + } + + public void onGetRoomInfo(RoomInfo roomInfo) { + if (roomInfo == null) { + //该用户还未开房间 + setUserRoomVisible(false); + return; + } + //已经存在的activity + if (mRoomInfo != null && mRoomInfo.getRoomId() == roomInfo.getRoomId()) { + mRoomInfo = roomInfo; + } else if (mRoomInfo == null) { + //打开新的activity的时候 + mRoomInfo = roomInfo; + } + setUserRoomVisible(roomInfo.isValid() && identityState != IdentityState.OWN); + } + + public void onGetUserRoom(RoomInfo roomInfo) { + getDialogManager().dismissDialog(); + RoomInfo current = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null && roomInfo.getUid() > 0) { + if (current != null) { + if (current.getUid() == roomInfo.getUid()) { + toast("已经和对方在同一个房间"); + return; + } + } + AVRoomActivity.start(this, roomInfo.getUid(), roomInfo.getType()); + } else { + toast("对方不在房间内"); + } + } + + public void onGetUserRoomFail(String msg) { + getDialogManager().dismissDialog(); + toast(msg); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onIsLiked(IsLikedEvent event) { + setLikedText(event.isLiked); + } + + private void setLikedText(boolean isliked) { + mIslike = isliked; + attentionLayout.setCompoundDrawablesWithIntrinsicBounds( + (!isliked) ? mAttenDrawable : mAttenedDrawable, null, null, null); + attentionLayout.setCompoundDrawablePadding((isliked) ? 0 : SizeUtils.dp2px(this, 5f)); + attentionLayout.setText(getString((isliked) ? R.string.already_attention : R.string.attention)); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + if (event.getLikedUid() != userId || + userId == AuthModel.get().getCurrentUid()) { + return; + } + if (event.isFailed()) { + getDialogManager().dismissDialog(); + toast(event.getError()); + return; + } + getDialogManager().dismissDialog(); + toast(event.isPraise() ? R.string.fan_success : R.string.cancel_fan_success); + setLikedText(event.isPraise()); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + + if (mBinding.userInfoSvgaCar.isAnimating()) { + mBinding.userInfoSvgaCar.clearAnimation(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == REQUEST_CODE_UPDATE_VOICE) { + String audioFileUrl = data.getStringExtra(RecordingVoiceActivity.AUDIO_FILE); + int audioDuration = data.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0); + if (mUserInfoFragment != null) { + mUserInfoFragment.refreshVoiceDataView(audioFileUrl, audioDuration); + } + } + } + } + + /** + * static静态代码 + */ + + public final static class Companion { + public final static String TAG = UserInfoActivity.class.getSimpleName(); + + static final int FROM_TYPE_NORMAL = 1; + static final int FROM_TYPE_FAMILY = 2; + + public static void start(Context context, long userId) { + Intent intent = new Intent(context, UserInfoActivity.class); + intent.putExtra("userId", userId); + int from = FROM_TYPE_NORMAL; + if (context instanceof FamilyHomeActivity + || context instanceof FamilyMemberListActivity + || context instanceof FamilyMemberSearchActivity) { + //这里限制循环访问, 例如:家族->个人主页->家族->个人主页->.... + from = FROM_TYPE_FAMILY; + } + intent.putExtra("from", from); + context.startActivity(intent); + + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivityKotlin.kt b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivityKotlin.kt new file mode 100644 index 000000000..e880396f2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoActivityKotlin.kt @@ -0,0 +1,963 @@ +//package com.yizhuan.erban.ui.user +// +//import android.content.Context +//import android.content.Intent +//import android.graphics.Color +//import android.graphics.drawable.ColorDrawable +//import android.graphics.drawable.Drawable +//import android.os.Bundle +//import android.support.v4.content.ContextCompat +//import android.support.v4.widget.NestedScrollView +//import android.support.v7.widget.AppCompatButton +//import android.support.v7.widget.GridLayoutManager +//import android.support.v7.widget.LinearLayoutManager +//import android.text.TextUtils +//import android.view.LayoutInflater +//import android.view.View +//import android.view.View.GONE +//import android.view.View.VISIBLE +//import android.widget.LinearLayout +//import android.widget.RelativeLayout +//import android.widget.TextView +//import com.bumptech.glide.load.resource.bitmap.CenterCrop +//import com.bumptech.glide.load.resource.bitmap.RoundedCorners +//import com.netease.nim.uikit.common.util.log.LogUtil +//import com.netease.nim.uikit.impl.cache.NimUserInfoCache +//import com.netease.nim.uikit.support.glide.GlideApp +//import com.netease.nimlib.sdk.RequestCallbackWrapper +//import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent +//import com.netease.nimlib.sdk.media.player.AudioPlayer +//import com.netease.nimlib.sdk.media.player.OnPlayListener +//import com.netease.nimlib.sdk.uinfo.model.NimUserInfo +//import com.opensource.svgaplayer.SVGACallback +//import com.opensource.svgaplayer.SVGADrawable +//import com.opensource.svgaplayer.SVGAParser +//import com.opensource.svgaplayer.SVGAVideoEntity +//import com.trello.rxlifecycle2.android.ActivityEvent +//import com.yizhuan.erban.R +//import com.yizhuan.erban.UIHelper +//import com.yizhuan.erban.avroom.ButtonItemFactory +//import com.yizhuan.erban.avroom.activity.AVRoomActivity +//import com.yizhuan.erban.base.BaseBindingActivity +//import com.yizhuan.erban.car.activities.CarActivity +//import com.yizhuan.erban.common.widget.dialog.CommonPopupDialog +//import com.yizhuan.erban.common.widget.dialog.DialogManager +//import com.yizhuan.erban.databinding.ActivityUserInfoBinding +//import com.yizhuan.erban.decoration.view.DecorationStoreActivity +//import com.yizhuan.erban.family.view.activity.FamilyHomeActivity +//import com.yizhuan.erban.family.view.activity.FamilyMemberListActivity +//import com.yizhuan.erban.family.view.activity.FamilyMemberSearchActivity +//import com.yizhuan.erban.ui.im.avtivity.NimFriendModel +//import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity +//import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity.SYSTEM_MESSAGE_UID +//import com.yizhuan.erban.ui.relation.AttentionListActivity +//import com.yizhuan.erban.ui.relation.FansListActivity +//import com.yizhuan.erban.ui.user.adapter.MyCarAdapter +//import com.yizhuan.erban.ui.user.adapter.MyMagicWallAdapter +//import com.yizhuan.erban.ui.utils.ImageLoadUtils +//import com.yizhuan.erban.ui.widget.ObservableScrollView +//import com.yizhuan.erban.utils.RegexUtil +//import com.yizhuan.xchat_android_core.Constants +//import com.yizhuan.xchat_android_core.audio.AudioPlayAndRecordManager +//import com.yizhuan.xchat_android_core.auth.AuthModel +//import com.yizhuan.xchat_android_core.decoration.car.CarInfo +//import com.yizhuan.xchat_android_core.decoration.car.CarInfo.STATUS_OFF_SHELF +//import com.yizhuan.xchat_android_core.decoration.car.CarModel +//import com.yizhuan.xchat_android_core.family.bean.FamilyInfo +//import com.yizhuan.xchat_android_core.family.model.FamilyModel +//import com.yizhuan.xchat_android_core.im.friend.IMFriendModel +//import com.yizhuan.xchat_android_core.initial.InitModel +//import com.yizhuan.xchat_android_core.level.UserLevelVo +//import com.yizhuan.xchat_android_core.magic.bean.MagicInfo +//import com.yizhuan.xchat_android_core.magic.MagicModel +//import com.yizhuan.xchat_android_core.manager.AvRoomDataManager +//import com.yizhuan.xchat_android_core.manager.IMNetEaseManager +//import com.yizhuan.xchat_android_core.manager.RoomEvent +//import com.yizhuan.xchat_android_core.noble.NobleUtil +//import com.yizhuan.xchat_android_core.praise.IPraiseClient +//import com.yizhuan.xchat_android_core.praise.PraiseModel +//import com.yizhuan.xchat_android_core.room.IRoomCore +//import com.yizhuan.xchat_android_core.room.IRoomCoreClient +//import com.yizhuan.xchat_android_core.room.bean.RoomInfo +//import com.yizhuan.xchat_android_core.user.UserModel +//import com.yizhuan.xchat_android_core.user.bean.GiftWallInfo +//import com.yizhuan.xchat_android_core.user.bean.UserInfo +//import com.yizhuan.xchat_android_core.user.bean.UserPhoto +//import com.yizhuan.xchat_android_core.user.event.OtherUserInfoEvent +//import com.yizhuan.xchat_android_core.utils.StarUtils +//import com.yizhuan.xchat_android_core.utils.net.BeanObserver +//import com.yizhuan.xchat_android_library.annatation.ActLayoutRes +//import com.yizhuan.xchat_android_library.coremanager.CoreEvent +//import com.yizhuan.xchat_android_library.coremanager.CoreManager +//import com.yizhuan.xchat_android_library.utils.ListUtils +//import com.yizhuan.xchat_android_library.utils.SizeUtils +//import com.yizhuan.xchat_android_library.utils.StringUtils +//import com.yizhuan.xchat_android_library.widget.ButtonItem +//import kotlinx.android.synthetic.main.activity_user_info.* +//import kotlinx.android.synthetic.main.layout_user_car_store.* +//import kotlinx.android.synthetic.main.layout_user_family.* +//import kotlinx.android.synthetic.main.layout_user_magic_wall.* +//import kotlinx.android.synthetic.main.user_info_gift_list_layout.* +//import org.greenrobot.eventbus.EventBus +//import org.greenrobot.eventbus.Subscribe +//import org.greenrobot.eventbus.ThreadMode +//import java.net.MalformedURLException +//import java.net.URL +//import java.util.* +// +///** +// * 用户中心 +// * +// * @author zhouxiangfeng +// * @date 2017/5/24 +// */ +//@ActLayoutRes(R.layout.activity_user_info) +//class UserInfoActivity : BaseBindingActivity(), +// View.OnClickListener, UserPhotoAdapter.ImageClickListener, +// ObservableScrollView.ScrollViewListener { +// +// override fun init() { +// +// } +// +// private var userInfo: UserInfo? = null +// private var userId: Long = 0 +// private var mRoomInfo: RoomInfo? = null +// private var audioPlayer: AudioPlayer? = null +// private var audioManager: AudioPlayAndRecordManager? = null +// +// private var bottomViewLayout: LinearLayout? = null +// private var sendMsgLayout: TextView? = null +// private var attentionLayout: TextView? = null +// +// private var userInfoCarNoText: TextView? = null +// private var userInfoCarBuyNow: AppCompatButton? = null +// private var emptyView: LinearLayout? = null +// +// private var adapter: GiftWallAdapter? = null +// private var mActivity: UserInfoActivity? = null +// private var mIslike: Boolean = false +// private var mAttenDrawable: Drawable? = null +// +// private var mCarListAdapter: MyCarAdapter? = null +// private var mMagicListAdapter: MyMagicWallAdapter? = null +// +// private var playState = PlayState.NORMAL +// private var flag = 0 +// private var mSVGAParser: SVGAParser? = null +// private var isNoble: Boolean = false +// +// private var onPlayListener: OnPlayListener? = object : OnPlayListener { +// +// // 音频转码解码完成,会马上开始播放了 +// override fun onPrepared() {} +// +// // 播放结束 +// override fun onCompletion() { +// playState = PlayState.NORMAL +// showByPlayState() +// } +// +// // 播放被中断了 +// override fun onInterrupt() { +// playState = PlayState.NORMAL +// showByPlayState() +// } +// +// // 播放过程中出错。参数为出错原因描述 +// override fun onError(error: String) { +// playState = PlayState.NORMAL +// showByPlayState() +// } +// +// // 播放进度报告,每隔 500ms 会回调一次,告诉当前进度。 参数为当前进度,单位为毫秒,可用于更新 UI +// override fun onPlaying(curPosition: Long) {} +// } +// +// +// override fun onCreate(savedInstanceState: Bundle?) { +// super.onCreate(savedInstanceState) +// mActivity = this +// onFindViews() +// onSetListener() +// userId = intent.getLongExtra("userId", 0) +// +// EventBus.getDefault().register(this) +// +// UserModel.get().getUserInfo(userId, true) +// .subscribe { userInfo -> +// this.userInfo = userInfo +// if (userInfo!!.carInfo != null && userInfo.carInfo!!.isUsing) { +// try { +// mSVGAParser!!.parse(URL(userInfo.carInfo!!.effect), +// object : SVGAParser.ParseCompletion { +// override fun onComplete(videoItem: SVGAVideoEntity) { +// user_info_svga_car.visibility = VISIBLE +// user_info_svga_car.loops = 1 +// val drawable = SVGADrawable(videoItem) +// user_info_svga_car.setImageDrawable(drawable) +// user_info_svga_car.startAnimation() +// } +// +// override fun onError() { +// user_info_svga_car.visibility = GONE +// } +// }) +// } catch (e: MalformedURLException) { +// e.printStackTrace() +// } +// } +// } +// user_info_svga_car!!.callback = object : SVGACallback { +// override fun onPause() {} +// override fun onRepeat() {} +// override fun onStep(frame: Int, percentage: Double) {} +// override fun onFinished() { +// } +// } +// +// +// mAttenDrawable = ContextCompat.getDrawable(this, R.mipmap-xhdpi.icon_new_attention) +// +// car_recycler_view.layoutManager = +// LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) +// mCarListAdapter = MyCarAdapter() +// mCarListAdapter!!.bindToRecyclerView(car_recycler_view) +// mCarListAdapter!!.setOnItemChildClickListener { _, _, position -> +// if (AuthModel.get().currentUid == userInfo!!.uid) { +// CarActivity.start(this, 1) +// } else { +// val carInfo = mCarListAdapter!!.data[position] +// if (carInfo!!.status == STATUS_OFF_SHELF) { +// toast(R.string.car_user_info_off_shelf) +// } else { +// CarActivity.start(this, 0) +// } +// } +// } +// +// user_info_svga_car!!.clearAnimation() +// user_info_svga_car!!.visibility = GONE +// mSVGAParser = SVGAParser(this) +// +// // 魔法墙 +// recycler_view_magic_wall.layoutManager = +// LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) +// mMagicListAdapter = MyMagicWallAdapter() +// mMagicListAdapter!!.bindToRecyclerView(recycler_view_magic_wall) +// +// if (AuthModel.get().currentUid == userId) { +// tv_send_car!!.text="立即购买" +// iv_edit!!.visibility = VISIBLE +// tv_attention_count!!.setOnClickListener(this) +// tv_user_attention_text!!.setOnClickListener(this) +// tv_fans_count!!.setOnClickListener(this) +// tv_user_fan_text!!.setOnClickListener(this) +// user_where!!.visibility = GONE +// if (bottomViewLayout != null) +// bottomViewLayout!!.visibility = GONE +// } else { +// tv_send_car!!.text="送TA一部" +// iv_edit!!.visibility = GONE +// if (userId == 90003989L || userId == SYSTEM_MESSAGE_UID) { +// iv_more!!.visibility = GONE +// } else { +// iv_more!!.visibility = VISIBLE +// } +// user_where!!.visibility = VISIBLE +// +// if (bottomViewLayout == null) { +// val view = vs_bottom_layout!!.inflate() +// bottomViewLayout = view.findViewById(R.id.bottom_view_layout) +// sendMsgLayout = view.findViewById(R.id.send_msg_layout) +// attentionLayout = view.findViewById(R.id.attention_layout) +// sendMsgLayout!!.setOnClickListener(this) +// attentionLayout!!.setOnClickListener(this) +// } +// bottomViewLayout!!.visibility = VISIBLE +// } +// +// mCompositeDisposable.add(IMNetEaseManager.get().chatRoomEventObservable +// .subscribe { roomEvent -> +// if (roomEvent != null) { +// when (roomEvent.event) { +// RoomEvent.KICK_OUT_ROOM -> { +// val reason = roomEvent.reason +// if (reason != null) { +// val kickOutReason = reason.reason +// if (kickOutReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { +// user_room!!.visibility = GONE +// } +// } +// } +// } +// } +// }) +// } +// +// +// @Subscribe(threadMode = ThreadMode.MAIN) +// fun onRequestUserInfo(event: OtherUserInfoEvent?) { +// val info = event!!.data +// if (info!!.uid == userId) { +// userInfo = info +// initDatas(userInfo) +// } +// } +// +// @Subscribe(threadMode = ThreadMode.MAIN) +// fun onCurrentUserInfoUpdate(info: UserInfo?) { +// if (info!!.uid == userId) { +// userInfo = info +// initDatas(userInfo) +// } +// } +// +// private fun onSetListener() { +// iv_edit!!.setOnClickListener(this) +// iv_more!!.setOnClickListener(this) +// tv_duration!!.setOnClickListener(this) +// user_room!!.setOnClickListener(this) +// +// iv_back!!.setOnClickListener(this) +// user_where!!.setOnClickListener(this) +// tv_send_car!!.setOnClickListener(this) +// } +// +// override fun needSteepStateBar(): Boolean { +// return true +// } +// +// private fun onFindViews() { +// audioManager = AudioPlayAndRecordManager.getInstance() +// audioPlayer = audioManager!!.getAudioPlayer(null, onPlayListener) +// +// val mLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) +// photo_recyclerView!!.layoutManager = mLayoutManager +// +// val manager = GridLayoutManager(recycler_view!!.context, 4) +// recycler_view!!.layoutManager = manager +// +// scroll_view!!.setScrollViewListener(this) +// } +// +// private fun showByPlayState() { +// var drawable: Drawable? = null +// if (playState == PlayState.NORMAL) { +// drawable = ContextCompat.getDrawable(this, R.mipmap-xhdpi.ic_user_info_stop) +// } else if (playState == PlayState.PLAYING) { +// drawable = ContextCompat.getDrawable(this, R.mipmap-xhdpi.ic_user_info_play) +// } +// if (drawable != null) +// tv_duration!!.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null) +// } +// +// private fun initDatas(userInfo: UserInfo?) { +// if (null != userInfo) { +// showByPlayState() +// +// ImageLoadUtils.loadBigAvatar(this, userInfo.avatar, imageView, false) +// +// CoreManager.getCore(IRoomCore::class.java).requestRoomInfo(userInfo.uid, Constants.PAGE_TYPE_USER_INFO_ACTIVITY) +// tv_nick!!.text = userInfo.nick?.replace(Regex(RegexUtil.getNotPrintableStringReg()), "?") +// val drawable = ContextCompat.getDrawable(this, +// if (userInfo.gender == 1) R.drawable.icon_man else R.drawable.icon_female) +// tv_nick!!.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null) +// +// tv_attention_count!!.text = userInfo.followNum.toString() +// tv_fans_count!!.text = userInfo.fansNum.toString() +// +// //设置家族 +// if (FamilyInfo.NO_FAMILY_ID == userInfo.familyId || TextUtils.isEmpty(userInfo.familyId) +// || InitModel.get().isMarketChecking){ +// ll_my_family_container.visibility = GONE +// } else{ +// FamilyModel.Instance().loadFamilySimpleInfoV2(userInfo.familyId) +// .compose(bindUntilEvent(ActivityEvent.DESTROY)) +// .subscribe(object : BeanObserver() { +// override fun onErrorMsg(error: String) { +// toast(error) +// } +// +// override fun onSuccess(familyInfo: FamilyInfo) { +// ll_my_family_container.visibility = VISIBLE +// GlideApp.with(mActivity) +// .load(familyInfo.familyIcon) +// .dontAnimate() +// .placeholder(R.drawable.default_cover) +// .transforms(CenterCrop(), +// RoundedCorners(10)) +// .error(R.drawable.default_cover) +// .into(iv_family_cover) +// tv_family_name.text = familyInfo.familyName +// tv_family_id.text = String.format(resources.getString(R.string.family_id),familyInfo.familyId) +// tv_family_member_count.text = String.format(resources.getString(R.string.family_member_count),familyInfo.memberCount) +// ll_my_family.setOnClickListener { +// if(intent.extras.getInt("from",1) == FROM_TYPE_NORMAL){ +// //这里限制循环访问, 例如:家族->个人主页->家族->个人主页->.... +// FamilyHomeActivity.start(mActivity, familyInfo.familyId) +// }else{ +// onBackPressed() +// } +// } +// } +// }) +// +// +//// mvpPresenter.loadFamilyData(userInfo.familyId) +//// .subscribe(object :SingleObserver{ +//// +//// override fun onSubscribe(d: Disposable) { +//// mCompositeDisposable.add(d) +//// } +//// +//// override fun onSuccess(familyInfo: FamilyInfo) { +//// ll_my_family_container.visibility = VISIBLE +//// GlideApp.with(mActivity) +//// .load(familyInfo.familyIcon) +//// .dontAnimate() +//// .placeholder(R.drawable.default_cover) +//// .transforms(CenterCrop(), +//// RoundedCorners(10)) +//// .error(R.drawable.default_cover) +//// .into(iv_family_cover) +//// tv_family_name.text = familyInfo.familyName +//// tv_family_id.text = String.format(resources.getString(R.string.family_id),familyInfo.familyId) +//// tv_family_member_count.text = String.format(resources.getString(R.string.family_member_count),familyInfo.memberCount) +//// ll_my_family.setOnClickListener { +//// if(intent.extras.getInt("from",1) == FROM_TYPE_NORMAL){ +//// //这里限制循环访问, 例如:家族->个人主页->家族->个人主页->.... +//// FamilyHomeActivity.start(mActivity, familyInfo.familyId) +//// }else{ +//// onBackPressed() +//// } +//// } +//// } +//// override fun onError(e: Throwable) { +//// toast(e.message) +//// } +//// +//// }) +// +// } +// +// //设置星座 +// val star = StarUtils.getConstellation(Date(userInfo.birth)) +// if (null == star) { +// tv_constellation!!.visibility = View.GONE +// } else { +// tv_constellation!!.text = star +// tv_constellation!!.visibility = View.VISIBLE +// } +// tv_erban_id!!.text = getString(R.string.me_user_id, userInfo.erbanNo) +// tv_user_desc!!.text = userInfo.userDesc +// +// setUserLevel(userInfo.userLevelVo) +// +// val nobleInfo = userInfo.nobleInfo +// var headWearInfo = userInfo.userHeadwear +// if (nobleInfo != null) { +// setBgByLevel(true) +// NobleUtil.loadResource(nobleInfo.headWear, iv_avatar_head_wear) +// val zoneBg = nobleInfo.zoneBg +// if (TextUtils.isEmpty(zoneBg)) { +// ImageLoadUtils.loadImage(this, userInfo.avatar, avatar_bg) +// } else { +// ImageLoadUtils.loadImage(this, zoneBg, avatar_bg) +// } +// NobleUtil.loadResource(NobleUtil.getBadgeByLevel(nobleInfo.level), iv_user_noble_level) +// } else { +// setBgByLevel(false) +// iv_user_noble_level!!.setImageDrawable(null) +// ImageLoadUtils.loadImageWithBlurTransformation(this, userInfo.avatar, avatar_bg) +// } +// if(headWearInfo!=null){ +// iv_avatar_head_wear.setImageDrawable(null) +// iv_avatar_head_wear.visibility = VISIBLE +// NobleUtil.loadHeadWear(headWearInfo.pic, iv_avatar_head_wear) +// } +// +// tv_duration!!.text = getString(R.string.user_info_voice_dur, userInfo.voiceDura) +// +// //设置靓号 +// val hasPrettyErbanNo = userInfo.isHasPrettyErbanNo +// iv_good_number!!.visibility = if (hasPrettyErbanNo) View.VISIBLE else View.GONE +// iv_good_number!!.setBackgroundDrawable(if (hasPrettyErbanNo) +// ContextCompat.getDrawable(this, R.mipmap-xhdpi.ic_good_number) +// else +// null) +// val params = iv_good_number!!.layoutParams as RelativeLayout.LayoutParams +// params.rightMargin = if (hasPrettyErbanNo) SizeUtils.dp2px(this, 3f) else 0 +// +// //贵族相关信息 +// val privatePhoto = userInfo.privatePhoto +// if (ListUtils.isListEmpty(privatePhoto)) { +// photo_recyclerView!!.visibility = View.GONE +// tv_empty_photo!!.visibility = View.VISIBLE +// } else { +// photo_recyclerView!!.visibility = View.VISIBLE +// tv_empty_photo!!.visibility = View.GONE +// val photoAdapter = UserPhotoAdapter(privatePhoto, 0, userInfo.uid) +// photo_recyclerView!!.adapter = photoAdapter +// photoAdapter.setImageClickListener(this) +// } +// +// if (AuthModel.get().currentUid != userInfo.uid) { +// PraiseModel.get().isPraised(AuthModel.get().currentUid, userInfo.uid) +// } +// UserModel.get().requestUserGiftWall(userId, 2) +// .subscribe(object : BeanObserver>() { +// override fun onErrorMsg(error: String) { +// onRequestGiftWallFail(error) +// } +// +// override fun onSuccess(t: List) { +// onRequestGiftWall(t) +// } +// }) +// +// // 获取车库数据 +// //mvpPresenter.getGarageCars(userId) +// CarModel.get().getMyCars(AuthModel.get().ticket, userId) +// .compose(bindUntilEvent(ActivityEvent.DESTROY)) +// .subscribe({ list -> getGarageCarsSuccessView(list as MutableList?) } +// , { t -> getGarageCarsFailView(t) }) +// +// // 获取魔法数据 +// //mvpPresenter.getMyMagicWall(userId) +// MagicModel.get().getTargetMagicWall(userId) +// .compose(bindUntilEvent(ActivityEvent.DESTROY)) +// .subscribe({ list -> getMagicWallSuccessView(list as MutableList?)}, +// {t -> getMagicWallFailView(t) }) +// } +// } +// +// private fun setUserLevel(userLevelVo: UserLevelVo?) { +// iv_user_charm!!.visibility = View.GONE +// iv_user_level!!.visibility = View.GONE +// if (userLevelVo != null) { +// val userLevelUrl: String? = userLevelVo.getExperUrl() +// val userCharmUrl: String? = userLevelVo.getCharmUrl() +// if (!TextUtils.isEmpty(userLevelUrl)) { +// iv_user_level!!.visibility = View.VISIBLE +// ImageLoadUtils.loadImage(this, userLevelUrl, iv_user_level) +// } +// if (!TextUtils.isEmpty(userCharmUrl)) { +// iv_user_charm!!.visibility = View.VISIBLE +// ImageLoadUtils.loadImage(this, userCharmUrl, iv_user_charm) +// } +// } +// } +// +// private fun setBgByLevel(isNoble: Boolean) { +// this.isNoble = isNoble +// iv_avatar_head_wear!!.visibility = if (isNoble) View.VISIBLE else View.GONE +// iv_user_noble_level!!.visibility = if (isNoble) View.VISIBLE else View.INVISIBLE +// val layoutParams = iv_user_noble_level!!.layoutParams as RelativeLayout.LayoutParams +// layoutParams.width = if (isNoble) SizeUtils.dp2px(this, 17f) else 0 +// layoutParams.height = if (isNoble) SizeUtils.dp2px(this, 17f) else 0 +// val nobleColor = ContextCompat.getColor(this, R.color.color_1D1F1F) +// ll_user_info!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// ll_add_user_album!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// ll_user_gift!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// user_info_car_layout!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// rl_user_info_magic_layout!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// rl_user_info_magic_layout!!.setBackgroundColor(if (isNoble) nobleColor else Color.WHITE) +// +// ll_my_family_container.setBackgroundColor(if(isNoble) nobleColor else Color.WHITE); +// +// scroll_view!!.setBackgroundColor(ContextCompat.getColor(this, +// if (isNoble) R.color.color_0f0f0f else R.color.common_bg_color)) +// gift_view_line!!.setBackgroundColor(ContextCompat.getColor(this, +// if (isNoble) R.color.color_0f0f0f else R.color.common_divider_color)) +// family_view_line!!.setBackgroundColor(ContextCompat.getColor(this, +// if (isNoble) R.color.color_0f0f0f else R.color.common_divider_color)) +// car_view_line!!.setBackgroundColor(ContextCompat.getColor(this, +// if (isNoble) R.color.color_0f0f0f else R.color.common_divider_color)) +// magic_view_line!!.setBackgroundColor(ContextCompat.getColor(this, +// if (isNoble) R.color.color_0f0f0f else R.color.common_divider_color)) +// +// val nobleTextColor = ContextCompat.getColor(this, R.color.white_op_30) +// val normalTextColor = ContextCompat.getColor(this, R.color.color_999999) +// +// tv_empty_photo!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// tv_user_desc!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// tv_user_desc_text!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// gift_number!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// gift_number_text!!.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this, R.color.color_333333)) +// tv_constellation_text!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// tv_constellation!!.setTextColor(if (isNoble) nobleTextColor else Color.WHITE) +// +// car_number!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// car_text!!.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this, R.color.color_333333)) +// +// tv_magic_number!!.setTextColor(if (isNoble) nobleTextColor else normalTextColor) +// tv_magic_text!!.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this, R.color.color_333333)) +// +// tv_family_title.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this,R.color.color_1A1A1A)) +// tv_family_name.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this,R.color.color_1A1A1A)) +// tv_family_id.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this,R.color.color_999999)) +// tv_family_member_count.setTextColor(if (isNoble) nobleTextColor else ContextCompat.getColor(this,R.color.color_999999)) +// +// } +// +// override fun click(position: Int, userPhoto: UserPhoto?, isOwner: Boolean) { +// if (isOwner) { +// if (position > 0) { +// showUserPhoto(position - 1) +// } else { +// UIHelper.showModifyPhotosAct(this@UserInfoActivity, userId) +// } +// } else { +// //创建一个集合拿来做用户所有照片信息 +// showUserPhoto(position) +// } +// } +// +// private fun showUserPhoto(position: Int) { +// //创建一个集合拿来做用户所有照片信息 +// val userPhotos = ArrayList() +// val realmList = userInfo!!.privatePhoto +// for (i in realmList.indices) { +// val photo = realmList[i] +// val newPhoto = UserPhoto() +// newPhoto.pid = photo!!.pid +// newPhoto.photoUrl = photo!!.photoUrl +// userPhotos.add(newPhoto) +// } +// val intent = Intent(mActivity, ShowPhotoActivity::class.java) +// intent.putExtra("position", position) +// intent.putExtra("photoList", userPhotos) +// startActivity(intent) +// } +// +// override fun onClick(v: View) { +// when (v.id) { +// R.id.iv_more -> if (userInfo != null && !TextUtils.isEmpty(userInfo!!.uid.toString())) { +// val account = userInfo!!.uid.toString() +// val inMyBlackList = NimFriendModel.get().isInMyBlackList(account) +// val buttonItems = ArrayList(2) +// if (!inMyBlackList) { +// val blackListItem = ButtonItemFactory.createAddToBlackListItem(dialogManager, account) +// buttonItems.add(blackListItem) +// } +// val reportItem = ButtonItemFactory.createReportItem(account) +// buttonItems.add(reportItem) +// CommonPopupDialog(this, "", buttonItems, "取消", false).show() +// } +// R.id.iv_edit -> UIHelper.showUserInfoModifyAct(this@UserInfoActivity, userId) +// R.id.tv_duration -> if (userInfo != null) { +// if (!StringUtils.isEmpty(userInfo!!.userVoice)) { +// voiceClicked() +// } +// } +// R.id.iv_back -> finish() +// R.id.tv_attention_count, R.id.tv_user_attention_text -> mActivity!!.startActivity(Intent(mActivity, AttentionListActivity::class.java)) +// R.id.tv_fans_count, R.id.tv_user_fan_text -> mActivity!!.startActivity(Intent(mActivity, FansListActivity::class.java)) +// R.id.user_room -> if (mRoomInfo != null) { +// LogUtil.i(TAG, "进入的房间: " + mRoomInfo!!.uid) +// AVRoomActivity.start(this, mRoomInfo!!.uid, mRoomInfo!!.type) +// } +// R.id.send_msg_layout -> { +// val nimUserInfo = NimUserInfoCache.getInstance().getUserInfo(userId.toString()) +// if (nimUserInfo != null) { +// NimP2PMessageActivity.start(this, userId.toString()) +// } else { +// NimUserInfoCache.getInstance().getUserInfoFromRemote(userId.toString(), +// object : RequestCallbackWrapper() { +// override fun onResult(i: Int, nimUserInfo: NimUserInfo?, throwable: Throwable?) { +// if (i == 200) { +// NimP2PMessageActivity.start(this@UserInfoActivity, userId.toString()) +// } else { +// toast("网络异常,请重试") +// } +// } +// }) +// } +// } +// R.id.attention_layout -> +// if (mIslike) { +// val isMyFriend = IMFriendModel.get().isMyFriend(userInfo!!.uid.toString()) +// val tip = if (isMyFriend) "取消关注将不再是好友关系,确定取消关注?" else "确定取消关注?" +// +// dialogManager.showOkCancelDialog(tip, true, object : DialogManager.OkCancelDialogListener { +// override fun onCancel() { +// dialogManager.dismissDialog() +// } +// +// override fun onOk() { +// dialogManager.dismissDialog() +// dialogManager.showProgressDialog(this@UserInfoActivity, getString(R.string.waiting_text)) +// PraiseModel.get().cancelPraise(userInfo!!.uid) +// } +// }) +// } else { +// dialogManager.showProgressDialog(this@UserInfoActivity, getString(R.string.waiting_text)) +// if (userInfo != null) { +// PraiseModel.get().praise(userInfo!!.uid) +// } +// } +// R.id.user_where -> { +// dialogManager.showProgressDialog(this, "请稍后...") +// CoreManager.getCore(IRoomCore::class.java).getUserRoom(userId) +// +//// /**************** 测试代码 **************/ +//// AVRoomActivity.start(this, 91, mRoomInfo!!.type) +// } +// R.id.user_info_btn_buy_now -> +// startActivity(Intent(this, CarActivity::class.java)) +// R.id.tv_send_car -> +// DecorationStoreActivity.start(this,userId,1) +// } +// } +// +// override fun onScrollChanged(view: NestedScrollView, x: Int, y: Int, oldx: Int, oldy: Int) { +// if (flag == 0 && oldy > 300) { +// flag = 1 +// tv_title!!.visibility = View.VISIBLE +// if (userInfo != null) { +// tv_title!!.text = userInfo!!.nick +// } +// val isNoble = userInfo != null && userInfo!!.nobleInfo != null +// tv_title!!.setTextColor(if (isNoble) +// ContextCompat.getColor(this, R.color.white) +// else +// ContextCompat.getColor(this, R.color.text_color_primary)) +// rl_nav!!.setBackgroundResource(if (!isNoble) R.color.white else R.color.color_1D1F1F) +// iv_back!!.setImageResource(if (isNoble) R.drawable.arrow_left_white else R.drawable.icon_arrow_left_black) +// iv_edit!!.setImageResource(if (isNoble) R.drawable.icon_user_info_edit else R.drawable.icon_edit_black) +// } else if (flag == 1 && oldy <= 300) { +// flag = 0 +// tv_title!!.visibility = View.GONE +// +// rl_nav!!.setBackgroundResource(R.color.transparent) +// iv_back!!.setImageResource(R.drawable.arrow_left_white) +// iv_edit!!.setImageResource(R.drawable.icon_user_info_edit) +// } +// } +// +// +// private interface PlayState { +// companion object { +// val NORMAL = 0 +// val PLAYING = 1 +// } +// } +// +// private fun voiceClicked() { +// if (playState == PlayState.NORMAL) { +// playState = PlayState.PLAYING +// audioPlayer!!.setDataSource(userInfo!!.userVoice) +// audioManager!!.play() +// } else if (playState == PlayState.PLAYING) { +// playState = PlayState.NORMAL +// audioManager!!.stopPlay() +// +// } +// showByPlayState() +// } +// +// private fun setTextViewLeftDrawable(tvPlayAudio: TextView, drawId: Int) { +// val drawablePlay = resources.getDrawable(drawId) +// drawablePlay.setBounds(0, 0, drawablePlay.minimumWidth, drawablePlay.minimumHeight) +// tvPlayAudio.setCompoundDrawables(drawablePlay, null, null, null) +// } +// +// fun getMagicWallSuccessView(magicInfoList: MutableList?) { +// if (ListUtils.isListEmpty(magicInfoList)) { +// if (rl_user_info_magic_layout != null) { +// rl_user_info_magic_layout.visibility = GONE +// } +// return +// } +// val allMagicCounts = magicInfoList!!.sumBy { magicInfo -> magicInfo.amount } +// tv_magic_number!!.text = getString(R.string.user_info_gift_number, allMagicCounts) +// mMagicListAdapter!!.isNoble = isNoble +// mMagicListAdapter!!.setNewData(magicInfoList) +// } +// +// fun getMagicWallFailView(throwable: Throwable?) { +// } +// +// fun getGarageCarsSuccessView(carInfoList: MutableList?) { +// if (ListUtils.isListEmpty(carInfoList)) { +// car_number!!.text = getString(R.string.user_info_gift_number, 0) +// if (emptyView == null) { +// emptyView = LayoutInflater.from(this).inflate(R.layout.user_info_car_empty, null, false) as LinearLayout? +// val param = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, SizeUtils.dp2px(this, 79f)) +// emptyView!!.layoutParams = param +// userInfoCarNoText = emptyView!!.findViewById(R.id.user_info_car_no_text) +// userInfoCarBuyNow = emptyView!!.findViewById(R.id.user_info_btn_buy_now) +// userInfoCarBuyNow!!.setOnClickListener(this) +// } +// if (AuthModel.get().currentUid == userId) { +// userInfoCarNoText!!.text = getString(R.string.user_info_car_no_text_for_my) +// userInfoCarBuyNow!!.visibility = GONE +// } else { +// userInfoCarNoText!!.text = getString(R.string.user_info_car_no_text_for_other) +// userInfoCarBuyNow!!.visibility = GONE +// } +// mCarListAdapter!!.emptyView = emptyView +// return +// } +// carInfoList!!.removeAt(0) +// car_number!!.text = getString(R.string.user_info_gift_number, carInfoList!!.size) +// mCarListAdapter!!.setNewData(carInfoList) +// } +// +// fun getGarageCarsFailView(throwable: Throwable?) { +// throwable!!.printStackTrace() +// } +// +// +// @CoreEvent(coreClientClass = IRoomCoreClient::class) +// fun onGetRoomInfo(roomInfo: RoomInfo?, pageType: Int) { +// if (roomInfo == null) { +// //该用户还未开房间 +// user_room!!.visibility = View.GONE +// return +// } +// if (Constants.PAGE_TYPE_USER_INFO_ACTIVITY == pageType) { +// //已经存在的activity +// if (mRoomInfo != null && mRoomInfo!!.roomId == roomInfo.roomId) { +// mRoomInfo = roomInfo +// } else if (mRoomInfo == null) { +// //打开新的activity的时候 +// mRoomInfo = roomInfo +// } +// user_room!!.visibility = if (roomInfo.isValid) View.VISIBLE else View.GONE +// } +// } +// +// @CoreEvent(coreClientClass = IRoomCoreClient::class) +// fun onGetUserRoom(roomInfo: RoomInfo?) { +// dialogManager.dismissDialog() +// val current = AvRoomDataManager.get().mCurrentRoomInfo +// if (roomInfo != null && roomInfo.uid > 0) { +// if (current != null) { +// if (current.uid == roomInfo.uid) { +// toast("已经和对方在同一个房间") +// return +// } +// } +// AVRoomActivity.start(this, roomInfo.uid, roomInfo.type) +// } else { +// toast("对方不在房间内") +// } +// } +// +// @CoreEvent(coreClientClass = IRoomCoreClient::class) +// fun onGetUserRoomFail(msg: String) { +// dialogManager.dismissDialog() +// toast(msg) +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onIsLiked(islike: Boolean, uid: Long) { +// setLikedText(islike) +// } +// +// private fun setLikedText(isliked: Boolean) { +// mIslike = isliked +// attentionLayout!!.setCompoundDrawablesWithIntrinsicBounds(if (!isliked) mAttenDrawable else ColorDrawable(Color.TRANSPARENT), null, null, null) +// attentionLayout!!.compoundDrawablePadding = if (isliked) 0 else SizeUtils.dp2px(this, 5f) +// attentionLayout!!.text = getString(if (isliked) R.string.already_attention else R.string.attention) +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onIsLikedFail(error: String) { +// dialogManager.dismissDialog() +// toast(error) +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onPraise(likedUid: Long) { +// dialogManager.dismissDialog() +// toast("关注成功,相互关注可成为好友哦!") +// setLikedText(true) +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onCanceledPraise(likedUid: Long) { +// toast("取消关注成功") +// dialogManager.dismissDialog() +// setLikedText(false) +// +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onCanceledPraiseFaith(error: String) { +// // getDialogManager().dismissDialog(); +// toast(error) +// } +// +// @CoreEvent(coreClientClass = IPraiseClient::class) +// fun onPraiseFaith(error: String) { +// dialogManager.dismissDialog() +// toast(error) +// } +// +// fun onRequestGiftWall(giftWallInfoList: List?) { +// if (userInfo == null) return +// adapter = GiftWallAdapter(this, ContextCompat.getColor(this, +// if (userInfo!!.nobleInfo == null) R.color.black else R.color.white_op_30)) +// adapter!!.setGiftWallInfoList(giftWallInfoList) +// recycler_view!!.adapter = adapter +// recycler_view!!.isNestedScrollingEnabled = false +// val totalCount = giftWallInfoList!!.indices +// .map { giftWallInfoList[it] } +// .sumBy { it.reciveCount } +// +// if (totalCount == 0) { +// recycler_view!!.visibility = View.GONE +// gift_empty!!.visibility = View.VISIBLE +// } else { +// recycler_view!!.visibility = View.VISIBLE +// gift_empty!!.visibility = View.GONE +// } +// gift_number!!.text = getString(R.string.user_info_gift_number, totalCount) +// } +// +// fun onRequestGiftWallFail(msg: String) { +// dialogManager.dismissDialog() +// toast(msg) +// } +// +// override fun onDestroy() { +// if (onPlayListener != null) { +// onPlayListener = null +// } +// if (audioPlayer != null) { +// audioPlayer!!.onPlayListener = null +// } +// +// if (user_info_svga_car.isAnimating) { +// user_info_svga_car.clearAnimation() +// } +// EventBus.getDefault().unregister(this) +// super.onDestroy() +// } +// +// /**static静态代码*/ +// companion object { +// private val TAG = UserInfoActivity::class.java.simpleName +// private const val FROM_TYPE_NORMAL: Int = 1 +// private const val FROM_TYPE_FAMILY: Int = 2 +// +// fun start(context: Context, userId: Long) { +// val intent = Intent(context, UserInfoActivity::class.java) +// intent.putExtra("userId", userId) +// var from :Int = FROM_TYPE_NORMAL +// if(context is FamilyHomeActivity +// || context is FamilyMemberListActivity +// || context is FamilyMemberSearchActivity){ +// //这里限制循环访问, 例如:家族->个人主页->家族->个人主页->.... +// from = FROM_TYPE_FAMILY +// } +// intent.putExtra("from", from) +// context.startActivity(intent) +// +// } +// +// } +//} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoCarFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoCarFragment.java new file mode 100644 index 000000000..c9a16686c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoCarFragment.java @@ -0,0 +1,234 @@ +package com.yizhuan.erban.ui.user; + +import android.arch.lifecycle.Observer; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.LayoutUserCarStoreBinding; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.decoration.view.MyDecorationActivity; +import com.yizhuan.erban.ui.user.adapter.UserInfoCarAdapter; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.CarButtonInfo; +import com.yizhuan.xchat_android_core.bean.GiftTitleInfo; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.bean.response.ServiceResult; +import com.yizhuan.xchat_android_core.decoration.car.CarModel; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.user.UserInfoUiMgr; + +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.layout_user_car_store) +public class UserInfoCarFragment extends BaseBindingFragment { + + private long userId; + + private UserInfoCarAdapter mUserInfoCarAdapter; + private List mList = new ArrayList<>(); + private Observer mObserver; + + public static UserInfoCarFragment newInstance() { + return new UserInfoCarFragment(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mObserver = new Observer() { + @Override + public void onChanged(@Nullable Long o) { + if (o != null) { + userId = o; + } + + } + }; + UserInfoUiMgr.get().registerUid(this, mObserver); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + + if (isVisibleToUser) { + initData(); + } + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + } + + @Override + public void onSetListener() { + super.onSetListener(); + } + + @Override + public void initiate() { + + mBinding.rvCar.setLayoutManager(new GridLayoutManager(mContext, 2)); + + final int px = SizeUtils.dp2px(mContext, 15); + int spanCount = ((GridLayoutManager) mBinding.rvCar.getLayoutManager()).getSpanCount(); + mBinding.rvCar.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int pos = parent.getChildAdapterPosition(view); + + if (pos == 0) { + outRect.set(-px, 0, 0, 0); + + } else { + + int left, right; + if ((pos - 1) % spanCount == 0) { //第一列 + left = 0; + right = px / 2; + } else { + left = px / 2; + right = 0; + } + outRect.set(left, 0, right, px); + + } + } + }); + + mUserInfoCarAdapter = new UserInfoCarAdapter(mContext, mList); + mUserInfoCarAdapter.bindToRecyclerView(mBinding.rvCar); + mUserInfoCarAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + + List list = mUserInfoCarAdapter.getData(); + if (ListUtils.isListEmpty(list)) + return 2; + + UserInfoItem userInfoItem = list.get(position); + int type = userInfoItem.getItemType(); + if (type == UserInfoItem.TYPE_TITLE + || type == UserInfoItem.TYPE_CAR_BUTTON + || type == UserInfoItem.TYPE_CAR_EMPTY + || type == UserInfoItem.TYPE_DIV) { + return 2; + + } else + return 1; + } + }); + + mUserInfoCarAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List list = mUserInfoCarAdapter.getData(); + if (ListUtils.isListEmpty(list)) + return; + + UserInfoItem userInfoItem = list.get(position); + if (userInfoItem.getItemType() == UserInfoItem.TYPE_CAR_ITEM) { + + if (AuthModel.get().getCurrentUid() == userId) { + MyDecorationActivity.start(mContext, 1); + + } else { + CarInfo carInfo = (CarInfo) userInfoItem.getData(); + if (carInfo.getStatus() == CarInfo.STATUS_OFF_SHELF) { + toast(R.string.car_user_info_off_shelf); + } else { + DecorationStoreActivity.start(mContext, userId, DecorationStoreActivity.TAB_CAR); + } + } + + } else if (userInfoItem.getItemType() == UserInfoItem.TYPE_CAR_BUTTON) { + DecorationStoreActivity.start(mContext, userId, DecorationStoreActivity.TAB_CAR); + } + } + }); + } + + private void initData() { + // 获取车库数据 + CarModel.get().getUserCarsV2(userId) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new SingleObserver>>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(ServiceResult> listServiceResult) { + if (listServiceResult.isSuccess()) { + getGarageCarsSuccessView(listServiceResult.getData()); + } + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + private void getGarageCarsSuccessView(List carInfoList) { + mList.clear(); + + if (ListUtils.isListEmpty(carInfoList)) { + initCarTitle(0); + + UserInfoItem emptyItem = new UserInfoItem(UserInfoItem.TYPE_CAR_EMPTY); + mList.add(emptyItem); + + } else { + initCarTitle(carInfoList.size()); + + for (CarInfo carInfo : carInfoList) { + UserInfoItem carItem = new UserInfoItem<>(UserInfoItem.TYPE_CAR_ITEM, carInfo); + mList.add(carItem); + } + + } + + CarButtonInfo carButtonInfo = new CarButtonInfo(); + if (AuthModel.get().getCurrentUid() == userId) { + carButtonInfo.setContext("立即购买"); + } else { + carButtonInfo.setContext("送TA一部"); + } + UserInfoItem carButtonItem = new UserInfoItem<>(UserInfoItem.TYPE_CAR_BUTTON, carButtonInfo); + mList.add(carButtonItem); + mUserInfoCarAdapter.setNewData(mList); + mUserInfoCarAdapter.notifyDataSetChanged(); + } + + private void initCarTitle(int size) { + GiftTitleInfo giftTitleInfo = new GiftTitleInfo(); + giftTitleInfo.setTitle("座驾"); + giftTitleInfo.setNum(String.valueOf(size)); + UserInfoItem userInfoItem = new UserInfoItem<>(UserInfoItem.TYPE_TITLE, giftTitleInfo); + mList.add(userInfoItem); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoFragment.java new file mode 100644 index 000000000..f5408afed --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoFragment.java @@ -0,0 +1,633 @@ +package com.yizhuan.erban.ui.user; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.RecordingVoiceActivity; +import com.yizhuan.erban.audio.helper.AudioPlayerHelper; +import com.yizhuan.erban.audio.helper.OnPlayListener; +import com.yizhuan.erban.avroom.widget.MessageView; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.module_hall.team.activity.HallTeamMessageActivity; +import com.yizhuan.erban.ui.user.adapter.UserDesAdapter; +import com.yizhuan.erban.ui.user.dialog.LiveTagDialog; +import com.yizhuan.xchat_android_core.audio.AudioModel; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.miniworld.event.MiniWorldStateChangedEvent; +import com.yizhuan.xchat_android_core.module_hall.hall.HallModel; +import com.yizhuan.xchat_android_core.module_hall.hall.bean.OwnerHallInfo; +import com.yizhuan.xchat_android_core.module_hall.team.HTeamModel; +import com.yizhuan.xchat_android_core.module_hall.team.event.HteamListChangeEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.JoinWorldInfo; +import com.yizhuan.xchat_android_core.user.bean.LiveTagInfo; +import com.yizhuan.xchat_android_core.user.bean.UserGameInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_core.utils.StringUtils; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +public class UserInfoFragment extends BaseFragment implements View.OnClickListener { + + public static final int REQUEST_CODE_MY_VOICE = 1; + Unbinder unbinder; + + @BindView(R.id.rv_desc) + RecyclerView rvDesc; + + private UserInfo userInfo; + private long userId = 0; + private int from = 1; + private long time; + + private UserDesAdapter mUserDesAdapter; + private boolean isPlaying; + + public static UserInfoFragment newInstance(long userId, int from) { + UserInfoFragment userInfoFragment = new UserInfoFragment(); + Bundle bundle = new Bundle(); + bundle.putLong("userId", userId); + bundle.putInt("from", from); + userInfoFragment.setArguments(bundle); + return userInfoFragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + + if (bundle != null) { + userId = bundle.getLong("userId", 0); + from = bundle.getInt("from", 1); + } + } + + @Override + public void initiate() { + + initList(); + mUserDesAdapter = new UserDesAdapter(mContext, mList); + mUserDesAdapter.setUserId(userId); + + rvDesc.setLayoutManager(new LinearLayoutManager(mContext)); + rvDesc.setAdapter(mUserDesAdapter); + + mUserDesAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List list = mUserDesAdapter.getData(); + if (ListUtils.isListEmpty(list)) + return; + + UserInfoItem userInfoItem = list.get(position); + if (userInfoItem.getItemType() == UserInfoItem.TYPE_DES_VOICE) { + voiceOption(view); + + } else if (userInfoItem.getItemType() == UserInfoItem.TYPE_DES_FAMILY) { + familyOption((FamilyInfo) userInfoItem.getData()); + + } else if (userInfoItem.getItemType() == UserInfoItem.TYPE_DES_HALL) { + OwnerHallInfo ownerHallInfo = (OwnerHallInfo) userInfoItem.getData(); + hallOption(view, ownerHallInfo); + + } else if (userInfoItem.getItemType() == UserInfoItem.TYPE_DES_TAG) { + tagOption(view); + + } + + } + }); + + initData(userInfo); + + } + + private List mList = new ArrayList<>(); + + private void initList() { + mList.clear(); + + // 相册 + UserInfoItem photoItem = new UserInfoItem(UserInfoItem.TYPE_DES_PHOTO); + mList.add(photoItem); + + // 个人介绍 + UserInfoItem descItem = new UserInfoItem(UserInfoItem.TYPE_DES_PERSONAL); + mList.add(descItem); + + // 我的声音 + UserInfoItem voiceItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + voiceItem.setTag(UserInfoItem.TYPE_DES_VOICE); + mList.add(voiceItem); + + // 小世界 + UserInfoItem joinWorldsItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + joinWorldsItem.setTag(UserInfoItem.TYPE_DES_JOIN_WORLDS); + mList.add(joinWorldsItem); + + // 家族 + UserInfoItem familyItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + familyItem.setTag(UserInfoItem.TYPE_DES_FAMILY); + mList.add(familyItem); + + // 模厅 + UserInfoItem hallItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + hallItem.setTag(UserInfoItem.TYPE_DES_HALL); + mList.add(hallItem); + + // 战绩 + UserInfoItem GameItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + GameItem.setTag(UserInfoItem.TYPE_DES_GAME); + mList.add(GameItem); + + // 认证标签 + UserInfoItem tagItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + tagItem.setTag(UserInfoItem.TYPE_DES_TAG); + mList.add(tagItem); + } + + @Override + public void onFindViews() { + super.onFindViews(); + } + + @Override + public void onPause() { + super.onPause(); + AudioPlayerHelper.get().onPause(); + stopVoice(); + } + + @Override + public void onDestroyView() { + EventBus.getDefault().unregister(this); + unbinder.unbind(); + super.onDestroyView(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + AudioPlayerHelper.get().onDestroy(); + stopVoice(); + } + + private void familyOption(FamilyInfo familyInfo) { + + if (from == UserInfoActivity.Companion.FROM_TYPE_NORMAL) { + //这里限制循环访问, 例如:家族->个人主页->家族->个人主页->.... + FamilyHomeActivity.start(getActivity(), familyInfo.getFamilyId()); + } else { + Activity activity = getActivity(); + if (activity != null) + activity.onBackPressed(); + } + + } + + private void setUserInfoItem(Serializable data, int itemType, boolean canRefresh) { + for (UserInfoItem userInfoItem : mList) { + if (userInfoItem.getTag() == itemType) { + userInfoItem.setItemType(data == null ? UserInfoItem.TYPE_NONE : itemType); + userInfoItem.setData(data); + break; + } + } + + if (canRefresh) + mUserDesAdapter.notifyDataSetChanged(); + + } + + private void initVoiceView(boolean canShow) { + for (UserInfoItem userInfoItem : mList) { + if (userInfoItem.getTag() == UserInfoItem.TYPE_DES_VOICE) { + userInfoItem.setItemType(canShow ? UserInfoItem.TYPE_DES_VOICE : UserInfoItem.TYPE_NONE); + break; + } + } + + } + + private void initJoinWorlds(ArrayList list) { + for (UserInfoItem userInfoItem : mList) { + if (userInfoItem.getTag() == UserInfoItem.TYPE_DES_JOIN_WORLDS) { + userInfoItem.setItemType(list != null && list.size() > 0 ? UserInfoItem.TYPE_DES_JOIN_WORLDS : UserInfoItem.TYPE_NONE); + userInfoItem.setData(list); + break; + } + + } + } + + private void initData(UserInfo userInfo) { + if (userInfo == null) { + return; + } + //每次打开这里都走了四次,先做个处理 + if (System.currentTimeMillis() - time < 2000) { + return; + } + time = System.currentTimeMillis(); + + // 判断是否隐藏声音item + if (AuthModel.get().getCurrentUid() == userId) {// 主态 + initVoiceView(true); + } else {// 客态 + initVoiceView(!StringUtils.isEmpty(userInfo.getUserVoice())); + } + + initJoinWorlds(userInfo.getJoinWorlds()); + + // 判断是否隐藏 认证标签 item + if (userInfo.getUserInfoSkillVo() != null && !ListUtils.isListEmpty(userInfo.getUserInfoSkillVo().getLiveSkillVoList())) { + setUserInfoItem((ArrayList) userInfo.getUserInfoSkillVo().getLiveSkillVoList(), + UserInfoItem.TYPE_DES_TAG, false); + } + + mUserDesAdapter.setUserInfo(userInfo); + //设置家族 + if (FamilyInfo.NO_FAMILY_ID.equals(userInfo.getFamilyId()) || TextUtils.isEmpty(userInfo.getFamilyId()) + || MarketVerifyModel.get().isMarketChecking()) { + } else { + FamilyModel.Instance().loadFamilySimpleInfo(userInfo.getFamilyId()) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + setUserInfoItem(familyInfo, UserInfoItem.TYPE_DES_FAMILY, true); + } + }); + } + + setHallData(userInfo); + setGameInfo(); + } + + @Override + public void onClick(View view) { + } + + private void voiceOption(View view) { + int id = view.getId(); + if (id == R.id.layout_voice_bar) { + voiceClick(); + } else if (id == R.id.iv_voice_more || id == R.id.layout_voice_bar_no_data) { + UIHelper.showMyVoiceAct(this, REQUEST_CODE_MY_VOICE, "个人主页");// 点击则跳转到我的声音页面 + } + } + + private void voiceClick() { + if (AudioPlayerHelper.get().isPlaying()) { + isPlaying = false; + stopVoice(); + } else { + isPlaying = true; + playVoice(); + } + } + + private void playVoice() { + if (StringUtils.isEmpty(userInfo.getUserVoice())) { + return; + } + AudioPlayerHelper.get().playInThread(userInfo.getUserVoice(), new OnPlayListener() { + + @Override + public void onPreStart() { + addPlayCount(userId); + } + + @Override + public void onError(String error) { + if (mUserDesAdapter != null) { + mUserDesAdapter.setPlaying(false);// 播放出错 + mUserDesAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onPrepared() { + if (mUserDesAdapter != null) { + mUserDesAdapter.setPlaying(true);// 准备完毕要开始播放 + mUserDesAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onPlaying(long currDuration) { + } + + @Override + public void onCompletion() { + if (mUserDesAdapter != null) { + mUserDesAdapter.setPlaying(false);// 播放完成 + mUserDesAdapter.notifyDataSetChanged(); + } + } + }); + } + + private void addPlayCount(long voiceUid) { + AudioModel.get().addPlayCount(AuthModel.get().getCurrentUid(), null, voiceUid) + .subscribe(); + } + + private void stopVoice() { + AudioPlayerHelper.get().endPlay(); + if (mUserDesAdapter != null) { + mUserDesAdapter.setPlaying(false);// 触发或点击 停止播放 + mUserDesAdapter.notifyDataSetChanged(); + } + } + + @SuppressWarnings("CheckResult") + private void setGameInfo() { + UserModel.get().getGameWeek(userId) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(userGameInfos -> { + setUserInfoItem((ArrayList) userGameInfos, UserInfoItem.TYPE_DES_GAME, true); + }); + } + + private void hallOption(View view, OwnerHallInfo ownerHallInfo) { + switch (view.getId()) { + case R.id.stv_apply_hall: + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.JOIN_HALL_CLICK, "申请入厅按钮", null); + + if (userInfo == null) { + return; + } + String hallName = null; + + if (ownerHallInfo != null) + hallName = ownerHallInfo.getHallName(); + + if (TextUtils.isEmpty(hallName)) { + hallName = "厅"; + } + MessageView.SpannableBuilder builder = new MessageView.SpannableBuilder(null); + builder.append("确认加入 ") + .append(hallName, new ForegroundColorSpan(getResources().getColor(R.color.appColor))) + .append(" 吗?"); + getDialogManager().showOkCancelDialog(builder.build(), new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + HallModel.get().applyJoinHall(userInfo.getHallId()) + .compose(RxHelper.bindFragment(UserInfoFragment.this)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(String s) { + toast(s); + } + }); + } + }); + break; + case R.id.stv_apply_team: + //加入公开群 + + StatisticManager.Instance().onEvent(BasicConfig.INSTANCE.getAppContext(), + StatisticsProtocol.Event.JOIN_HALL_OPEN_GROUP_CLICK, "加入公开群按钮", null); + + if (ownerHallInfo == null) { + return; + } + HTeamModel.get().joinHteam(ownerHallInfo.getPublicChatId()) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(String s) { + String tid = ownerHallInfo.getPublicTeamId(); + if (!TextUtils.isEmpty(tid)) { + HallTeamMessageActivity.start(getActivity(), tid); + } + } + }); + break; + + case R.id.rl_hall_team_layout: + if (ownerHallInfo == null) { + return; + } + if (ownerHallInfo.getPublicChat() != null && !ownerHallInfo.getPublicChat().isInChat()) { + return; + } + String tid = ownerHallInfo.getPublicTeamId(); + if (!TextUtils.isEmpty(tid)) { + HallTeamMessageActivity.start(getActivity(), tid); + } + break; + } + + } + + private OwnerHallInfo ownerHallInfo; + + /** + * 模厅数据 + */ + private void setHallData(UserInfo userInfo) { + if (userInfo.getHallId() <= 0) { + setUserInfoItem(null, UserInfoItem.TYPE_DES_HALL, true); + return; + } + + HallModel.get().getOwnerHallInfo(userInfo.getUid()) + .compose(RxHelper.bindFragment(this)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(OwnerHallInfo info) { + ownerHallInfo = info; + if (ownerHallInfo == null || ownerHallInfo.getHallId() <= 0) + setUserInfoItem(null, UserInfoItem.TYPE_DES_HALL, true); + + else + setUserInfoItem(ownerHallInfo, UserInfoItem.TYPE_DES_HALL, true); + + } + + @Override + public void onError(Throwable e) { + setUserInfoItem(null, UserInfoItem.TYPE_DES_HALL, true); + } + }); + } + + private void setHallInfo(OwnerHallInfo info) { + + for (UserInfoItem item : mList) { + if (item.getItemType() == UserInfoItem.TYPE_DES_HALL) { + item.setData(info); + break; + } + } + + mUserDesAdapter.notifyDataSetChanged(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onHteamListChange(HteamListChangeEvent event) { + if (userInfo == null) { + return; + } + setHallData(userInfo); + } + + public void onGetUserInfo(UserInfo userInfo) { + if (isDestroyView) { + return; + } + this.userInfo = userInfo; + + if (!mIsViewCreated) + return; + + initData(userInfo); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentUserInfoUpdate(LoginUserInfoUpdateEvent event) { + if (UserModel.get().getCacheLoginUserInfo().getUid() == userId) { + userInfo = UserModel.get().getCacheLoginUserInfo(); + initData(userInfo); + } + } + + /** + * 更新主态小世界列表 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMiniWorldStateChangedEvent(MiniWorldStateChangedEvent miniWorldStateChangedEvent) { + if (UserModel.get().getCacheLoginUserInfo().getUid() == userId && + !miniWorldStateChangedEvent.isJoin() && + miniWorldStateChangedEvent.getWorldId() > 0) { + userInfo = UserModel.get().getCacheLoginUserInfo(); + userInfo.removeWorld(miniWorldStateChangedEvent.getWorldId()); + initData(userInfo); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_user_info, container, false); + unbinder = ButterKnife.bind(this, mView); + EventBus.getDefault().register(this); + AudioPlayerHelper.get().onCreate(); + return mView; + } + + private void tagOption(View view) { + switch (view.getId()) { + case R.id.tv_edit: + LiveTagDialog liveTagDialog = new LiveTagDialog(getActivity(), userInfo.getUserInfoSkillVo().getLiveSkillVoList()); + liveTagDialog.openDialog(); + break; + } + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == Activity.RESULT_OK) { + if (requestCode == REQUEST_CODE_MY_VOICE) { + String audioFileUrl = data.getStringExtra(RecordingVoiceActivity.AUDIO_FILE); + int audioDuration = data.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0); + refreshVoiceDataView(audioFileUrl, audioDuration); + } + } + } + + public void refreshVoiceDataView(String audioFileUrl, int audioDuration) { + UserModel.get().getUserInfoFromServer(userId) + .compose(bindToLifecycle()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(UserInfo Info) { + userInfo = Info; + initData(userInfo); + } + }); + // 跳转到我的声音页面,录制了声音,刷新数据显示 + if (mUserDesAdapter != null) { + mUserDesAdapter.setPlaying(false);// 录制完声音 刷新页面显示 + mUserDesAdapter.notifyDataSetChanged(); + } + } + + public boolean isPlaying() { + return isPlaying; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftFragment.java new file mode 100644 index 000000000..286ff372e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftFragment.java @@ -0,0 +1,340 @@ +package com.yizhuan.erban.ui.user; + +import android.arch.lifecycle.Observer; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.GridLayoutManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.FragmentUserInfoGiftBinding; +import com.yizhuan.erban.ui.user.adapter.UserGiftAdapter; +import com.yizhuan.xchat_android_core.bean.GiftTitleInfo; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.bills.RadishGiftModel; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.user.UserInfoUiMgr; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.GiftWallInfo; +import com.yizhuan.xchat_android_core.user.bean.RadishWallInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.fragment_user_info_gift) +public class UserInfoGiftFragment extends BaseBindingFragment { + + private UserInfo userInfo; + private long userId = 0; + + private long time; + + private List userInfoItems = new ArrayList<>(); + private UserGiftAdapter userGiftAdapter; + private Observer mObserver; + private Observer mUidObserver; + + public static UserInfoGiftFragment newInstance() { + return new UserInfoGiftFragment(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mUidObserver = new Observer() { + @Override + public void onChanged(@Nullable Long info) { + if (info != null) { + userId = info; + } + } + }; + + mObserver = new Observer() { + @Override + public void onChanged(@Nullable UserInfo info) { + if (info != null && info.getUid() == userId) { + Log.i("UserInfoGiftFragment", "info not null"); + userInfo = info; + initData(userInfo); + } + + } + }; + + UserInfoUiMgr.get().registerUid(this, mUidObserver); + UserInfoUiMgr.get().register(this, mObserver); + } + + @Override + public void initiate() { + + initUserGiftItems(); + + mBinding.rvGift.setLayoutManager(new GridLayoutManager(mContext, 4)); + userGiftAdapter = new UserGiftAdapter(mContext, userInfoItems); + userGiftAdapter.bindToRecyclerView(mBinding.rvGift); + userGiftAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() { + @Override + public int getSpanSize(GridLayoutManager gridLayoutManager, int position) { + List list = userGiftAdapter.getData(); + if (ListUtils.isListEmpty(list)) + return 4; + + UserInfoItem userInfoItem = list.get(position); + int type = userInfoItem.getItemType(); + if (type == UserInfoItem.TYPE_TITLE + || type == UserInfoItem.TYPE_MAGIC_ITEMS + || type == UserInfoItem.TYPE_RADISH_ITEMS + || type == UserInfoItem.TYPE_DIV + || type == UserInfoItem.TYPE_GIFT_EMPTY) { + return 4; + + } else + return 1; + + } + }); + + Long uid = UserInfoUiMgr.get().getUid(); + if (uid != null) { + userId = uid; + } + userInfo = UserInfoUiMgr.get().getValue(); + initData(userInfo); + } + + private void initUserGiftItems() { + for (int i = 0; i < 7; i++) { + UserInfoItem userInfoItem = new UserInfoItem(UserInfoItem.TYPE_NONE); + userInfoItems.add(userInfoItem); + } + } + + private void initData(UserInfo userInfo) { + if (null != userInfo) { + Log.i("UserInfoGiftFragment", "not null"); + if (System.currentTimeMillis() - time < 2000) { + return; + } + time = System.currentTimeMillis(); + // 获取魔法数据 + MagicModel.get().getTargetMagicWall(userId) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + + } + + @Override + public void onSuccess(List magicInfos) { + getMagicWallSuccessView(magicInfos); + } + }); + + RadishGiftModel.get().getRadishWall(userId) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List radishWallInfos) { + getRadishWallSuccess(radishWallInfos); + + } + + @Override + public void onError(Throwable e) { + getRadishWallSuccess(null); + + } + }); + + UserModel.get().requestUserGiftWall(userId, 2) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + onRequestGiftWallFail(error); + } + + @Override + public void onSuccess(List giftWallInfos) { + onRequestGiftWall(giftWallInfos); + } + }); + + + NobleInfo nobleInfo = userInfo.getNobleInfo(); + userGiftAdapter.setNoble(nobleInfo != null); + userGiftAdapter.setmTextColor(ContextCompat.getColor(mContext, nobleInfo == null ? R.color.black : R.color.color_333333)); + } else { + + Log.i("UserInfoGiftFragment", "null"); + } + } + + private void getRadishWallSuccess(List radishWallInfoList) { + if (ListUtils.isListEmpty(radishWallInfoList)) + return; + + int allMagicCounts = 0; + for (RadishWallInfo magicInfo : radishWallInfoList) { + allMagicCounts += magicInfo.getReceiveCount(); + } + + GiftTitleInfo giftTitleInfo = new GiftTitleInfo(); + giftTitleInfo.setTitle("收到的萝卜礼物"); + giftTitleInfo.setNum(String.valueOf(allMagicCounts)); + UserInfoItem userInfoItemTitle = userInfoItems.get(3); + userInfoItemTitle.setItemType(UserInfoItem.TYPE_TITLE); + userInfoItemTitle.setData(giftTitleInfo); + + UserInfoItem userInfoItemList = userInfoItems.get(4); + userInfoItemList.setItemType(UserInfoItem.TYPE_RADISH_ITEMS); + userInfoItemList.setData((ArrayList) radishWallInfoList); + + UserInfoItem div = userInfoItems.get(5); + div.setItemType(UserInfoItem.TYPE_DIV); + + userGiftAdapter.notifyDataSetChanged(); + } + + private void getMagicWallSuccessView(List magicInfoList) { + if (ListUtils.isListEmpty(magicInfoList)) + return; + + int allMagicCounts = 0; + for (MagicInfo magicInfo : magicInfoList) { + allMagicCounts += magicInfo.getAmount(); + } + + GiftTitleInfo giftTitleInfo = new GiftTitleInfo(); + giftTitleInfo.setTitle("被施展的魔法"); + giftTitleInfo.setNum(String.valueOf(allMagicCounts)); + UserInfoItem userInfoItemTitle = userInfoItems.get(0); + userInfoItemTitle.setItemType(UserInfoItem.TYPE_TITLE); + userInfoItemTitle.setData(giftTitleInfo); + + UserInfoItem userInfoItemList = userInfoItems.get(1); + userInfoItemList.setItemType(UserInfoItem.TYPE_MAGIC_ITEMS); + userInfoItemList.setData((ArrayList) magicInfoList); + + UserInfoItem div = userInfoItems.get(2); + div.setItemType(UserInfoItem.TYPE_DIV); + + userGiftAdapter.notifyDataSetChanged(); + } + + private void onRequestGiftWall(List giftWallInfoList) { + if (userInfo == null) return; + + // 刷新数据 + while (userInfoItems.size() > 7) { + userInfoItems.remove(7); + } + + if (ListUtils.isListEmpty(giftWallInfoList)) { + GiftTitleInfo giftTitleInfo = new GiftTitleInfo(); + giftTitleInfo.setTitle("收到的礼物"); + giftTitleInfo.setNum(String.valueOf(0)); + UserInfoItem userInfoItemTitle = userInfoItems.get(6); + userInfoItemTitle.setItemType(UserInfoItem.TYPE_TITLE); + userInfoItemTitle.setData(giftTitleInfo); + + UserInfoItem userInfoItem = new UserInfoItem(UserInfoItem.TYPE_GIFT_EMPTY); + userInfoItems.add(userInfoItem); + + } else { + int totalCount = 0; + for (GiftWallInfo giftWallInfo : giftWallInfoList) { + totalCount += giftWallInfo.getReciveCount(); + } + + GiftTitleInfo giftTitleInfo = new GiftTitleInfo(); + giftTitleInfo.setTitle("收到的礼物"); + giftTitleInfo.setNum(String.valueOf(totalCount)); + UserInfoItem userInfoItemTitle = userInfoItems.get(6); + userInfoItemTitle.setItemType(UserInfoItem.TYPE_TITLE); + userInfoItemTitle.setData(giftTitleInfo); + + for (GiftWallInfo giftWallInfo : giftWallInfoList) { + UserInfoItem userInfoItem = new UserInfoItem<>(UserInfoItem.TYPE_GIFT_ITEM, giftWallInfo); + userInfoItems.add(userInfoItem); + } + + } + + userGiftAdapter.notifyDataSetChanged(); + + } + + private void onRequestGiftWallFail(String msg) { + toast(msg); + } + + public void onGetUserInfo(UserInfo userInfo) { + if (isDestroyView) { + return; + } + this.userInfo = userInfo; + + if (!mIsViewCreated) + return; + + initData(userInfo); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + userInfo = UserModel.get().getCacheLoginUserInfo(); + initData(userInfo); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View tmp = super.onCreateView(inflater, container, savedInstanceState); + EventBus.getDefault().register(this); + return tmp; + } + + @Override + public void onDestroyView() { + EventBus.getDefault().unregister(this); + if (mObserver != null) { + UserInfoUiMgr.get().unregister(mObserver); + } + + if (mUidObserver != null) { + UserInfoUiMgr.get().unregisterUid(mUidObserver); + } + super.onDestroyView(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftGroupFrg.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftGroupFrg.java new file mode 100644 index 000000000..bd4d4dcb4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoGiftGroupFrg.java @@ -0,0 +1,150 @@ +package com.yizhuan.erban.ui.user; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import butterknife.Unbinder; + +public class UserInfoGiftGroupFrg extends BaseFragment implements UserGiftAchievementFrg.UserGiftNoDataListener { + + @BindView(R.id.iv_label) + ImageView ivLabel; + @BindView(R.id.tv_label_change) + TextView tvLabelChange; + @BindView(R.id.fl_gift_container) + FrameLayout flGiftContainer; + + private UserInfoGiftFragment userInfoGiftFragment; + private UserGiftAchievementFrg userGiftAchievementFrg; + + public static final byte TAG_ACHIEVEMENT = (byte) 1; + public static final byte TAG_GIFT = (byte) 2; + private byte tag = TAG_ACHIEVEMENT; + + private Unbinder unbinder; + + public static UserInfoGiftGroupFrg newInstance() { + return new UserInfoGiftGroupFrg(); + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + + if (isVisibleToUser) { + setFragment(); + } + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + unbinder = ButterKnife.bind(this, mView); + return mView; + } + + @Override + public void initiate() { + userGiftAchievementFrg = UserGiftAchievementFrg.newInstance(); + userGiftAchievementFrg.setmUserGiftNoDataListener(this); + userInfoGiftFragment = UserInfoGiftFragment.newInstance(); + + tag = TAG_ACHIEVEMENT; + } + + private long lastClick = 0L; + + @OnClick({R.id.tv_label_change}) + public void onClick(View view) { + long currentClick = System.currentTimeMillis(); + + if (currentClick - lastClick > 500) { + lastClick = currentClick; + + switch (view.getId()) { + case R.id.tv_label_change: + String temp = tvLabelChange.getText().toString(); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOMEPAGE_GIFT_CHANGE_TAB, "礼物页切换按钮-" + temp); + + if (tag == TAG_ACHIEVEMENT) { + tag = TAG_GIFT; + } else { + tag = TAG_ACHIEVEMENT; + } + setFragment(); + hasData(tag); + + break; + } + + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + if (unbinder != null) { + unbinder.unbind(); + } + } + + private void setFragment() { + FragmentManager manager = getChildFragmentManager(); + if (tag == TAG_GIFT) { + manager.beginTransaction().replace(R.id.fl_gift_container, userInfoGiftFragment, "userInfoGiftFragment") + .commit(); + } else if (tag == TAG_ACHIEVEMENT) { + manager.beginTransaction().replace(R.id.fl_gift_container, userGiftAchievementFrg, "userGiftAchievementFrg") + .commit(); + } + + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_gift_group; + } + + // 礼物成就没数据 + @Override + public void noData(byte o) { + tvLabelChange.setVisibility(View.GONE); // 是否显示只根据礼物成就判断 + setLabel(TAG_GIFT); + tag = o; + setFragment(); + } + + // 礼物成就有数据 + @Override + public void hasData(byte type) { + tvLabelChange.setVisibility(View.VISIBLE); + setLabel(type); + } + + private void setLabel(byte type) { + if (type == TAG_GIFT) { + ivLabel.setImageResource(R.drawable.ic_gift_received); + tvLabelChange.setText("礼物成就"); + } else if (type == TAG_ACHIEVEMENT) { + ivLabel.setImageResource(R.drawable.ic_gift_achievement); + tvLabelChange.setText("收到的礼物"); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoModifyActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoModifyActivity.java new file mode 100644 index 000000000..660243518 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserInfoModifyActivity.java @@ -0,0 +1,410 @@ +package com.yizhuan.erban.ui.user; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.fourmob.datetimepicker.date.DatePickerDialog; +import com.jph.takephoto.model.TResult; +import com.netease.nim.uikit.common.util.sys.TimeUtil; +import com.sleepbot.datetimepicker.time.RadialPickerLayout; +import com.sleepbot.datetimepicker.time.TimePickerDialog; +import com.yizhuan.erban.ErbanTakePhotoActivity; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.RecordingVoiceActivity; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.ui.login.ModifyInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; +import com.yizhuan.xchat_android_library.utils.TimeUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * @author zhouxiangfeng + */ +public class UserInfoModifyActivity extends BaseActivity + implements View.OnClickListener, TimePickerDialog.OnTimeSetListener, + DatePickerDialog.OnDateSetListener, UserPhotoAdapter.ImageClickListener, + ErbanTakePhotoActivity.TakePhotoCallBack { + + private static final String TAG = "UserInfoModifyActivity"; + + private static final String CAMERA_PREFIX = "picture_"; + private ImageView civAvatar; + private DatePickerDialog datePickerDialog; + private TextView tvBirth; + private TextView tvNick; + private TextView tvDesc; + private UserInfo mUserInfo; + private long userId; + // private TextView tvVoice; + private TextView tvNoVoice; + private String audioFileUrl; + private RecyclerView photosRecyclerView; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_user_info_modify); + initTitleBar(getString(R.string.label_title_modify_info)); + findViews(); + init(); + onSetListener(); + + userId = getIntent().getLongExtra("userId", 0); + UserModel.get().getUserInfo(userId).subscribe(userInfoUpdateObserver); + + } + + + @Override + public void click(int position, UserPhoto userPhoto, boolean isOwner) { + if (userPhoto != null) { +// UIHelper.showModifyPhotosAct(UserInfoModifyActivity.this, userId); + UserModifyPhotosActivity.startForResult(UserInfoModifyActivity.this, userId, Method.PHOTO); + } + } + + private void onSetListener() { + + } + + private void setTextViewLeftDrawable(TextView tvVoice, int drawId) { + Drawable drawablePlay = getResources().getDrawable(drawId); + drawablePlay.setBounds(0, 0, drawablePlay.getMinimumWidth(), drawablePlay.getMinimumHeight()); + tvVoice.setCompoundDrawables(drawablePlay, null, null, null); + } + + private void initData(UserInfo userInfo) { + if (null != userInfo) { + audioFileUrl = userInfo.getUserVoice(); + ImageLoadUtils.loadAvatar(this, userInfo.getAvatar(), civAvatar); + String birth = TimeUtil.getDateTimeString(userInfo.getBirth(), "yyyy-MM-dd"); + tvBirth.setText(birth); + tvNick.setText(RegexUtil.getPrintableString(userInfo.getNick())); + setTvDesc(userInfo.getUserDesc()); + + boolean hasVoice = userInfo.getVoiceDura() > 0; + tvNoVoice.setVisibility(hasVoice ? View.GONE : View.VISIBLE); +// tvVoice.setVisibility(hasVoice ? View.VISIBLE : View.GONE); +// tvVoice.setText(hasVoice ? getString(R.string.user_info_voice_dur, userInfo.getVoiceDura()) : ""); + + UserPhotoAdapter adapter = new UserPhotoAdapter(userInfo.getPrivatePhoto(), 1, userInfo.getUid()); + adapter.setSmall(true); + adapter.setImageClickListener(this); + photosRecyclerView.setAdapter(adapter); + if (userInfo.getPrivatePhoto() != null && userInfo.getPrivatePhoto().size() > 0) { + photosRecyclerView.setVisibility(View.VISIBLE); + } else { + photosRecyclerView.setVisibility(View.GONE); + } + } + } + + private void findViews() { + civAvatar = findViewById(R.id.civ_avatar); + tvBirth = findViewById(R.id.tv_birth); + tvNick = findViewById(R.id.tv_nick); + tvDesc = findViewById(R.id.tv_desc); +// tvVoice = findViewById(R.id.tv_voice); + tvNoVoice = findViewById(R.id.tv_no_voice); + photosRecyclerView = findViewById(R.id.rv_photos); + findViewById(R.id.layout_avatar).setOnClickListener(this); + tvBirth.setOnClickListener(this); + findViewById(R.id.tv_nick).setOnClickListener(this); + findViewById(R.id.layout_desc).setOnClickListener(this); + findViewById(R.id.iv_desc_more).setOnClickListener(this); + findViewById(R.id.layout_photos).setOnClickListener(this); + findViewById(R.id.rl_audio_record).setOnClickListener(this); + LinearLayoutManager mLayoutManager = + new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true); + photosRecyclerView.setLayoutManager(mLayoutManager); + + } + + private void setTvDesc(String desc) { + tvDesc.setText(TextUtils.isEmpty(desc) ? getString(R.string.label_hint_desc_setting) : desc); + } + + private void init() { + Calendar calendar = Calendar.getInstance(); + datePickerDialog = DatePickerDialog.newInstance(this, calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), true); + } + + @Override + public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) { + String monthStr; + if ((month + 1) < 10) { + monthStr = "0" + (month + 1); + } else { + monthStr = String.valueOf(month + 1); + } + String dayStr; + if ((day) < 10) { + dayStr = "0" + (day); + } else { + dayStr = String.valueOf(day); + } + String birth = String.valueOf(year) + "-" + monthStr + "-" + dayStr; + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setBirthStr(birth); + UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver); + } + + + @Override + public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) { + + } + + + public interface Method { + /** + * 录音 + */ + int AUDIO = 2; + /** + * 昵称 + */ + int NICK = 3; + /** + * 个人介绍 + */ + int DESC = 4; + + int PHOTO = 5; + } + + + PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() { + @Override + public void superPermission() { + takePhoto(); + } + }; + + private void takePhoto() { + ErbanTakePhotoActivity.startToTakePhoto(this, this); + } + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(checkPermissionListener, R.string.ask_camera, Manifest.permission.CAMERA); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (resultCode != Activity.RESULT_OK) { + MLog.info(this, "return is not ok,resultCode=%d", resultCode); + return; + } + + if (requestCode == Method.NICK) { + getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后"); + String stringExtra = data.getStringExtra(ModifyInfoActivity.CONTENT_NICK); + tvNick.setText(stringExtra); + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setNick(stringExtra); + UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver); + + } + + if (requestCode == Method.DESC) { + getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后"); + String stringExtra = data.getStringExtra(ModifyInfoActivity.CONTENT); + setTvDesc(stringExtra); + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setUserDesc(stringExtra); + UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver); + } + + // 刷新声音资源 + if (requestCode == Method.AUDIO) { + // 传给上个页面 + setResult(RESULT_OK, data); + + // 获取数据并刷新显示 + audioFileUrl = data.getStringExtra(RecordingVoiceActivity.AUDIO_FILE); + int audioDura = data.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0); +// tvVoice.setText(getString(R.string.user_info_voice_dur, audioDura)); + + // 更新用户信息 + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setUserVoice(audioFileUrl); + user.setVoiceDura(audioDura); + UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver); + } + + if (requestCode == Method.PHOTO && data != null) { + boolean isChanged = data.getBooleanExtra(UserModifyPhotosActivity.FLAG_CHANGE, false); + if (isChanged) + UserModel.get().getUserInfo(userId).subscribe(userInfoUpdateObserver); + + } + + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.layout_avatar: + ButtonItem buttonItem = new ButtonItem("拍照上传", this::checkPermissionAndStartCamera); + ButtonItem buttonItem1 = new ButtonItem("本地相册", () -> { + ErbanTakePhotoActivity.startToSelectPhoto(this, this); + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, "取消", false); + + isAvatar = true; + break; + case R.id.tv_birth: + if (mUserInfo != null) { + int year = TimeUtils.getYear(mUserInfo.getBirth()); + int month = TimeUtils.getMonth(mUserInfo.getBirth()); + int day = TimeUtils.getDayOfMonth(mUserInfo.getBirth()); + datePickerDialog = DatePickerDialog.newInstance(this, year, (month - 1), day, true); + } + Calendar calendar = Calendar.getInstance(); + + datePickerDialog.setVibrate(true); + datePickerDialog.setYearRange(1945, calendar.get(Calendar.YEAR) - 18); + datePickerDialog.show(getSupportFragmentManager(), "DATEPICKER_TAG_1"); + break; + case R.id.tv_nick: + UIHelper.showModifyInfoAct(UserInfoModifyActivity.this, Method.NICK, ModifyInfoActivity.NICK_MODIFY); + break; + + case R.id.iv_desc_more: + case R.id.layout_desc: + UIHelper.showModifyInfoAct(UserInfoModifyActivity.this, Method.DESC, ModifyInfoActivity.CONTENT_MODIFY); + break; + + case R.id.rl_audio_record: + checkPermission(() -> { + // 点击跳转到我的声音页面 + UIHelper.showMyVoiceAct(UserInfoModifyActivity.this, Method.AUDIO,"编辑资料"); + isAvatar = false; + }, R.string.ask_again, + Manifest.permission.RECORD_AUDIO); + + break; + case R.id.layout_photos: +// UIHelper.showModifyPhotosAct(UserInfoModifyActivity.this, userId); + UserModifyPhotosActivity.startForResult(UserInfoModifyActivity.this, userId, Method.PHOTO); + break; + default: + } + } + + private boolean isAvatar = false; + + public void onUpload(String url) { + if (isAvatar) { + UserInfo user = new UserInfo(); + user.setUid(AuthModel.get().getCurrentUid()); + user.setAvatar(url); + UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver); + } + } + + public void onUploadFail() { + toast("上传失败"); + getDialogManager().dismissDialog(); + } + + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后"); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadFail(); + } else { + onUpload(url); + } + }); + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + + @Override + public void takeCancel() { + + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + + /** + * 观察用户信息 + */ + private SingleObserver userInfoUpdateObserver = new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(UserInfo info) { + if (info.getUid() == userId) { + mUserInfo = info; + initData(mUserInfo); + } + getDialogManager().dismissDialog(); + } + + @Override + public void onError(Throwable e) { + getDialogManager().dismissDialog(); + toast(e.getMessage()); + } + }; +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosActivity.java new file mode 100644 index 000000000..ec7e93d91 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosActivity.java @@ -0,0 +1,268 @@ +package com.yizhuan.erban.ui.user; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.widget.GridView; + +import com.jph.takephoto.app.TakePhotoActivity; +import com.jph.takephoto.compress.CompressConfig; +import com.jph.takephoto.model.TResult; +import com.orhanobut.logger.Logger; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.permission.PermissionActivity; +import com.yizhuan.erban.ui.widget.ButtonItem; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.file.JXFileUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by chenran on 2017/7/24. + */ + +public class UserModifyPhotosActivity extends TakePhotoActivity implements UserModifyPhotosAdapter.PhotoItemClickListener { + + public static final String FLAG_CHANGE = "isChanged"; + + private long userId; + private UserInfo userInfo; + private GridView photoGridView; + private boolean isEditMode; + private UserModifyPhotosAdapter adapter; + private UserModifyPhotosActivity mActivity; + + // 判断相册是否做过增减操作 + private boolean isChanged = false; + + public static void startForResult(Activity activity, long userId, int requestCode) { + Intent intent = new Intent(activity, UserModifyPhotosActivity.class); + intent.putExtra("userId", userId); + activity.startActivityForResult(intent, requestCode); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_user_photos_modify); + initView(); + mActivity = this; + userId = getIntent().getLongExtra("userId", 0); + userInfo = UserModel.get().getCacheLoginUserInfo(); + adapter = new UserModifyPhotosAdapter(this, new ArrayList(), this); + photoGridView.setAdapter(adapter); + if (userInfo != null) { + updateView(); + } + } + + private void initView() { + initTitleBar("我的相册"); + TitleBar titleBar = findViewById(R.id.title_bar); + titleBar.addAction(new TitleBar.TextAction("编辑") { + @Override + public void performAction(View view) { + notifyEditMode(); + } + }); + + photoGridView = findViewById(R.id.gridView); +// dialog = new BottomSelectDialog(this); +//// dialog.create(); +// dialog.setHideTitle(true); +// dialog.setTvOne("拍照上传"); +// dialog.setTvTwo("本地相册"); +// dialog.setButtonText("取消"); + } + + @Override + protected void onLeftClickListener() { + onBackPressed(); + } + + private void updateView() { + adapter.setData(userInfo.getPrivatePhoto()); + adapter.notifyDataSetChanged(); + } + + private void notifyEditMode() { + adapter.setEditMode(!isEditMode); + isEditMode = !isEditMode; + adapter.notifyDataSetChanged(); + } + + private void takePhoto() { + File cameraOutFile = JXFileUtils.getTempFile(this, "picture_" + System.currentTimeMillis() + ".jpg"); + if (!cameraOutFile.getParentFile().exists()) { + cameraOutFile.getParentFile().mkdirs(); + } + Uri uri = Uri.fromFile(cameraOutFile); + CompressConfig compressConfig = new CompressConfig.Builder().create(); + compressConfig.setMaxSize(500 * 1024); + getTakePhoto().onEnableCompress(compressConfig, false); + getTakePhoto().onPickFromCapture(uri); + } + + PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() { + @Override + public void superPermission() { + takePhoto(); + } + }; + + private void checkPermissionAndStartCamera() { + //低版本授权检查 + checkPermission(checkPermissionListener, R.string.ask_camera, android.Manifest.permission.CAMERA); + } + + @Override + public void onPhotoDeleteClick(int position) { + getDialogManager().showProgressDialog(this, "请稍后"); + if (position != 0) { + UserPhoto userPhoto = userInfo.getPrivatePhoto().get(position - 1); + UserModel.get().requestDeletePhoto(userPhoto.getPid()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast("操作失败,请检查网络"); + getDialogManager().dismissDialog(); + } + + @Override + public void onSuccess(UserInfo info) { + isChanged = true; + getDialogManager().dismissDialog(); + if (info.getUid() == userId) { + userInfo = info; + updateView(); + + } + } + }); + } + } + + @Override + public void onPhotoItemClick(int position) { + if (userInfo == null) { + return; + } + if (position == 0) { + if (userInfo.getPrivatePhoto() != null && userInfo.getPrivatePhoto().size() == 8) { + toast("照片已达到最大上传数"); + return; + } + ButtonItem upItem = new ButtonItem("拍照上传", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + checkPermissionAndStartCamera(); + } + }); + ButtonItem loaclItem = new ButtonItem("本地相册", new ButtonItem.OnClickListener() { + @Override + public void onClick() { + CompressConfig compressConfig = new CompressConfig.Builder().create(); + compressConfig.setMaxSize(500 * 1024); + getTakePhoto().onEnableCompress(compressConfig, true); + getTakePhoto().onPickFromGallery(); + } + }); + List buttonItemList = new ArrayList<>(); + buttonItemList.add(upItem); + buttonItemList.add(loaclItem); + getDialogManager().showCommonPopupDialog(buttonItemList, "取消", false); + } else { + ArrayList userPhotos1 = new ArrayList<>(); + userPhotos1.addAll(userInfo.getPrivatePhoto()); + Intent intent = new Intent(mActivity, ShowPhotoActivity.class); + int position1 = position - 1; + intent.putExtra("position", position1); + intent.putExtra("photoList", userPhotos1); + startActivity(intent); +// PhotoPreviewIntent intent = new PhotoPreviewIntent(this); +// intent.setCurrentItem(position-1); // 当前选中照片的下标 +// ArrayList paths = new ArrayList<>(); +// paths.add(userInfo.getAvatar()); +// paths.add(userInfo.getAvatar()); +// paths.add(userInfo.getAvatar()); +// paths.add(userInfo.getAvatar()); +// paths.add(userInfo.getAvatar()); +// paths.add(userInfo.getAvatar()); +// intent.setPhotoPaths(paths); +// startActivityForResult(intent, 201); + + + } + } + + public void onUploadPhoto(String url) { + Logger.d("onUploadPhoto:" + url); + UserModel.get().requestAddPhoto(url) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast("操作失败,请检查网络"); + getDialogManager().dismissDialog(); + } + + @Override + public void onSuccess(UserInfo info) { + isChanged = true; + getDialogManager().dismissDialog(); + if (info.getUid() == userId) { + userInfo = info; + updateView(); + + } + } + }); + } + + public void onUploadPhotoFail() { + toast("操作失败,请检查网络"); + getDialogManager().dismissDialog(); + } + + @SuppressLint("CheckResult") + @Override + public void takeSuccess(TResult result) { + getDialogManager().showProgressDialog(this, "请稍后"); + FileModel.get() + .uploadFile(result.getImage().getCompressPath()) + .compose(bindToLifecycle()) + .subscribe((url, throwable) -> { + if (throwable != null) { + onUploadPhotoFail(); + } else { + onUploadPhoto(url); + } + }); + } + + @Override + public void onBackPressed() { + Intent intent = new Intent(); + intent.putExtra(FLAG_CHANGE, isChanged); + setResult(RESULT_OK, intent); + + super.onBackPressed(); + } + + @Override + public void takeFail(TResult result, String msg) { + toast(msg); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosAdapter.java new file mode 100644 index 000000000..a68675c88 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserModifyPhotosAdapter.java @@ -0,0 +1,119 @@ +package com.yizhuan.erban.ui.user; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; + +import com.makeramen.roundedimageview.RoundedImageView; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; + +import java.util.List; + +/** + * Created by chenran on 2017/7/24. + */ + +public class UserModifyPhotosAdapter extends BaseAdapter{ + private Context mContext; + private List photoUrls; + private PhotoItemClickListener listener; + private boolean isEditMode; + + public void setEditMode(boolean editMode) { + isEditMode = editMode; + } + + public UserModifyPhotosAdapter(Context context, List photoUrls, PhotoItemClickListener listener) + { + this.mContext=context; + this.photoUrls = photoUrls; + this.listener = listener; + } + @Override + public int getCount() { + if (photoUrls == null) { + return 1; + } else { + return photoUrls.size() + 1; + } + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + UserModifyPhotosViewHolder holder; + if (null == convertView) { + holder = new UserModifyPhotosViewHolder(); + convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_user_photos_modify, null); + holder.imageView = convertView.findViewById(R.id.iv_user_photo); + holder.imageDelete = convertView.findViewById(R.id.iv_photo_delete); + convertView.setTag(holder); + } else { + holder = (UserModifyPhotosViewHolder) convertView.getTag(); + } + + holder.imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onPhotoItemClick(position); + } + } + }); + holder.imageDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener !=null) { + listener.onPhotoDeleteClick(position); + } + } + }); + + if (position == 0) { + holder.imageView.setImageResource(R.drawable.icon_add_photo); + holder.imageDelete.setVisibility(View.GONE); + } else { + UserPhoto userPhoto = photoUrls.get(position-1); + GlideApp.with(mContext) + .load(userPhoto.getPhotoUrl()) + .placeholder(R.drawable.default_avatar) + .dontAnimate() + .into(holder.imageView); + if (isEditMode) { + holder.imageDelete.setVisibility(View.VISIBLE); + } else { + holder.imageDelete.setVisibility(View.GONE); + } + } + + return convertView; + } + + public void setData(List privatePhoto) { + this.photoUrls = privatePhoto; + } + + class UserModifyPhotosViewHolder { + private RoundedImageView imageView; + private ImageView imageDelete; + } + + public interface PhotoItemClickListener { + void onPhotoItemClick(int position); + void onPhotoDeleteClick(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/UserPhotoAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/UserPhotoAdapter.java new file mode 100644 index 000000000..08384110f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/UserPhotoAdapter.java @@ -0,0 +1,131 @@ +package com.yizhuan.erban.ui.user; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.RectRoundImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; + +import java.util.List; + +/** + * @author chenran + * @date 2017/7/24 + */ +public class UserPhotoAdapter extends RecyclerView.Adapter { + + private static final int TYPE_ADD = 100; + private static final int TYPE_NORMAL = 101; + + private List photoUrls; + private int type; + private boolean mIsOwner; + + private boolean isSmall = false; + + public UserPhotoAdapter(List photoUrls, int type, long uid) { + this.photoUrls = photoUrls; + this.type = type; + mIsOwner = AuthModel.get().getCurrentUid() == uid && uid != 0; + + } + + public void setSmall(boolean small) { + isSmall = small; + } + + public interface ImageClickListener { + void click(int position, UserPhoto userPhoto, boolean isOwner); + } + + private ImageClickListener mImageClickListener; + + public void setImageClickListener(UserPhotoAdapter.ImageClickListener imageClickListener) { + mImageClickListener = imageClickListener; + } + + @Override + public UserPhtotViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item; + //表示在个人中心 + if (isInUserInfoView()) { + if (viewType == TYPE_NORMAL) { + + if (isSmall) + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_user_photo_small, parent, false); + else + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_user_photo, parent, false); + } else { + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_user_photo_edit, parent, false); + } + } else { + if (isSmall) + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_user_photo_small, parent, false); + else + item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_user_photo, parent, false); + } + return new UserPhtotViewHolder(item); + } + + @Override + public void onBindViewHolder(UserPhtotViewHolder holder, final int position) { + UserPhoto photo = null; + if (isInUserInfoView()) { + if (position > 0) { + photo = photoUrls.get(position - 1); + ImageLoadUtils.loadPhotoThumbnail(holder.itemView.getContext(), photo.getPhotoUrl(), holder.mPhotoImage); + } + } else { + photo = photoUrls.get(position); + ImageLoadUtils.loadPhotoThumbnail(holder.itemView.getContext(), photo.getPhotoUrl(), holder.mPhotoImage); + } + UserPhoto finalPhoto = photo; + holder.itemView.setOnClickListener(v -> { + if (mImageClickListener != null) { + mImageClickListener.click(position, finalPhoto, mIsOwner); + } + }); + + } + + @Override + public int getItemCount() { + if (photoUrls == null) { + return 0; + } else { + return photoUrls.size() + (isInUserInfoView() ? 1 : 0); + } + } + + private boolean isInUserInfoView() { + return type == 0 && mIsOwner; + } + + @Override + public int getItemViewType(int position) { + if (isInUserInfoView()) return (position == 0) ? TYPE_ADD : TYPE_NORMAL; + else return TYPE_NORMAL; + } + + static class UserPhtotViewHolder extends RecyclerView.ViewHolder { + + private RectRoundImageView mPhotoImage; + + UserPhtotViewHolder(View itemView) { + super(itemView); + + mPhotoImage = itemView.findViewById(R.id.iv_user_photo); + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/GiftAchievementAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/GiftAchievementAdapter.java new file mode 100644 index 000000000..f4ca595b8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/GiftAchievementAdapter.java @@ -0,0 +1,95 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.support.v4.content.ContextCompat; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.RectRoundImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementInfoSub; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementItem; + +import java.util.List; + +public class GiftAchievementAdapter extends BaseMultiItemQuickAdapter { + /** + * Same as QuickAdapter#QuickAdapter(Context,int) but with + * some initialization data. + * + * @param data A new list is created out of this one to avoid mutable list + */ + public GiftAchievementAdapter(List data) { + super(data); + + addItemType(GiftAchievementItem.TYPE_TITILE, R.layout.layout_gift_achievement_title); + addItemType(GiftAchievementItem.TYPE_ITEM, R.layout.item_gift_achievement); + addItemType(GiftAchievementItem.TYPE_BLOCK_DIVIDER, R.layout.layout_divider_achievement); + } + + @Override + protected void convert(BaseViewHolder helper, GiftAchievementItem item) { + if (item == null) { + return; + } + + switch (item.getItemType()) { + case GiftAchievementItem.TYPE_TITILE: + setTitle(helper, item); + break; + + case GiftAchievementItem.TYPE_ITEM: + setItem(helper, item); + break; + } + + } + + private void setTitle(BaseViewHolder helper, GiftAchievementItem item) { + String title = (String) item.getData(); + helper.setText(R.id.tv_gift_achievement_title, title); + } + + private void setItem(BaseViewHolder helper, GiftAchievementItem item) { + if (item == null) { + return; + } + + GiftAchievementInfoSub infoSub = (GiftAchievementInfoSub) item.getData(); + if (infoSub == null) { + return; + } + + // 礼物 + RectRoundImageView rrivGift = helper.getView(R.id.rriv_gift); + ImageLoadUtilsV2.loadImage(rrivGift, infoSub.getPicUrl()); + + // 背景 + ImageView bg = helper.getView(R.id.iv_bg_achievement); + // 蒙层 + ImageView mask = helper.getView(R.id.iv_mask); + if (infoSub.isStatus() && !TextUtils.isEmpty(item.getmMaskUrl())) { + ImageLoadUtilsV2.loadImage(mask, item.getmMaskUrl()); + + // 未点亮状态 + mask.setVisibility(View.VISIBLE); + ImageLoadUtilsV2.loadImage(bg, item.getmGrayBgUrl()); + helper.setTextColor(R.id.tv_gift_name, ContextCompat.getColor(mContext, R.color.color_common_text_light_gray)); + + } else { + // 点亮状态 + mask.setVisibility(View.GONE); + ImageLoadUtilsV2.loadImage(bg, item.getmBgUrl()); + helper.setTextColor(R.id.tv_gift_name, ContextCompat.getColor(mContext, R.color.color_common_text_gray)); + } + + helper.setText(R.id.tv_gift_name, infoSub.getGiftName()); + helper.setText(R.id.tv_gift_num, infoSub.getGiftSum() + ""); + helper.setGone(R.id.iv_achievement_tips, !TextUtils.isEmpty(infoSub.getTip())); + helper.addOnClickListener(R.id.cl_container_gift_achievement); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyCarAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyCarAdapter.java new file mode 100644 index 000000000..d5305ef78 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyCarAdapter.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; + +import static com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo.STATUS_OFF_SHELF; +import static com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo.STATUS_OUT_OF_DATE; + +/** + *

+ * + * @author jiahui + * date 2018/3/5 + */ +public class MyCarAdapter extends BaseQuickAdapter { + + public MyCarAdapter() { + super(R.layout.user_info_my_car_item); + } + + @Override + protected void convert(BaseViewHolder helper, CarInfo item) { + int resId = -1; + if (item.getStatus() == STATUS_OUT_OF_DATE) { + resId = R.drawable.ic_car_expire; + } else if (item.getStatus() == STATUS_OFF_SHELF) { + resId = R.drawable.ic_car_down; + } + + helper.setVisible(R.id.user_info_car_flag, + item.getStatus() == STATUS_OUT_OF_DATE || item.getStatus() == STATUS_OFF_SHELF) +// .setVisible(R.id.car_user_gray_view, item.getStatus() == STATUS_OFF_SHELF) + .addOnClickListener(R.id.user_info_car_pic) + ; + if (resId != -1) { + helper.setImageResource(R.id.user_info_car_flag, resId); + } + ImageView carPic = helper.getView(R.id.user_info_car_pic); + ImageLoadUtils.loadImage(mContext, item.getPic(), carPic); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyMagicWallAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyMagicWallAdapter.java new file mode 100644 index 000000000..66429a922 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/MyMagicWallAdapter.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.graphics.Color; +import android.widget.ImageView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; + +/** + *

+ * + * @author jiahui + * date 2018/3/5 + */ +public class MyMagicWallAdapter extends BaseQuickAdapter { + private boolean isNoble; + + public MyMagicWallAdapter() { + super(R.layout.user_info_my_magic_item); + } + + public boolean isNoble() { + return isNoble; + } + + public void setNoble(boolean noble) { + isNoble = noble; + } + + @Override + protected void convert(BaseViewHolder helper, MagicInfo item) { + // 魔法图片 + ImageView ivMagicItem = helper.getView(R.id.iv_user_info_magic_pic); + ImageLoadUtils.loadImage(mContext, item.getIcon(), ivMagicItem); + // 魔法名字 + TextView tvMagicName = helper.getView(R.id.tv_magic_item_name); + tvMagicName.setText(item.getName()); + tvMagicName.setTextColor(isNoble ? Color.parseColor("#999999") : Color.BLACK); + // 魔法数量 + TextView tvMagicNumber = helper.getView(R.id.tv_magic_item_number); + tvMagicNumber.setText(String.valueOf(item.getAmount())); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/RadishWallAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/RadishWallAdapter.java new file mode 100644 index 000000000..a55c5ec8c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/RadishWallAdapter.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.user.bean.RadishWallInfo; + +public class RadishWallAdapter extends BaseQuickAdapter { + + public RadishWallAdapter() { + super(R.layout.user_info_my_magic_item); + } + + @Override + protected void convert(BaseViewHolder helper, RadishWallInfo item) { + + if (item == null) + return; + + // 图片 + ImageView ivMagicItem = helper.getView(R.id.iv_user_info_magic_pic); + ImageLoadUtils.loadImage(mContext, item.getPicUrl(), ivMagicItem); + // 名字 + helper.setText(R.id.tv_magic_item_name, item.getGiftName()); + // 数量 + helper.setText(R.id.tv_magic_item_number, "" + item.getReceiveCount()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserDesAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserDesAdapter.java new file mode 100644 index 000000000..5ffdc8c74 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserDesAdapter.java @@ -0,0 +1,421 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.audio.widget.VoiceLine; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.miniworld.activity.MiniWorldGuestPageActivity; +import com.yizhuan.erban.ui.user.ShowPhotoActivity; +import com.yizhuan.erban.ui.user.UserPhotoAdapter; +import com.yizhuan.erban.ui.widget.SquareImageView; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.VerticalDecoration; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.module_hall.hall.bean.HTeamInfo; +import com.yizhuan.xchat_android_core.module_hall.hall.bean.OwnerHallInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.bean.JoinWorldInfo; +import com.yizhuan.xchat_android_core.user.bean.LiveTagInfo; +import com.yizhuan.xchat_android_core.user.bean.UserGameInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserPhoto; +import com.yizhuan.xchat_android_core.utils.StringUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class UserDesAdapter extends UserTabBaseAdapter implements UserPhotoAdapter.ImageClickListener { + public void setUserId(long userId) { + this.userId = userId; + } + + private long userId = 0; + private UserInfo userInfo; + private boolean isPlaying = false; + + public UserDesAdapter(Context context, List data) { + super(context, data); + + addItemType(UserInfoItem.TYPE_DES_PHOTO, R.layout.layout_des_photo); + addItemType(UserInfoItem.TYPE_DES_PERSONAL, R.layout.layout_des_personal); + addItemType(UserInfoItem.TYPE_DES_VOICE, R.layout.layout_desc_voice); + addItemType(UserInfoItem.TYPE_DES_FAMILY, R.layout.layout_user_family); + addItemType(UserInfoItem.TYPE_DES_HALL, R.layout.include_user_module_hall); + addItemType(UserInfoItem.TYPE_DES_GAME, R.layout.layout_desc_game); + addItemType(UserInfoItem.TYPE_DES_JOIN_WORLDS, R.layout.layout_user_join_worlds); + addItemType(UserInfoItem.TYPE_DES_TAG, R.layout.layout_desc_tag); + } + + public void setPlaying(boolean playing) { + isPlaying = playing; + } + + @Override + protected void convert(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + super.convert(helper, item); + + switch (item.getItemType()) { + case UserInfoItem.TYPE_DES_PHOTO: + setPhoto(helper); + break; + + case UserInfoItem.TYPE_DES_PERSONAL: + setPersonal(helper); + break; + + case UserInfoItem.TYPE_DES_VOICE: + setVoice(helper); + break; + + case UserInfoItem.TYPE_DES_FAMILY: + setFamily(helper, item); + break; + + case UserInfoItem.TYPE_DES_HALL: + setHall(helper, item); + break; + + case UserInfoItem.TYPE_DES_GAME: + setGame(helper, item); + break; + + case UserInfoItem.TYPE_DES_TAG: + setTag(helper, item); + break; + + case UserInfoItem.TYPE_DES_JOIN_WORLDS: + setJoinWorlds(helper, item); + break; + } + + + } + + private LinearLayoutManager tagManager; + + private void setTag(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + ArrayList liveSkillVoListBeans = (ArrayList) item.getData(); + if (liveSkillVoListBeans == null) + return; + + RecyclerView rvTag = helper.itemView.findViewById(R.id.rv_tag); + if (rvTag == null) + return; + + if (tagManager == null) + tagManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false); + rvTag.setLayoutManager(tagManager); + + BaseAdapter liveTagAdapter = new BaseAdapter(R.layout.item_live_tag, BR.tagInfo); + rvTag.setAdapter(liveTagAdapter); + + helper.setGone(R.id.rv_tag, true); + helper.setGone(R.id.ll_tag, true); + liveTagAdapter.setNewData(liveSkillVoListBeans); + + helper.setGone(R.id.tv_edit, isOwner()); + helper.addOnClickListener(R.id.tv_edit); + + } + + private LinearLayoutManager gameManager; + + private void setGame(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + ArrayList list = (ArrayList) item.getData(); + + if (ListUtils.isListEmpty(list)) { + helper.setGone(R.id.tv_game, false); + helper.setGone(R.id.rv_game, false); + + } else { + helper.setGone(R.id.tv_game, true); + helper.setGone(R.id.rv_game, true); + + RecyclerView rvGame = helper.itemView.findViewById(R.id.rv_game); + + if (gameManager == null) + gameManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false); + rvGame.setLayoutManager(gameManager); + + BaseAdapter adapter = new BaseAdapter(R.layout.item_user_game, BR.gameInfo); + rvGame.setAdapter(adapter); + adapter.setNewData(list); + } + } + + // 没有模厅不需要展示 + private void setHall(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + OwnerHallInfo ownerHallInfo = (OwnerHallInfo) item.getData(); + if (ownerHallInfo == null) { + helper.setGone(R.id.ll_hall_layout, false); + + } else { + + //说明该客态页是厅成员或者没有厅 + if (ownerHallInfo.getHallId() <= 0) { + helper.setGone(R.id.ll_hall_layout, false); + } else { + helper.setGone(R.id.ll_hall_layout, true); + helper.setGone(R.id.stv_apply_hall, false); + + helper.setText(R.id.tv_hall_name, ownerHallInfo.getHallName()); + //如果不是自己,并且不在厅里,才显示申请按钮 + if (!ownerHallInfo.isInHall()) { + helper.setGone(R.id.stv_apply_hall, true); + helper.addOnClickListener(R.id.stv_apply_hall); + } + + if (ownerHallInfo.isHasPublicChat()) { + helper.setGone(R.id.rl_hall_team_layout, true); + helper.addOnClickListener(R.id.rl_hall_team_layout); + + helper.setGone(R.id.stv_apply_team, false); + HTeamInfo publicTeam = ownerHallInfo.getPublicChat(); + if (publicTeam != null) { + helper.setText(R.id.tv_public_team_name, publicTeam.getName()); + if (!publicTeam.isInChat()) { + helper.setGone(R.id.stv_apply_team, true); + helper.addOnClickListener(R.id.stv_apply_team); + } + } + } else { + helper.setGone(R.id.rl_hall_team_layout, false); + } + + } + + } + + } + + // 没有家族不需要展示 + private void setFamily(BaseViewHolder helper, UserInfoItem item) { + + if (item == null) + return; + + FamilyInfo familyInfo = (FamilyInfo) item.getData(); + if (familyInfo == null) { + helper.setGone(R.id.ll_my_family_container, false); + return; + } + helper.setGone(R.id.ll_my_family_container, true); + + SquareImageView ivFamilyCover = helper.itemView.findViewById(R.id.iv_family_cover); + GlideApp.with(mContext) + .load(familyInfo.getFamilyIcon()) + .dontAnimate() + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(10)) + .error(R.drawable.default_cover) + .into(ivFamilyCover); + + helper.setText(R.id.tv_family_name, familyInfo.getFamilyName()); + helper.setText(R.id.tv_family_id, String.format(mContext.getString(R.string.family_id), familyInfo.getFamilyId())); + helper.setText(R.id.tv_family_member_count, String.format(mContext.getString( + R.string.family_member_count), String.valueOf(familyInfo.getMemberCount()))); + + helper.addOnClickListener(R.id.ll_my_family); + } + + public void setmVoiceDuration(int mVoiceDuration) { + this.mVoiceDuration = mVoiceDuration; + } + + private int mVoiceDuration = 0; + + private void setVoice(BaseViewHolder helper) { + if (userInfo == null) + return; + + if (isOwner()) {// 主态 + helper.setGone(R.id.layout_voice, true); + helper.setGone(R.id.layout_voice_bar, !StringUtils.isEmpty(userInfo.getUserVoice())); + helper.setGone(R.id.layout_voice_bar_no_data, StringUtils.isEmpty(userInfo.getUserVoice())); + helper.setText(R.id.tv_voice_title, "我的声音"); + helper.setGone(R.id.iv_voice_more, true); + + } else {// 客态 + helper.setGone(R.id.layout_voice, !StringUtils.isEmpty(userInfo.getUserVoice())); + helper.setGone(R.id.layout_voice_bar, !StringUtils.isEmpty(userInfo.getUserVoice())); + helper.setGone(R.id.layout_voice_bar_no_data, false); + helper.setText(R.id.tv_voice_title, "TA的声音"); + helper.setGone(R.id.iv_voice_more, false); + } + + helper.addOnClickListener(R.id.layout_voice_bar); + helper.addOnClickListener(R.id.iv_voice_more); + helper.addOnClickListener(R.id.layout_voice_bar_no_data); + + VoiceLine voiceLine = helper.itemView.findViewById(R.id.layout_voice_line); + if (voiceLine != null) { + voiceLine.stopAnim(); + if (isPlaying) { + helper.setImageResource(R.id.iv_voice_bar_play, R.drawable.ic_voice_bar_pause); + voiceLine.startAnim(); + } else { + helper.setImageResource(R.id.iv_voice_bar_play, R.drawable.ic_voice_bar_play); + voiceLine.stopAnim(); + } + } + +// int duration = mVoiceDuration; +// if (duration == 0) +// duration = userInfo.getVoiceDura(); + helper.setText(R.id.tv_voice_duration, String.format(Locale.getDefault(), "%ds", userInfo.getVoiceDura())); + } + + private void setPersonal(BaseViewHolder helper) { + if (userInfo == null) + return; + + String desc = userInfo.getUserDesc(); + helper.setText(R.id.tv_desc, TextUtils.isEmpty(desc) ? "这个人比较神秘,什么也没留下" : desc); + } + + private LinearLayoutManager mPhotoLayoutManager; + + private void setPhoto(BaseViewHolder helper) { + + if (userInfo == null) + return; + + if (mPhotoLayoutManager == null) + mPhotoLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false); + + RecyclerView photoRecyclerView = helper.itemView.findViewById(R.id.photo_recyclerView); + photoRecyclerView.setLayoutManager(mPhotoLayoutManager); + + List privatePhoto = userInfo.getPrivatePhoto(); + + if (isOwner()) {// 主态 + helper.setGone(R.id.photo_recyclerView, true); + helper.setGone(R.id.tv_empty_photo, false); + + UserPhotoAdapter photoAdapter = new UserPhotoAdapter(privatePhoto, 0, userInfo.getUid()); + photoRecyclerView.setAdapter(photoAdapter); + photoAdapter.setImageClickListener(this); + + } else { // 客态 + if (ListUtils.isListEmpty(privatePhoto)) { + helper.setGone(R.id.photo_recyclerView, false); + helper.setGone(R.id.tv_empty_photo, true); + + } else { + helper.setGone(R.id.photo_recyclerView, true); + helper.setGone(R.id.tv_empty_photo, false); + UserPhotoAdapter photoAdapter = new UserPhotoAdapter(privatePhoto, 0, userInfo.getUid()); + photoRecyclerView.setAdapter(photoAdapter); + photoAdapter.setImageClickListener(this); + } + } + + } + + public void setUserInfo(UserInfo userInfo) { + this.userInfo = userInfo; + } + + @Override + public void click(int position, UserPhoto userPhoto, boolean isOwner) { + if (isOwner) { + if (position > 0) { + showUserPhoto(position - 1); + } else { + UIHelper.showModifyPhotosAct((Activity) mContext, userId); + } + } else { + //创建一个集合拿来做用户所有照片信息 + showUserPhoto(position); + } + + } + + private void showUserPhoto(int position) { + //创建一个集合拿来做用户所有照片信息 + ArrayList userPhotos = new ArrayList<>(); + List realmList = userInfo.getPrivatePhoto(); + for (UserPhoto photo : realmList) { + UserPhoto newPhoto = new UserPhoto(); + newPhoto.setPid(photo.getPid()); + newPhoto.setPhotoUrl(photo.getPhotoUrl()); + userPhotos.add(newPhoto); + } + Intent intent = new Intent(mContext, ShowPhotoActivity.class); + intent.putExtra("position", position); + intent.putExtra("photoList", userPhotos); + mContext.startActivity(intent); + } + + private boolean isOwner() { + return AuthModel.get().getCurrentUid() == userId && userId != 0; + } + + private byte isInitJoinWorlds = 0; + private void setJoinWorlds(BaseViewHolder baseViewHolder, UserInfoItem item) { + baseViewHolder.setText(R.id.tv_label_user_join_worlds, isOwner() ? "我的世界" : "TA的世界"); + ArrayList list = (ArrayList) item.getData(); + + if (list != null && list.size() > 0) { + RecyclerView recyclerView = baseViewHolder.getView(R.id.rv_user_join_worlds); + recyclerView.getLayoutManager(); + UserJoinWorldAdapter userJoinWorldAdapter = new UserJoinWorldAdapter(); + userJoinWorldAdapter.setNewData(list); + userJoinWorldAdapter.setOnItemChildClickListener(new OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List list1 = adapter.getData(); + if (list1.size() > position) { + JoinWorldInfo joinWorldInfo = list1.get(position); + if (joinWorldInfo != null) { + String from = isOwner() ? "我的世界" : "TA的世界"; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_WORLD_VIEW_WORLD_PAGE, + "进入小世界客态页:" + from); + MiniWorldGuestPageActivity.start(mContext, String.valueOf(joinWorldInfo.getWorldId())); + } + } + } + }); + + recyclerView.setAdapter(userJoinWorldAdapter); + if (isInitJoinWorlds == 0) { + recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); + recyclerView.addItemDecoration(new VerticalDecoration(SizeUtils.dp2px(mContext, 15), true, true)); + + isInitJoinWorlds = 1; + } + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserGiftAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserGiftAdapter.java new file mode 100644 index 000000000..29897cb2a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserGiftAdapter.java @@ -0,0 +1,118 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.user.bean.GiftWallInfo; +import com.yizhuan.xchat_android_core.user.bean.RadishWallInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + +public class UserGiftAdapter extends UserTabBaseAdapter { + + private boolean isNoble; + private int mTextColor; + + public UserGiftAdapter(Context context, List data) { + super(context, data); + + addItemType(UserInfoItem.TYPE_MAGIC_ITEMS, R.layout.layout_gift_gallery); + addItemType(UserInfoItem.TYPE_RADISH_ITEMS, R.layout.layout_gift_gallery); + addItemType(UserInfoItem.TYPE_GIFT_ITEM, R.layout.list_item_gift_wall_info); + addItemType(UserInfoItem.TYPE_GIFT_EMPTY, R.layout.layout_gift_empty); + + mTextColor = ContextCompat.getColor(mContext, R.color.black); + + } + + @Override + protected void convert(BaseViewHolder helper, UserInfoItem item) { + if (item == null) { + return; + } + + super.convert(helper, item); + + switch (item.getItemType()) { + + case UserInfoItem.TYPE_MAGIC_ITEMS: + setMagicGallery(helper, item); + break; + + case UserInfoItem.TYPE_RADISH_ITEMS: + setRadishGallery(helper, item); + break; + + case UserInfoItem.TYPE_GIFT_ITEM: + setGiftItem(helper, item); + break; + + case UserInfoItem.TYPE_GIFT_EMPTY: + break; + } + + } + + private void setMagicGallery(BaseViewHolder helper, UserInfoItem item) { + ArrayList magicInfoList = (ArrayList) item.getData(); + + if (!ListUtils.isListEmpty(magicInfoList)) { + RecyclerView recyclerView = helper.itemView.findViewById(R.id.recycler_view_magic_wall); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); + + MyMagicWallAdapter mMagicListAdapter = new MyMagicWallAdapter(); + mMagicListAdapter.bindToRecyclerView(recyclerView); + + mMagicListAdapter.setNoble(isNoble); + mMagicListAdapter.setNewData(magicInfoList); + } + } + + private void setRadishGallery(BaseViewHolder helper, UserInfoItem item) { + ArrayList magicInfoList = (ArrayList) item.getData(); + + if (!ListUtils.isListEmpty(magicInfoList)) { + RecyclerView recyclerView = helper.itemView.findViewById(R.id.recycler_view_magic_wall); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); + + RadishWallAdapter radishWallAdapter = new RadishWallAdapter(); + radishWallAdapter.bindToRecyclerView(recyclerView); + + radishWallAdapter.setNewData(magicInfoList); + } + } + + private void setGiftItem(BaseViewHolder helper, UserInfoItem item) { + GiftWallInfo giftWallInfo = (GiftWallInfo) item.getData(); + + if (giftWallInfo != null) { + + helper.setText(R.id.gift_name, giftWallInfo.getGiftName()); + helper.setText(R.id.gift_num, String.valueOf(giftWallInfo.getReciveCount())); + helper.setTextColor(R.id.gift_name, mTextColor); + helper.setTextColor(R.id.gift_num, mTextColor); + + ImageView giftPic = helper.itemView.findViewById(R.id.gift_img); + ImageLoadUtils.loadImage(mContext, giftWallInfo.getPicUrl(), giftPic); + } + + } + + public void setNoble(boolean noble) { + isNoble = noble; + } + + public void setmTextColor(int mTextColor) { + this.mTextColor = mTextColor; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserInfoCarAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserInfoCarAdapter.java new file mode 100644 index 000000000..6474b7ee3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserInfoCarAdapter.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.content.Context; +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.bean.CarButtonInfo; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; + +import java.util.List; +import static com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo.STATUS_OFF_SHELF; +import static com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo.STATUS_OUT_OF_DATE; + +public class UserInfoCarAdapter extends UserTabBaseAdapter { + + public UserInfoCarAdapter(Context context, List data) { + super(context, data); + + addItemType(UserInfoItem.TYPE_CAR_ITEM, R.layout.user_info_my_car_item); + addItemType(UserInfoItem.TYPE_CAR_BUTTON, R.layout.layout_car_button); + addItemType(UserInfoItem.TYPE_CAR_EMPTY, R.layout.user_info_car_empty); + + } + + @Override + protected void convert(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + super.convert(helper, item); + + switch (item.getItemType()) { + case UserInfoItem.TYPE_CAR_ITEM: + setCarItem(helper, item); + break; + + case UserInfoItem.TYPE_CAR_BUTTON: + setCarButton(helper, item); + break; + + case UserInfoItem.TYPE_CAR_EMPTY: + break; + } + + } + + private void setCarItem(BaseViewHolder helper, UserInfoItem item) { + + CarInfo carInfo = (CarInfo) item.getData(); + + if (carInfo == null) + return; + + int resId = -1; + if (carInfo.getStatus() == STATUS_OUT_OF_DATE) { + resId = R.drawable.ic_car_expire; + } else if (carInfo.getStatus() == STATUS_OFF_SHELF) { + resId = R.drawable.ic_car_down; + } + + helper.setVisible(R.id.user_info_car_flag, + carInfo.getStatus() == STATUS_OUT_OF_DATE || carInfo.getStatus() == STATUS_OFF_SHELF) + .addOnClickListener(R.id.user_info_car_pic); + if (resId != -1) { + helper.setImageResource(R.id.user_info_car_flag, resId); + } + ImageView carPic = helper.getView(R.id.user_info_car_pic); + ImageLoadUtils.loadImage(mContext, carInfo.getPic(), carPic); + } + + private void setCarButton(BaseViewHolder helper, UserInfoItem item) { + CarButtonInfo carButtonInfo = (CarButtonInfo) item.getData(); + if (carButtonInfo == null) + return; + + helper.setText(R.id.tv_send_car, carButtonInfo.getContext()).addOnClickListener(R.id.tv_send_car); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserJoinWorldAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserJoinWorldAdapter.java new file mode 100644 index 000000000..0b5bb9b86 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserJoinWorldAdapter.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.ui.user.adapter; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.RectRoundImageView; +import com.yizhuan.erban.ui.utils.ImageLoadUtilsV2; +import com.yizhuan.xchat_android_core.user.bean.JoinWorldInfo; + +public class UserJoinWorldAdapter extends BaseQuickAdapter { + + public UserJoinWorldAdapter() { + super(R.layout.item_user_join_world); + } + + @Override + protected void convert(BaseViewHolder helper, JoinWorldInfo item) { + RectRoundImageView rectRoundImageView = helper.getView(R.id.rriv_user_join_world); + + ImageLoadUtilsV2.loadImage(rectRoundImageView, item.getIcon()); + helper.setText(R.id.tv_name_user_join_world, item.getName()); + + helper.addOnClickListener(R.id.ll_item_user_join_world); + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserTabBaseAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserTabBaseAdapter.java new file mode 100644 index 000000000..5f3527680 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/adapter/UserTabBaseAdapter.java @@ -0,0 +1,53 @@ +package com.yizhuan.erban.ui.user.adapter; + +import android.content.Context; + +import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.bean.GiftTitleInfo; +import com.yizhuan.xchat_android_core.bean.UserInfoItem; + +import java.util.List; + +public abstract class UserTabBaseAdapter extends BaseMultiItemQuickAdapter { + + public UserTabBaseAdapter(Context context, List data) { + super(data); + this.mContext = context; + + addItemType(UserInfoItem.TYPE_NONE, R.layout.layout_none); + addItemType(UserInfoItem.TYPE_DIV, R.layout.layout_gift_div); + addItemType(UserInfoItem.TYPE_TITLE, R.layout.layout_gift_title); + } + + public void setTitle(BaseViewHolder helper, UserInfoItem item) { + GiftTitleInfo giftTitleInfo = (GiftTitleInfo) item.getData(); + + if (giftTitleInfo == null) { + helper.setText(R.id.tv_title_text, ""); + helper.setText(R.id.tv_title_number, "(" + 0 + ")"); + + } else { + helper.setText(R.id.tv_title_text, giftTitleInfo.getTitle()); + helper.setText(R.id.tv_title_number, "(" + giftTitleInfo.getNum() + ")"); + + } + + } + + @Override + protected void convert(BaseViewHolder helper, UserInfoItem item) { + if (item == null) + return; + + switch (item.getItemType()) { + case UserInfoItem.TYPE_DIV: + break; + + case UserInfoItem.TYPE_TITLE: + setTitle(helper, item); + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionFragment.java new file mode 100644 index 000000000..1019bca64 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionFragment.java @@ -0,0 +1,201 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +import static com.yizhuan.erban.R.id.swipe_refresh; + +public class DSAttentionFragment extends BaseFragment { + public static final String TAG = "AttentionFragment"; + + private RecyclerView mRecyclerView; + private SwipeRefreshLayout swipeRefreshLayout; + private DSAttentionListAdapter mAdapter; + private List mAttentionInfoList = new ArrayList<>(); + private int mPage = Constants.PAGE_START; + + private DecorationSendActivity friendActivity; + + public static DSAttentionFragment newInstance() { + return new DSAttentionFragment(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + if (activity instanceof DecorationSendActivity) { + friendActivity = (DecorationSendActivity) activity; + } + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + //需要踩人等东西,所以进入这个界面需要强制刷新 + if (isVisibleToUser) { + firstLoadData(); + } + } + + @Override + public void onFindViews() { + mRecyclerView = mView.findViewById(R.id.recycler_view); + swipeRefreshLayout = mView.findViewById(swipe_refresh); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + } + + @Override + public void onSetListener() { + swipeRefreshLayout.setOnRefreshListener(onRefreshListener); + mAdapter = new DSAttentionListAdapter(mAttentionInfoList); + mAdapter.setRylListener(attentionInfo -> { + if (friendActivity != null) { + friendActivity.showSureDialog(attentionInfo.getUid(), attentionInfo.getNick()); + } + }); + mAdapter.setOnLoadMoreListener(() -> { + mPage++; + onRefreshing(); + }, mRecyclerView); + } + + @Override + public void initiate() { + mRecyclerView.setAdapter(mAdapter); + showLoading(); + onRefreshing(); + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_decoration_send_list; + } + + SwipeRefreshLayout.OnRefreshListener onRefreshListener = this::firstLoadData; + + public void firstLoadData() { + mPage = Constants.PAGE_START; + onRefreshing(); + } + + private void onRefreshing() { + AttentionModel.get().getAttentionList( + AuthModel.get().getCurrentUid(), + mPage, + Constants.PAGE_SIZE + ) + .subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List attentionInfos) { + onGetAttentionList(attentionInfos, mPage); + } + + @Override + public void onError(Throwable e) { + onGetAttentionListFail(e.getMessage(), mPage); + } + }); + } + + public void onGetAttentionList(List attentionInfoList, int page) { + mPage = page; + if (!ListUtils.isListEmpty(attentionInfoList)) { + if (mPage == Constants.PAGE_START) { + hideStatus(); + swipeRefreshLayout.setRefreshing(false); + mAttentionInfoList.clear(); + mAdapter.setNewData(attentionInfoList); + if (attentionInfoList.size() < Constants.PAGE_SIZE) { + mAdapter.setEnableLoadMore(false); + } + } else { + mAdapter.loadMoreComplete(); + mAdapter.addData(attentionInfoList); + } + } else { + if (mPage == Constants.PAGE_START) { + swipeRefreshLayout.setRefreshing(false); + showNoData(getString(R.string.no_attention_text)); + } else { + mAdapter.loadMoreEnd(true); + } + + } + } + + public void onGetAttentionListFail(String error, int page) { + mPage = page; + if (mPage == Constants.PAGE_START) { + swipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + mAdapter.loadMoreFail(); + toast(error); + } + } + + // ------------------关注动作回调 begin------------------- + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + if (event.isFailed()) { + return; + } + onRefreshing(); + } + // ------------------关注动作回调 end------------------- + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + onRefreshing(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + mPage = Constants.PAGE_START; + showLoading(); + onRefreshing(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionListAdapter.java new file mode 100644 index 000000000..a4382bbc1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSAttentionListAdapter.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.user.bean.AttentionInfo; + +import java.util.List; + +public class DSAttentionListAdapter extends DSBaseListAdapter { + + public DSAttentionListAdapter(List attentionInfoList) { + super(attentionInfoList); + } + + @Override + public String getNick(AttentionInfo info) { + return info.getNick(); + } + + @Override + public String getAvatar(AttentionInfo info) { + return info.getAvatar(); + } + + @Override + public NobleInfo getNobleInfo(AttentionInfo info) { + return info.nobleUsers; + } + + @Override + public UserLevelVo getUserLevelVo(AttentionInfo info) { + return info.userLevelVo; + } + + @Override + public int getGender(AttentionInfo info) { + return info.getGender(); + } + + @Override + public String getUserDesc(AttentionInfo info) { + return info.getUserDesc(); + } + + @Override + public void listeners(AttentionInfo info) { + if (rylListener != null) + rylListener.sendListener(info); + } + + private onClickListener rylListener; + + public interface onClickListener { + void sendListener(AttentionInfo attentionInfo); + } + + public void setRylListener(onClickListener onClickListener) { + rylListener = onClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSBaseListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSBaseListAdapter.java new file mode 100644 index 000000000..2f6e05733 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSBaseListAdapter.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.NobleAvatarView; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +import java.util.List; + +/** + * 好友,关注,粉丝展示ui一致 + */ +public abstract class DSBaseListAdapter extends BaseQuickAdapter { + + DSBaseListAdapter(List list) { + super(R.layout.item_send, list); + } + + @Override + protected void convert(K helper, T item) { + if (item == null) return; + + helper.setText(R.id.tv_userName, getNick(item)); + helper.setOnClickListener(R.id.tv_send, v -> listeners(item)); + + NobleInfo nobleUsers = getNobleInfo(item); + + NobleAvatarView nobleAvatarView = helper.getView(R.id.noble_avatar_view); + nobleAvatarView.setSize(50, 65, 15); + nobleAvatarView.setData(getAvatar(item), nobleUsers); + + AppCompatImageView ivNobleLevel = helper.getView(R.id.iv_user_badge); + ivNobleLevel.setVisibility(View.GONE); + if (nobleUsers != null) { + String badgeByLevel = NobleUtil.getBadgeByLevel(nobleUsers.getLevel()); + if (!TextUtils.isEmpty(badgeByLevel)) { + ivNobleLevel.setVisibility(View.VISIBLE); + NobleUtil.loadResource(badgeByLevel, ivNobleLevel); + } + } + + AppCompatImageView ivUserLevel = helper.getView(R.id.iv_user_level); + AppCompatImageView ivOtherLevel = helper.getView(R.id.iv_other_level); + ivUserLevel.setVisibility(View.GONE); + ivOtherLevel.setVisibility(View.GONE); + UserLevelVo userLevelVo = getUserLevelVo(item); + if (userLevelVo != null && !TextUtils.isEmpty(userLevelVo.getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, userLevelVo.getExperUrl(), ivUserLevel); + + if (!TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + ivOtherLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(mContext, userLevelVo.getCharmUrl(), ivOtherLevel); + } + } + + AppCompatImageView gender = helper.getView(R.id.iv_gender); + if (getGender(item) == 2) { + gender.setImageResource(R.drawable.ic_female); + } else { + gender.setImageResource(R.drawable.ic_male); + } + + TextView desc = helper.getView(R.id.tv_desc); + desc.setText(getUserDesc(item)); + } + + public abstract String getNick(T info); + public abstract String getAvatar(T info); + public abstract NobleInfo getNobleInfo(T info); + public abstract UserLevelVo getUserLevelVo(T info); + public abstract int getGender(T info); + public abstract String getUserDesc(T info); + public abstract void listeners(T info); + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansListFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansListFragment.java new file mode 100644 index 000000000..9e3c4d084 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansListFragment.java @@ -0,0 +1,219 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.praise.event.PraiseEvent; +import com.yizhuan.xchat_android_core.user.AttentionModel; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; +import com.yizhuan.xchat_android_core.user.bean.FansListInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class DSFansListFragment extends BaseFragment { + private RecyclerView mRecyclerView; + private SwipeRefreshLayout mSwipeRefreshLayout; + private DSFansViewAdapter mAdapter; + private int mCurrentCounter = Constants.PAGE_START; + private List mFansInfoList = new ArrayList<>(); + private Context mContext; + private int mPageType; + private DecorationSendActivity friendActivity; + + public static DSFansListFragment newInstanceForSelect() { + return new DSFansListFragment(); + } + + public static DSFansListFragment newInstance(int pageType) { + DSFansListFragment fragment = new DSFansListFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(Constants.KEY_PAGE_TYPE, pageType); + fragment.setArguments(bundle); + return fragment; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + mPageType = bundle.getInt(Constants.KEY_PAGE_TYPE); + } + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof DecorationSendActivity) { + friendActivity = (DecorationSendActivity) activity; + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = getContext(); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + mRecyclerView = mView.findViewById(R.id.recycler_view); + mSwipeRefreshLayout = mView.findViewById(R.id.swipe_refresh); + } + + @Override + public void onSetListener() { + mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + mAdapter = new DSFansViewAdapter(mFansInfoList); + mAdapter.setOnLoadMoreListener(() -> { + mCurrentCounter++; + onRefreshing(); + }, mRecyclerView); + mRecyclerView.setAdapter(mAdapter); + mSwipeRefreshLayout.setOnRefreshListener(() -> { + mCurrentCounter = Constants.PAGE_START; + onRefreshing(); + }); + mAdapter.setRylListener(new DSFansViewAdapter.OnItemClickListener() { + @Override + public void onItemClick(FansInfo fansInfo) { + UserInfoActivity.Companion.start(mContext, fansInfo.getUid()); + } + + @Override + public void sendListener(FansInfo attentionInfo) { + if (friendActivity != null) { + friendActivity.showSureDialog(attentionInfo.getUid(), attentionInfo.getNick()); + } + } + }); + } + + private void onRefreshing() { + AttentionModel.get().getFansList( + AuthModel.get().getCurrentUid(), + mCurrentCounter, + Constants.PAGE_SIZE + ).subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FansListInfo fansListInfo) { + onGetMyFansList(fansListInfo, mPageType, mCurrentCounter); + } + + @Override + public void onError(Throwable e) { + onGetMyFansListFail(e.getMessage(), mPageType, mCurrentCounter); + } + }); + } + + @Override + public void initiate() { + showLoading(); + onRefreshing(); + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_decoration_send_list; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPraise(PraiseEvent event) { + getDialogManager().dismissDialog(); + if (!event.isFailed()) { + toast(event.getError()); + return; + } + //该界面关注后,关注按钮消失,所有没有取消操作 + toast(getString(R.string.fan_success)); + } + + public void onGetMyFansList(FansListInfo fansListInfo, int pageType, int page) { + mCurrentCounter = page; + if (pageType == mPageType) { + mSwipeRefreshLayout.setRefreshing(false); + if (fansListInfo == null || ListUtils.isListEmpty(fansListInfo.getFansList())) { + //第一页 + if (mCurrentCounter == Constants.PAGE_START) { + showNoData(getString(R.string.no_fan_text)); + } else { + mAdapter.loadMoreEnd(true); + } + } else { + hideStatus(); + if (mCurrentCounter == Constants.PAGE_START) { + mFansInfoList.clear(); + List fansList = fansListInfo.getFansList(); + mFansInfoList.addAll(fansList); + mAdapter.setNewData(mFansInfoList); + if (fansList.size() < Constants.PAGE_SIZE) { + mAdapter.setEnableLoadMore(false); + } + return; + } + mAdapter.loadMoreComplete(); + mAdapter.addData(fansListInfo.getFansList()); + } + } + } + + public void onGetMyFansListFail(String error, int pageType, int page) { + mCurrentCounter = page; + if (pageType == mPageType) { + if (mCurrentCounter == Constants.PAGE_START) { + mSwipeRefreshLayout.setRefreshing(false); + showNetworkErr(); + } else { + mAdapter.loadMoreFail(); + toast(error); + } + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + mCurrentCounter = Constants.PAGE_START; + onRefreshing(); + } + + @Override + public void onReloadData() { + super.onReloadData(); + mCurrentCounter = Constants.PAGE_START; + showLoading(); + onRefreshing(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansViewAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansViewAdapter.java new file mode 100644 index 000000000..9665f756f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFansViewAdapter.java @@ -0,0 +1,63 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; + +import java.util.List; + +public class DSFansViewAdapter extends DSBaseListAdapter { + + private OnItemClickListener onItemClickListener; + + public interface OnItemClickListener { + void onItemClick(FansInfo fansInfo); + void sendListener(FansInfo attentionInfo); + } + + public void setRylListener(OnItemClickListener onClickListener) { + onItemClickListener = onClickListener; + } + + public DSFansViewAdapter(List fansInfoList) { + super(fansInfoList); + } + + @Override + public String getNick(FansInfo info) { + return info.getNick(); + } + + @Override + public String getAvatar(FansInfo info) { + return info.getAvatar(); + } + + @Override + public NobleInfo getNobleInfo(FansInfo info) { + return info.getNobleUsers(); + } + + @Override + public UserLevelVo getUserLevelVo(FansInfo info) { + return info.getUserLevelVo(); + } + + @Override + public int getGender(FansInfo info) { + return info.getGender(); + } + + @Override + public String getUserDesc(FansInfo info) { + return info.getUserDesc(); + } + + @Override + public void listeners(FansInfo info) { + if (onItemClickListener != null) + onItemClickListener.sendListener(info); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListAdapter.java new file mode 100644 index 000000000..b4f5b5f17 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListAdapter.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import java.util.List; + +public class DSFriendListAdapter extends DSBaseListAdapter { + + private onClickListener rylListener; + + public DSFriendListAdapter(List userInfoList) { + super(userInfoList); + } + + @Override + public String getNick(UserInfo info) { + return info.getNick(); + } + + @Override + public String getAvatar(UserInfo info) { + return info.getAvatar(); + } + + @Override + public NobleInfo getNobleInfo(UserInfo info) { + return info.getNobleUsers(); + } + + @Override + public UserLevelVo getUserLevelVo(UserInfo info) { + return info.getUserLevelVo(); + } + + @Override + public int getGender(UserInfo info) { + return info.getGender(); + } + + @Override + public String getUserDesc(UserInfo info) { + return info.getUserDesc(); + } + + public void setRylListener(onClickListener onClickListener) { + rylListener = onClickListener; + } + + @Override + public void listeners(UserInfo info) { + if (rylListener != null) + rylListener.sendListener(info); + } + + public interface onClickListener { + void sendListener(UserInfo userInfo); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListFragment.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListFragment.java new file mode 100644 index 000000000..98d20f4bc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DSFriendListFragment.java @@ -0,0 +1,160 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import android.app.Activity; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.xchat_android_core.im.friend.IMFriendModel; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RelationShipEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.user.event.LoginUserInfoUpdateEvent; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class DSFriendListFragment extends BaseFragment { + + private DSFriendListAdapter mAdapter = null; + private DecorationSendActivity selectFriendActivity; + private SwipeRefreshLayout mSwipeRefresh; + private RecyclerView mRecyclerView; + + public static DSFriendListFragment newInstances() { + return new DSFriendListFragment(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof DecorationSendActivity) { + selectFriendActivity = (DecorationSendActivity) activity; + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + mSwipeRefresh = mView.findViewById(R.id.swipe_refresh); + mRecyclerView = mView.findViewById(R.id.recycler_view); + } + + @Override + public void onSetListener() { + } + + @Override + public void initiate() { + mSwipeRefresh.setOnRefreshListener(() -> { + mSwipeRefresh.setRefreshing(true); + loadFriends(); + mSwipeRefresh.setRefreshing(false); + }); + + mAdapter = new DSFriendListAdapter(null); + mAdapter.setEnableLoadMore(true); + mAdapter.setRylListener((attentionInfo)->{ + if (selectFriendActivity != null && attentionInfo != null) { + selectFriendActivity.showSureDialog(attentionInfo.getUid(), attentionInfo.getNick()); + } + }); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + mRecyclerView.setAdapter(mAdapter); + + loadFriends(); + + Disposable d = IMNetEaseManager.get().getRelationShipEventObservable().subscribe(this::onGetRelationShipEvent); + mCompositeDisposable.add(d); + } + + private void onGetRelationShipEvent(RelationShipEvent event) { + if (event.event == RelationShipEvent.EVENT_FRIEND_UPDATE) { + onFriendListUpdate(event.accounts); + } + } + + private void loadFriends() { + onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()); + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_decoration_send_list; + } + + private void onFriendListUpdate(List accounts) { + if (ListUtils.isListEmpty(accounts)) { + showNoData(getString(R.string.no_frenids_text)); + return; + } + UserModel.get().loadUserInfoByUids(accounts).subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(List userInfos) { + setData(userInfos); + } + + @Override + public void onError(Throwable e) { + toast(e.getMessage()); + } + }); + + } + + private void setData(List userInfo) { + if (userInfo != null && !userInfo.isEmpty()) { + hideStatus(); + mAdapter.setNewData(userInfo); + mAdapter.notifyDataSetChanged(); + } else { + showNoData(getString(R.string.no_frenids_text)); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoginUserInfoUpdateEvent event) { + mRecyclerView.postDelayed(()->onFriendListUpdate(IMFriendModel.get().getMyFriendsAccounts()) + , 250); + } + + + @Override + public void onReloadData() { + super.onReloadData(); + showLoading(); + loadFriends(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DecorationSendActivity.java b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DecorationSendActivity.java new file mode 100644 index 000000000..d6d0dcde2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/decorationsend/DecorationSendActivity.java @@ -0,0 +1,161 @@ +package com.yizhuan.erban.ui.user.decorationsend; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.Fragment; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.common.ViewPagerAdapter; +import com.yizhuan.erban.databinding.ActivityDecorationSendBinding; +import com.yizhuan.erban.decoration.helper.DecorationDialogHelper; +import com.yizhuan.erban.decoration.helper.DecorationSaleType; +import com.yizhuan.erban.decoration.view.widgets.CarMagicIndicator; +import com.yizhuan.erban.friend.action.AbstractSelectFriendAction; +import com.yizhuan.erban.ui.search.SearchActivity; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.decoration.car.bean.CarInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.util.ArrayList; +import java.util.List; + +@ActLayoutRes(R.layout.activity_decoration_send) +public class DecorationSendActivity extends BaseBindingActivity implements CarMagicIndicator.OnItemSelectListener { + + private static final String CAR_INFO = "carInfo"; + private static final String WEAR_INFO = "wearInfo"; + + private String[] titles = {"好友", "关注", "粉丝"}; + private CarInfo carInfo; + private HeadWearInfo wearInfo; + private int type; + + public static void start(Context context, CarInfo carInfo) { + Intent intent = new Intent(context, DecorationSendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_CAR); + intent.putExtra(CAR_INFO, carInfo); + context.startActivity(intent); + } + + public static void start(Context context, HeadWearInfo wearInfo) { + Intent intent = new Intent(context, DecorationSendActivity.class); + intent.putExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_WEAR); + intent.putExtra(WEAR_INFO, wearInfo); + context.startActivity(intent); + } + + @Override + public void init() { + type = getIntent().getIntExtra(AbstractSelectFriendAction.KEY_TYPE, AbstractSelectFriendAction.TYPE_CAR); + + if (type != AbstractSelectFriendAction.TYPE_CAR && type != AbstractSelectFriendAction.TYPE_WEAR) + finish(); + + carInfo = (CarInfo) getIntent().getSerializableExtra(CAR_INFO); + wearInfo = (HeadWearInfo) getIntent().getSerializableExtra(WEAR_INFO); + + initTitleBar(getString(R.string.title_select_friend)); + + mBinding.titleBar.addAction(new TitleBar.Action() { + @Override + public String getText() { + return null; + } + + @Override + public int getDrawable() { + return R.drawable.ic_send_search; + } + + @Override + public void performAction(View view) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + SearchActivity.start(DecorationSendActivity.this, carInfo); + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + SearchActivity.start(DecorationSendActivity.this, wearInfo); + break; + + } + } + }); + + mBinding.viewpager.setOffscreenPageLimit(3); + mBinding.viewpager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), getFragment(), titles)); + + List tabInfoList = new ArrayList<>(2); + tabInfoList.add(new TabInfo(1, getString(R.string.tab_title_friends))); + tabInfoList.add(new TabInfo(2, getString(R.string.tab_title_attentions))); + tabInfoList.add(new TabInfo(3, getString(R.string.tab_title_fans))); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CarMagicIndicator indicator = new CarMagicIndicator(this, tabInfoList, 0); + indicator.setOnItemSelectListener(this); + commonNavigator.setAdapter(indicator); + mBinding.viewIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(mBinding.viewIndicator, mBinding.viewpager); + } + + private List getFragment() { + List list = new ArrayList<>(); + list.add(DSFriendListFragment.newInstances()); + list.add(DSAttentionFragment.newInstance()); + list.add(DSFansListFragment.newInstanceForSelect()); + return list; + } + + @Override + public void onItemSelect(int position) { + mBinding.viewpager.setCurrentItem(position); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == SearchActivity.CODE_REQUEST_TO_SEARCH && resultCode == RESULT_OK) { + setResult(RESULT_OK, data); + finish(); + } + } + + public void showSureDialog(long targetUid, String nick) { + switch (type) { + case AbstractSelectFriendAction.TYPE_CAR: + if (carInfo != null) { + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setType(DecorationSaleType.SEND_CAR) + .setNick(nick) + .setDecoration(carInfo) + .setTargetUid(targetUid) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(context, getDialogManager(), options); + helper.showBuyOrDonateDialog(); + } + break; + + case AbstractSelectFriendAction.TYPE_WEAR: + if (wearInfo != null) { + DecorationDialogHelper.Options options = new DecorationDialogHelper.Builder() + .setType(DecorationSaleType.SEND_HEAD_WEAR) + .setNick(nick) + .setDecoration(wearInfo) + .setTargetUid(targetUid) + .create(); + DecorationDialogHelper helper = new DecorationDialogHelper(context, getDialogManager(), options); + helper.showBuyOrDonateDialog(); + } else { + return; + } + break; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/dialog/LiveTagDialog.java b/app/src/main/java/com/yizhuan/erban/ui/user/dialog/LiveTagDialog.java new file mode 100644 index 000000000..f6fe4eccb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/dialog/LiveTagDialog.java @@ -0,0 +1,117 @@ +package com.yizhuan.erban.ui.user.dialog; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.treasure_box.widget.dialog.BaseBindingDialog; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.bindadapter.BaseAdapter; +import com.yizhuan.erban.bindadapter.BindingViewHolder; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.databinding.DialogLiveTagBinding; +import com.yizhuan.erban.databinding.ItemLiveTagDialogBinding; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.LiveTagInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.List; + +@ActLayoutRes(R.layout.dialog_live_tag) +public class LiveTagDialog extends BaseBindingDialog implements View.OnClickListener { + + private final List listBeans; + private long liveId; + + public LiveTagDialog(Context context, List listBeans) { + super(context); + this.listBeans = listBeans; + } + + @Override + protected void init() { + binding.setClick(this); + binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + LiveTagAdapter adapter = new LiveTagAdapter(R.layout.item_live_tag_dialog, BR.tagInfo); + adapter.setOnItemClickListener((adapt, view, position) -> { + liveId = adapter.getItem(position).getLiveId(); + adapter.setSelect(position); + adapter.notifyDataSetChanged(); + }); + for (int i = 0; i < listBeans.size(); i++) { + LiveTagInfo.LiveSkillVoListBean listBean = listBeans.get(i); + if (listBean.getHasUse() == 1) { + liveId = listBean.getLiveId(); + adapter.setSelect(i); + break; + } + } + binding.recyclerView.setAdapter(adapter); + adapter.setNewData(listBeans); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_delete: + closeDialog(); + ((BaseActivity) context).getDialogManager().showOkCancelDialog("删除的标签需重新认证", true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + UserModel.get().useOrDelete(liveId, 1) + .subscribe(s -> { + UserModel.get().updateCurrentUserInfo().subscribe(); + SingleToastUtil.showToast("删除成功"); + }); + } + }); + + break; + case R.id.tv_used: + + UserModel.get().useOrDelete(liveId, 2) + .subscribe(s -> { + UserModel.get().updateCurrentUserInfo().subscribe(); + SingleToastUtil.showToast("使用成功"); + closeDialog(); + }); + break; + } + + + } + + private static class LiveTagAdapter extends BaseAdapter { + private int select = -1; + + public int getSelect() { + return select; + } + + public void setSelect(int select) { + this.select = select; + } + + public LiveTagAdapter(int layoutResId, int brid) { + super(layoutResId, brid); + } + + @Override + protected void convert(BindingViewHolder helper, LiveTagInfo.LiveSkillVoListBean item) { + super.convert(helper, item); + ItemLiveTagDialogBinding binding = (ItemLiveTagDialogBinding) helper.getBinding(); + if (select == helper.getAdapterPosition()) { + binding.ivSelect.setVisibility(View.VISIBLE); + } else { + binding.ivSelect.setVisibility(View.GONE); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/presenter/UserGiftAchievementPresenter.java b/app/src/main/java/com/yizhuan/erban/ui/user/presenter/UserGiftAchievementPresenter.java new file mode 100644 index 000000000..d3cd3496c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/presenter/UserGiftAchievementPresenter.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.ui.user.presenter; + +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.erban.ui.user.view.IUserGiftAchievement; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementInfo; + +import java.util.List; + +import io.reactivex.functions.BiConsumer; + +public class UserGiftAchievementPresenter extends BaseMvpPresenter { + + @SuppressWarnings("CheckResult") + public void getAchievementList(long targetUid) { + UserModel.get() + .getAchievementList(targetUid) + .compose(bindToLifecycle()).subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List list, Throwable throwable) throws Exception { + if (throwable != null) { + if (mMvpView != null) { + mMvpView.getAchievementListFail(throwable); + } + } else { + if (mMvpView != null) { + mMvpView.getAchievementListSuccess(list); + } + } + + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/user/view/IUserGiftAchievement.java b/app/src/main/java/com/yizhuan/erban/ui/user/view/IUserGiftAchievement.java new file mode 100644 index 000000000..920eb7c4a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/user/view/IUserGiftAchievement.java @@ -0,0 +1,11 @@ +package com.yizhuan.erban.ui.user.view; + +import com.yizhuan.xchat_android_core.user.bean.GiftAchievementInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +public interface IUserGiftAchievement extends IMvpBaseView { + void getAchievementListSuccess(List list); + void getAchievementListFail(Throwable error); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/ArrayUtils.java b/app/src/main/java/com/yizhuan/erban/ui/utils/ArrayUtils.java new file mode 100644 index 000000000..cb3498997 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/ArrayUtils.java @@ -0,0 +1,50 @@ +package com.yizhuan.erban.ui.utils; + +import com.yizhuan.xchat_android_library.utils.log.MLog; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.List; + +/** + * Created by zhouxiangfeng on 2017/6/14. + */ + +public class ArrayUtils { + + private static final String TAG = "ArrayUtils"; + + public static List deepCopy(List src) { + List dest = null; + try { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = null; + out = new ObjectOutputStream(byteOut); + out.writeObject(src); + + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + dest = (List) in.readObject(); + } catch (IOException e) { + e.printStackTrace(); + MLog.error(TAG,"deep copy io exception!"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + MLog.error(TAG,"deep copy classNotFoundException!"); + } + return dest; + } + + public static boolean replace(List mListData, T newT, T t) { + if (mListData.contains(t)) { + int position = mListData.indexOf(t); + mListData.set(position, newT); + return true; + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/DesignUtils.java b/app/src/main/java/com/yizhuan/erban/ui/utils/DesignUtils.java new file mode 100644 index 000000000..4edcd3f34 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/DesignUtils.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.ui.utils; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.app.Activity; +import android.os.Build; +import android.transition.Explode; +import android.transition.Fade; +import android.transition.Slide; +import android.view.Gravity; +import android.view.View; +import android.view.ViewAnimationUtils; + +/** + * Created by zhouxiangfeng on 2017/4/18. + */ + +public class DesignUtils { + + /** + * 显示控件 + * @param myView + */ + private void show(final View myView) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // get the center for the clipping circle + int cx = (myView.getLeft() + myView.getRight()) / 2; + int cy = (myView.getTop() + myView.getBottom()) / 2; + // get the final radius for the clipping circle + int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); + // create the animator for this view (the start radius is zero) + Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); + // make the view visible and start the animation + myView.setVisibility(View.VISIBLE); + anim.start(); + } else { + myView.setVisibility(View.VISIBLE); + } + } + + /** + * 隐藏控件 + * @param myView + */ + private void hide(final View myView) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // get the center for the clipping circle + int cx = (myView.getLeft() + myView.getRight()) / 2; + int cy = (myView.getTop() + myView.getBottom()) / 2; + // get the initial radius for the clipping circle + int initialRadius = myView.getWidth(); + // create the animation (the final radius is zero) + Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); + // make the view invisible when the animation is done + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + myView.setVisibility(View.INVISIBLE); + } + }); + anim.start(); + } else { + myView.setVisibility(View.INVISIBLE); + } + } + + private void showAnim(Activity act, int type) { + if(Build.VERSION.SDK_INT >= 21){ + switch (type) { + case 1: + Explode explode = new Explode(); + explode.setDuration(300L); + act.getWindow().setEnterTransition(explode); + break; + case 2: + Slide slide = new Slide(Gravity.RIGHT); + slide.setDuration(300L); + act.getWindow().setEnterTransition(slide); + break; + case 3: + Fade fade = new Fade(); + fade.setDuration(300L); + act.getWindow().setEnterTransition(fade); + break; + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/GlideCacheUtil.java b/app/src/main/java/com/yizhuan/erban/ui/utils/GlideCacheUtil.java new file mode 100644 index 000000000..6cda46dfb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/GlideCacheUtil.java @@ -0,0 +1,175 @@ +package com.yizhuan.erban.ui.utils; + +import android.content.Context; +import android.os.Looper; +import android.text.TextUtils; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory; +import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; + +import java.io.File; +import java.math.BigDecimal; + +/** + * Glide缓存工具类 + * Created by KathLine on 2017/4/27. + */ + +public class GlideCacheUtil { + private static GlideCacheUtil inst; + + public static GlideCacheUtil getInstance() { + if (inst == null) { + inst = new GlideCacheUtil(); + } + return inst; + } + + /** + * 清除图片磁盘缓存 + */ + public void clearImageDiskCache(final Context context) { + try { + if (Looper.myLooper() == Looper.getMainLooper()) { + new Thread(new Runnable() { + @Override + public void run() { + Glide.get(context).clearDiskCache(); + } + }).start(); + } else { + Glide.get(context).clearDiskCache(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 清除图片内存缓存 + */ + public void clearImageMemoryCache(Context context) { + try { + if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行 + Glide.get(context).clearMemory(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 清除图片所有缓存 + */ + public void clearImageAllCache(Context context) { + clearImageDiskCache(context); + clearImageMemoryCache(context); + String ImageExternalCatchDir = context.getExternalCacheDir() + ExternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR; + deleteFolderFile(ImageExternalCatchDir, true); + } + + /** + * 获取Glide造成的缓存大小 + * + * @return CacheSize + */ + public String getCacheSize(Context context) { + try { + return getFormatSize(getFolderSize(new File(context.getCacheDir() + "/" + InternalCacheDiskCacheFactory.DEFAULT_DISK_CACHE_DIR))); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 获取指定文件夹内所有文件大小的和 + * + * @param file file + * @return size + * @throws Exception + */ + private long getFolderSize(File file) throws Exception { + long size = 0; + try { + File[] fileList = file.listFiles(); + for (File aFileList : fileList) { + if (aFileList.isDirectory()) { + size = size + getFolderSize(aFileList); + } else { + size = size + aFileList.length(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return size; + } + + /** + * 删除指定目录下的文件,这里用于缓存的删除 + * + * @param filePath filePath + * @param deleteThisPath deleteThisPath + */ + private void deleteFolderFile(String filePath, boolean deleteThisPath) { + if (!TextUtils.isEmpty(filePath)) { + try { + File file = new File(filePath); + if (file.isDirectory()) { + File files[] = file.listFiles(); + for (File file1 : files) { + deleteFolderFile(file1.getAbsolutePath(), true); + } + } + if (deleteThisPath) { + if (!file.isDirectory()) { + file.delete(); + } else { + if (file.listFiles().length == 0) { + file.delete(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * 格式化单位 + * + * @param size size + * @return size + */ + private static String getFormatSize(double size) { + + double kiloByte = size / 1024; + if (kiloByte < 1) { + return size + "Byte"; + } + + double megaByte = kiloByte / 1024; + if (megaByte < 1) { + BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); + return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB"; + } + + double gigaByte = megaByte / 1024; + if (gigaByte < 1) { + BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); + return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB"; + } + + double teraBytes = gigaByte / 1024; + if (teraBytes < 1) { + BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); + return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"; + } + BigDecimal result4 = new BigDecimal(teraBytes); + + return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtils.java b/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtils.java new file mode 100644 index 000000000..1faa27a9a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtils.java @@ -0,0 +1,485 @@ +package com.yizhuan.erban.ui.utils; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.CircleCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.target.Target; +import com.bumptech.glide.request.transition.Transition; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.utils.BlurTransformation; +import com.yizhuan.xchat_android_core.utils.SystemUtils; + +import java.io.File; + +import io.reactivex.Single; + +/** + * 图片加载处理 + * Created by chenran on 2017/11/9. + */ +public class ImageLoadUtils { + private static final String PIC_PROCESSING = "?imageslim"; + private static final String ACCESS_URL = "img.erbanyy.com"; + + public static void laodUsrInfoAvatar(Context context, String avatar, ImageView imageView) { + loadCircleImage(context, avatar, imageView, R.drawable.default_user_head); + } + + public static void loadAvatar(Context context, String avatar, ImageView imageView, boolean isCircle) { + if (StringUtil.isEmpty(avatar)) { + loadDefaultImage(context, imageView, R.drawable.default_user_head); + return; + } + + StringBuilder sb = new StringBuilder(avatar); + if (avatar.contains(ACCESS_URL)) { + if (!avatar.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/100/h/100"); + } + if (isCircle) { + loadCircleImage(context, sb.toString(), imageView, R.drawable.default_user_head); + } else { + loadImage(context, sb.toString(), imageView, R.drawable.default_user_head); + } + } + + public static void loadBigAvatar(Context context, String avatar, ImageView imageView, boolean isCircle) { + if (StringUtil.isEmpty(avatar)) { + return; + } + StringBuffer sb = new StringBuffer(avatar); + if (avatar.contains(ACCESS_URL)) { + if (!avatar.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/150/h/150"); + } + if (isCircle) { + loadCircleImage(context, sb.toString(), imageView, R.drawable.default_user_head); + } else { + loadImage(context, sb.toString(), imageView, R.drawable.default_user_head); + } + } + + public static void loadAvatar(Context context, String avatar, ImageView imageView) { + loadAvatar(context, avatar, imageView, false); + } + + public static void loadAvatar(String avatar, ImageView imageView) { + loadAvatar(avatar, imageView, R.drawable.default_user_head); + } + + public static void loadAvatar(String avatar, ImageView imageView, int defaultRes) { + loadAvatar(avatar, imageView, defaultRes, 150); + } + + public static void loadAvatarBig(String avatar, ImageView imageView) { + loadAvatarBig(avatar, imageView, R.drawable.default_user_head); + } + + public static void loadAvatarBig(String avatar, ImageView imageView, int defaultRes) { + loadAvatar(avatar, imageView, defaultRes, 250); + } + + /** + * do by lvzebiao + * 加载头像通用方法 + */ + public static void loadAvatar(String avatar, ImageView imageView, int defaultRes, int customSize) { + StringBuilder sb = new StringBuilder(avatar); + if (avatar.contains(ACCESS_URL)) { + if (!avatar.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/").append(customSize).append("/h/").append(customSize); + } + loadImage(imageView.getContext(), sb.toString(), imageView, defaultRes); + } + + public static void loadSmallRoundBackground(Context context, String url, ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuilder sb = new StringBuilder(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/220/h/220"); + } + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new RoundedCorners(context.getResources().getDimensionPixelOffset(R.dimen.common_cover_round_size))) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(imageView); + } + + public static void loadRoomBgBackground(Context context, String url, ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuilder sb = new StringBuilder(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/720/h/1280"); + } + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .into(imageView); + } + + public static void loadBannerRoundBackground(Context context, String url, ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/660/h/220"); + } + + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new RoundedCorners(context.getResources().getDimensionPixelOffset(R.dimen.common_cover_round_size))) + .placeholder(R.drawable.default_cover) + .into(imageView); + } + + public static void loadGameBannerRoundBackground(Context context, String url, ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/660/h/220"); + } + + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new RoundedCorners(context.getResources().getDimensionPixelOffset(R.dimen.dp_8))) + .placeholder(R.drawable.default_cover) + .into(imageView); + } + + public static void loadBannerRoundBackground(Context context, String url, ImageView imageView, int roundingRadius) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/660/h/220"); + } + + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new RoundedCorners(roundingRadius)) + .placeholder(R.drawable.default_cover) + .into(imageView); + } + + public static void loadPhotoThumbnail(Context context, String url, ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/150/h/150"); + } + + loadImage(context, sb.toString(), imageView, R.drawable.default_cover); + } + + public static void loadImageWithBlurTransformation(Context context, String url, final ImageView imageView) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/75/h/75"); + } + GlideApp.with(context.getApplicationContext()) + .load(sb.toString()) + .dontTransform() + .dontAnimate() + .override(75, 75) + .centerInside() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, + Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, + Target target, DataSource dataSource, boolean b) { + imageView.setImageDrawable(drawable); + if (!b) { + imageView.setAlpha(0.F); + imageView.animate().alpha(1F).setDuration(500).start(); + } + return true; + } + }) + // “23”:设置模糊度(在0.0到25.0之间),默认”25";"4":图片缩放比例,默认“1”。 + .transforms(new BlurTransformation(context, 10, 1)) + .into(imageView); + } + + public static void loadImageWithBlurTransformationAndCorner(Context context, String url, + ImageView imageView) { + int defaultPx = context.getResources().getDimensionPixelOffset(R.dimen.common_cover_round_size); + loadImageWithBlurTransformationAndCorner(context, url, imageView, 25, defaultPx); + } + + /** + * @param blur 0-25 越大高斯效果越强 + * @param scale 值越大,图片越模糊 + */ + public static void loadImageWithBlur(Context context, String url, ImageView imageView, int blur, int scale) { + if (StringUtil.isEmpty(url)) { + return; + } + GlideApp.with(context) + .load(url) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new BlurTransformation(context, blur, scale)) + .into(imageView); + } + + public static void loadImageWithBlurTransformationAndCorner(Context context, String url, + ImageView imageView, int blurRadius, int cornerPx) { + if (StringUtil.isEmpty(url)) { + return; + } + StringBuffer sb = new StringBuffer(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/75/h/75"); + } + GlideApp.with(context.getApplicationContext()) + .load(url) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new CenterCrop(), + new BlurTransformation(context, blurRadius, 3), + new RoundedCorners(cornerPx) + ) + .into(imageView); + } + + public static void loadCircleImage(Context context, String url, ImageView imageView, int defaultRes) { + GlideApp.with(context.getApplicationContext()).load(url) + .transform(new CircleCrop()) + .placeholder(defaultRes) + .error(defaultRes) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, + Target target, boolean isFirstResource) { + imageView.setImageResource(defaultRes); + return true; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, + Target target, DataSource dataSource, boolean isFirstResource) { + imageView.setImageDrawable(resource); + return true; + } + }) + .into(imageView); + } + + public static void loadBackground(Context context, String url, int defaultRes, View view) { + GlideApp.with(context) + .asDrawable() + .load(url) + .error(defaultRes) + .placeholder(defaultRes) + .into(new SimpleTarget() { + @Override + public void onResourceReady(Drawable resource, Transition transition) { + view.setBackground(resource); + } + }); + } + + public static void loadSpecSizeCircleImage(Context context, String url, ImageView imageView, + int defaultRes, int width, int height) { + GlideApp.with(context.getApplicationContext()).load(url) + .transform(new CircleCrop()) + .override(width, height) + .centerCrop() + .placeholder(defaultRes) + .into(imageView); + } + + public static void loadRectImage(Context context, String url, ImageView imageView, int defaultRes, int cornerRadius) { + GlideApp.with(context.getApplicationContext()).load(url) + .dontAnimate() + .placeholder(defaultRes) + .transforms(new CenterCrop(), + new RoundedCorners(cornerRadius)) + .error(defaultRes) + .into(imageView); + } + + public static void loadImage(Context context, String url, ImageView imageView, int defaultRes) { + GlideApp.with(context.getApplicationContext()).load(url) + .dontAnimate() + .placeholder(defaultRes) + .error(defaultRes) + .into(imageView); + } + + public static void loadDefaultImage(Context context, ImageView imageView, int defaultRes) { + GlideApp.with(context.getApplicationContext()) + .load(defaultRes) + .placeholder(defaultRes) + .error(defaultRes) + .into(imageView); + } + + public static void loadImage(Context context, File file, ImageView imageView, int defaultRes) { + GlideApp.with(context.getApplicationContext()).load(file).dontAnimate().placeholder(defaultRes).into(imageView); + } + + public static void loadImage(Context context, File file, ImageView imageView) { + GlideApp.with(context.getApplicationContext()).load(file).dontAnimate().into(imageView); + } + + public static void loadImage(Context context, String url, ImageView imageView) { + GlideApp.with(context.getApplicationContext()).load(url).dontAnimate().into(imageView); + } + + public static void loadImage1(Context context, String url, ImageView imageView) { + GlideApp.with(context).load(url).optionalFitCenter().into(new SimpleTarget() { + @Override + public void onResourceReady(Drawable resource, Transition transition) { + imageView.setImageDrawable(resource); + } + }); + } + + + public static void clearMemory(Context context) { + if (SystemUtils.isMainThread()) { + Glide.get(context.getApplicationContext()).clearMemory(); + } + } + + public static void loadKtvRoundBackground(Context context, String url, ImageView imageView) { + GlideApp.with(context) + .load(url) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .transforms(new RoundedCorners(context.getResources().getDimensionPixelOffset(R.dimen.common_cover_round_size))) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(imageView); + } + public static void loadImageWithPlaceholder(Context context, String url, ImageView imageView) { + GlideApp.with(context) + .load(url) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(imageView); + } + + /** + * 下载图片 + * + * @param context + * @param url + * @return 返回一个图片 + */ + public static Single loadDrawable(Context context, String url) { + return Single.create(emitter -> GlideApp.with(context).load(url) + + .into(new SimpleTarget() { + + @Override + public void onResourceReady(Drawable resource, Transition transition) { + emitter.onSuccess(resource); + } + + @Override + public void onLoadCleared(@Nullable Drawable placeholder) { + super.onLoadCleared(placeholder); + emitter.onError(new Throwable("onLoadCleared")); + } + + @Override + public void onLoadFailed(@Nullable Drawable errorDrawable) { + super.onLoadFailed(errorDrawable); + emitter.onError(new Throwable("onLoadCleared")); + } + + })); + } + + public static String getCustomSizeUrl(String url, int customSize) { + if (TextUtils.isEmpty(url)) { + return ""; + } + StringBuilder sb = new StringBuilder(url); + if (url.contains(ACCESS_URL)) { + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + sb.append("|imageView2/1/w/").append(customSize).append("/h/").append(customSize); + } + return sb.toString(); + } + + public static String getAvatarSizeUrl(String url) { + return getCustomSizeUrl(url, 150); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtilsV2.java b/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtilsV2.java new file mode 100644 index 000000000..4210342c2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/ImageLoadUtilsV2.java @@ -0,0 +1,171 @@ +package com.yizhuan.erban.ui.utils; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.widget.ImageView; + +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestOptions; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.netease.nim.uikit.support.glide.GlideRequest; +import com.netease.nim.uikit.support.glide.GlideRequests; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * create by lvzebiao @2019/7/26 + * {@link ImageLoadUtils 写的有点乱,添加V2,对Context进行判断} + */ +public class ImageLoadUtilsV2 { + + private static final String PIC_PROCESSING = "?imageslim"; + + private static int small_avatar_size = 100; + + public static void init(Context context) { + small_avatar_size = UIUtil.dip2px(context, 50); + } + + public static void loadAvatar(ImageView imageView, String url) { + loadImage(imageView, url, small_avatar_size, true, false); + } + + public static void loadAvatar(ImageView imageView, String url, boolean isDontAnim) { + loadImage(imageView, url, small_avatar_size, true, isDontAnim); + } + + public static void loadImage(ImageView imageView, String url, int size) { + loadImage(imageView, url, size, false, false); + } + + public static void loadImage(ImageView imageView, String url) { + loadImage(imageView, url, false); + } + + public static void loadImage(ImageView imageView, String url, boolean isDontAnim) { + loadImage(imageView, url, -1, false, isDontAnim); + } + + public static void loadImage(ImageView imageView, String url, boolean isDontAnim, int roundDp) { + loadImage(imageView, url, isDontAnim, roundDp, null); + } + + public static void loadImage(ImageView imageView, String url, boolean isDontAnim, int roundDp, + RequestOptions option) { + if (imageView == null) { + return; + } + loadImage(imageView.getContext(), imageView, url, -1, false, + R.drawable.default_cover, R.drawable.default_cover, isDontAnim, option, + new CenterCrop(), new RoundedCorners(UIUtil.dip2px(imageView.getContext(), roundDp))); + } + + public static void loadImage(ImageView imageView, String url, + int size, boolean isSquare, boolean isDontAnim) { + loadImage(imageView, url, size, isSquare, R.drawable.default_cover, R.drawable.default_cover, + isDontAnim, null); + } + + public static void loadImage(ImageView imageView, String url, + int size, boolean isSquare, + int errorId, int placeholderId, + boolean isDontAnim) { + loadImage(imageView, url, size, isSquare, errorId, placeholderId, + isDontAnim, null); + } + + public static void loadImage(ImageView imageView, String url, + int size, boolean isSquare, + int errorId, int placeholderId, + boolean isDontAnim, RequestOptions option, + BitmapTransformation... transformations) { + if (imageView == null) { + return; + } + loadImage(imageView.getContext(), imageView, url, size, isSquare, errorId, placeholderId, + isDontAnim, option, transformations); + } + + /** + * + */ + public static void loadImage(Context context, ImageView imageView, String url, + int size, boolean isSquare, + int errorId, int placeholderId, + boolean isDontAnim, RequestOptions option, + BitmapTransformation... transformations) { + if (imageView == null) { + return; + } + if (context == null) { + imageView.setImageResource(placeholderId); + return; + } + if (isGlideDestroyActivity(context)) { + imageView.setImageResource(placeholderId); + return; + } + if (size > 0) { + url = getSizeUrl(url, isSquare, size); + } + GlideRequest requests = GlideApp.with(context).load(url); + if (transformations != null && transformations.length > 0) { + requests = requests.transforms(transformations); + } + if (option != null) { + requests = requests.apply(option); + } + if (isDontAnim) { + requests = requests.dontAnimate(); + } + requests.placeholder(placeholderId) + .error(errorId) + .into(imageView); + + } + + /** + * + * @param url - + * @param customSize 七牛云返回的尺寸 + * @param isSquare ture的话,返回一个正方形尺寸,一般用于头像 + * false的话,指定宽度,高度自适应 + * @return - + */ + public static String getSizeUrl(String url, boolean isSquare, int customSize) { + if (TextUtils.isEmpty(url)) { + return ""; + } + try { + if (!url.startsWith("http")) { + return url; + } + StringBuilder sb = new StringBuilder(url); + if (!url.contains("?")) { + sb.append(PIC_PROCESSING); + } + if (isSquare) { + sb.append("|imageView2/1/w/").append(customSize).append("/h/").append(customSize); + } else { + sb.append("|imageView2/2/w/").append(customSize); + } + return sb.toString(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return url; + } + + public static String getSizeUrl(String url, int customSize) { + return getSizeUrl(url, false, customSize); + } + + private static boolean isGlideDestroyActivity(Context context) { + return context instanceof Activity && ((Activity) context).isDestroyed(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/SurfaceViewAnimation.java b/app/src/main/java/com/yizhuan/erban/ui/utils/SurfaceViewAnimation.java new file mode 100644 index 000000000..006c447c1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/SurfaceViewAnimation.java @@ -0,0 +1,505 @@ +package com.yizhuan.erban.ui.utils; + +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.support.annotation.IntDef; +import android.support.annotation.IntRange; +import android.support.annotation.NonNull; +import android.util.Log; +import android.util.SparseArray; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by yuyashuai on 2016/11/28 0028. + * use SurfaceView play Frame Animation + */ + +public final class SurfaceViewAnimation { + + + private final SparseArray mBitmapCache; + private SurfaceView mSurfaceView; + private SurfaceHolder mSurfaceHolder; + private List mPathList; + private MyCallBack mCallBack; + private int mode = MODE_INFINITE; + private boolean isOnDestory = false; + /** + * 是否从asset中读取资源 + */ + private boolean isAssetResource = false; + private AssetManager mAssetManager; + private final String TAG = "SurfaceViewAnimation"; + /** + * total frames. + */ + private int mTotalCount; + + /** + * handler of the thread that in charge of loading bitmap. + */ + private Handler mDecodeHandler; + + /** + * time interval between two frames. + */ + private int mFrameInterval = 100; + /** + * number of frames resides in memory. + */ + private int mCacheCount = 5; + + /** + * callback of animation state. + */ + private AnimationStateListener mAnimationStateListener; + + /** + * start animation command. + */ + private final int CMD_START_ANIMATION = -1; + + /** + * stop animation command. + */ + private final int CMD_STOP_ANIMATION = -2; + + /** + * Repeat the animation once. + */ + public static final int MODE_ONCE = 1; + /** + * Repeat the animation indefinitely. + */ + public static final int MODE_INFINITE = 2; + + private SurfaceViewAnimation() { + mBitmapCache = new SparseArray<>(); + } + + @IntDef({MODE_INFINITE, MODE_ONCE}) + @Retention(RetentionPolicy.SOURCE) + public @interface RepeatMode { + } + + public static class Builder { + + private final String TAG = "SurfaceViewAnimation"; + + private SurfaceViewAnimation mAnimation; + + public Builder(@NonNull SurfaceView surfaceView, @NonNull List pathList) { + mAnimation = new SurfaceViewAnimation(); + mAnimation.init(surfaceView, pathList); + } + + /** + * @param surfaceView + * @param assetPath asset resource path, must be a directory + */ + public Builder(@NonNull SurfaceView surfaceView, @NonNull String assetPath) { + AssetManager assetManager = surfaceView.getContext().getAssets(); + try { + String assetFiles[] = assetManager.list(assetPath); + if (assetFiles.length == 0) { + Log.e(TAG, "no file in this asset directory"); + return; + } + //转换真实路径 + for(int i=0;i mAssertList = Arrays.asList(assetFiles); + mAnimation = new SurfaceViewAnimation(); + mAnimation.isAssetResource = true; + mAnimation.setAssetManager(assetManager); + mAnimation.init(surfaceView, mAssertList); + } catch (IOException e) { + Log.e(TAG, e.getMessage()); + e.printStackTrace(); + } + } + + /** + * @param surfaceView + * @param file must be a directory + */ + public Builder(@NonNull SurfaceView surfaceView, @NonNull File file) { + List list = new ArrayList<>(); + if (file != null) { + if (file.exists() && file.isDirectory()) { + File[] files = file.listFiles(); + for (File mFrameFile : files) { + list.add(mFrameFile.getAbsolutePath()); + } + } else if (!file.exists()) { + Log.e(TAG, "file doesn't exists"); + } else { + Log.e(TAG, "file isn't a directory"); + } + } else { + Log.e(TAG, "file is null"); + } + mAnimation = new SurfaceViewAnimation(); + mAnimation.init(surfaceView, list); + } + + + public Builder setFrameInterval(int timeMillisecond) { + mAnimation.setFrameInterval(timeMillisecond); + return this; + } + + public Builder setCacheCount(@IntRange(from = 1) int count) { + mAnimation.setCacheCount(count); + return this; + } + + public Builder setAnimationListener(AnimationStateListener listener) { + mAnimation.setAnimationStateListener(listener); + return this; + } + + public Builder setRepeatMode(@RepeatMode int mode) { + mAnimation.setRepeatMode(mode); + return this; + } + + public SurfaceViewAnimation build() { + return mAnimation; + } + + } + + private void init(SurfaceView surfaceView, List pathList) { + this.mSurfaceView = surfaceView; + this.mSurfaceHolder = surfaceView.getHolder(); + mCallBack = new MyCallBack(); + mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT); + mSurfaceView.setZOrderOnTop(true); + mSurfaceHolder.addCallback(mCallBack); + this.mPathList = pathList; + } + + + public void start() { + if (isOnDestory) { + return; + } + + if (mCallBack.isDrawing) { + return; + //stopAnimation(); + } + if (mPathList == null) { + throw new NullPointerException("pathList can not be null."); + } + if (mPathList.size() == 0) { + return; + } + //从文件中读取 + if(!isAssetResource) + { + File file = new File(mPathList.get(0)); + if (!file.exists()) { + return; + } + } + mTotalCount = mPathList.size(); + startDecodeThread(); + } + + private void setAssetManager(AssetManager assetManager) { + this.mAssetManager = assetManager; + } + + private void setFrameInterval(int time) { + this.mFrameInterval = time; + } + + public void stop() { + if(!isDrawing()) return; + mCallBack.stopAnim(); + } + + private void setCacheCount(int count) { + mCacheCount = count; + } + + private void setRepeatMode(@RepeatMode int mode) { + this.mode = mode; + } + + public boolean isDrawing() { + return mCallBack.isDrawing; + } + + private void setAnimationStateListener(AnimationStateListener animationStateListener) { + this.mAnimationStateListener = animationStateListener; + } + + public interface AnimationStateListener { + void onStart(); + + void onFinish(); + } + + private class MyCallBack implements SurfaceHolder.Callback { + private Canvas mCanvas; + private Bitmap mCurrentBitmap; + private int position = 0; + public boolean isDrawing = false; + private Thread drawThread; + private Rect rect = new Rect(); + + @Override + public void surfaceCreated(SurfaceHolder holder) { + isOnDestory = false; + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + rect.set(0, 0, width, height); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + isOnDestory = true; + stop(); + } + + /** + * 绘制 + */ + private void drawBitmap() { + + //当循环播放时,获取真实的position + if (mode == MODE_INFINITE && position >= mTotalCount) { + position = position % mTotalCount; + } + + if (position >= mTotalCount) { + isDrawing = false; + mDecodeHandler.sendEmptyMessage(-2); + //clear surfaceView + clearSurface(); + return; + } + if (mBitmapCache.get(position, null) == null) { + mCanvas = mSurfaceHolder.lockCanvas(); + if (mCanvas == null) { + return; + } + //clear surfaceView + clearSurface(); + return; + } + mCurrentBitmap = mBitmapCache.get(position); + mDecodeHandler.sendEmptyMessage(position); + mCanvas = mSurfaceHolder.lockCanvas(rect); + if (mCanvas == null) { + return; + } + mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + mCanvas.drawBitmap(mCurrentBitmap, null, rect, null); + mSurfaceHolder.unlockCanvasAndPost(mCanvas); + mCurrentBitmap.recycle(); + position++; + } + + private void clearSurface() { + mCanvas = mSurfaceHolder.lockCanvas(); + //clear surfaceView + if (mCanvas != null) { + mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + mSurfaceHolder.unlockCanvasAndPost(mCanvas); + } + } + + private void startAnim() { + if (isOnDestory) { + return; + } + + if (mAnimationStateListener != null) { + mAnimationStateListener.onStart(); + } + isDrawing = true; + position = 0; + + //绘制线程 + drawThread = new Thread() { + @Override + public void run() { + super.run(); + while (isDrawing) { + try { + long now = System.currentTimeMillis(); +// drawBitmap(); + if (mode == MODE_INFINITE && position >= mTotalCount) { + position = position % mTotalCount; + } + + if (position >= mTotalCount) { + isDrawing = false; + mDecodeHandler.sendEmptyMessage(-2); + //clear surfaceView + clearSurface(); + return; + } + if (mBitmapCache.get(position, null) == null) { + mCanvas = mSurfaceHolder.lockCanvas(); + if (mCanvas == null) { + return; + } + //clear surfaceView + clearSurface(); + return; + } + mCurrentBitmap = mBitmapCache.get(position); + mDecodeHandler.sendEmptyMessage(position); + mCanvas = mSurfaceHolder.lockCanvas(rect); + if (mCanvas == null) { + return; + } + mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + mCanvas.drawBitmap(mCurrentBitmap, null, rect, null); + mSurfaceHolder.unlockCanvasAndPost(mCanvas); + mCurrentBitmap.recycle(); + position++; + //控制两帧之间的间隔 + sleep(mFrameInterval - (System.currentTimeMillis() - now) > 0 ? mFrameInterval - (System.currentTimeMillis() - now) : 0); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } +// finally { +// if (mCanvas != null) { +// mSurfaceHolder.unlockCanvasAndPost(mCanvas); +// } +// } + } + } + }; + drawThread.start(); + } + + private void stopAnim() { + isDrawing = false; + position = 0; + mBitmapCache.clear(); + clearSurface(); + //mPathList.clear(); + if(mDecodeHandler!=null) + { + mDecodeHandler.sendEmptyMessage(CMD_STOP_ANIMATION); + } + if(drawThread!=null) + { + drawThread.interrupt(); + } + if (mAnimationStateListener != null) { + mAnimationStateListener.onFinish(); + } + + } + } + + //decode线程 + private void startDecodeThread() { + new Thread() { + @Override + public void run() { + super.run(); + Looper.prepare(); + + mDecodeHandler = new Handler(Looper.myLooper()) { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == CMD_STOP_ANIMATION) { + decodeBitmap(CMD_STOP_ANIMATION); + getLooper().quit(); + return; + } + decodeBitmap(msg.what); + } + }; + decodeBitmap(CMD_START_ANIMATION); + Looper.loop(); + } + }.start(); + } + + /** + * 根据不同指令 进行不同操作 + * + * @param position + */ + private void decodeBitmap(int position) { + if (position == CMD_START_ANIMATION) { + for (int i = 0; i < mCacheCount; i++) { + if (mPathList.size() <= i) break; + mBitmapCache.put(i, decodeBitmapReal(mPathList.get(i))); + } + mCallBack.startAnim(); + } else if (position == CMD_STOP_ANIMATION) { + mCallBack.stopAnim(); + } else if (mode == MODE_ONCE) { + if (position + mCacheCount <= mTotalCount - 1) { + mBitmapCache.remove(position); + mBitmapCache.put(position + mCacheCount, decodeBitmapReal(mPathList.get(position + mCacheCount))); + } + } else if (mode == MODE_INFINITE) { + if (position + mCacheCount > mTotalCount - 1) { + mBitmapCache.remove(position); + mBitmapCache.put((position + mCacheCount) % mTotalCount, decodeBitmapReal(mPathList.get((position + mCacheCount) % mTotalCount))); + } else { + mBitmapCache.remove(position); + mBitmapCache.put(position + mCacheCount, decodeBitmapReal(mPathList.get(position + mCacheCount))); + } + } + } + + /** + * 根据不同的情况,选择不同的加载方式 + * @param path + * @return + */ + private Bitmap decodeBitmapReal(String path) + { + if(isAssetResource) + { + try { + return BitmapFactory.decodeStream(mAssetManager.open(path)); + } catch (IOException e) { + stop(); + Log.e(TAG,"IOException, animation stop"); + Log.e(TAG,e.getMessage()); + e.printStackTrace(); + } + }else + { + return BitmapFactory.decodeFile(path); + } + return null; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/sys/InstallUtil.java b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/InstallUtil.java new file mode 100644 index 000000000..49d00ad50 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/InstallUtil.java @@ -0,0 +1,116 @@ +package com.yizhuan.erban.ui.utils.sys; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.net.Uri; +import android.text.TextUtils; + +import com.netease.nim.uikit.api.NimUIKit; + +import java.io.File; + +public class InstallUtil { + private static final String TAG = "InstallUtil"; + + private static int versionCode; + + private static String versionName; + + /** + * 是否已安装app + * + * @param context + * @param packageName + * @return + */ + public static boolean isAppInstalled(Context context, String packageName) { + try { + if (TextUtils.isEmpty(packageName)) + return false; + return context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_ACTIVITIES) != null; + } catch (NameNotFoundException localNameNotFoundException) { + return false; + } + } + + /** + * 打开app + * + * @param packageName + * @param context + */ + public static void openApp(Context context, String packageName) { + PackageManager packageManager = context.getPackageManager(); + Intent intent = packageManager.getLaunchIntentForPackage(packageName); + if (intent != null) + context.startActivity(intent); + } + + /** + * 某个app的版本号,未安装时返回null + */ + public static final String getVersionName(Context context, String packageName) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0); + if (pi != null) { + return pi.versionName; + } else { + return null; + } + } catch (NameNotFoundException e) { + return null; + } + } + + public static final int getVersionCode(Context context) { + if (versionCode == 0) { + loadVersionInfo(context); + } + + return versionCode; + } + + /** + * 易信版本号 + */ + public static final String getVersionName(Context context) { + if (TextUtils.isEmpty(versionName)) { + loadVersionInfo(context); + } + + return versionName; + } + + private static final void loadVersionInfo(Context context) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + if (pi != null) { + versionCode = pi.versionCode; + versionName = pi.versionName; + } + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + } + + /** + * 安装apk文件 + */ + public static void installApk(String filepath) { + NimUIKit.getContext().startActivity(getInstallApkIntent(filepath)); + } + + /** + * 安装apk文件 + */ + public static Intent getInstallApkIntent(String filepath) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + File file = new File(filepath); + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + return intent; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SysInfoUtil.java b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SysInfoUtil.java new file mode 100644 index 000000000..0ef912641 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SysInfoUtil.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.ui.utils.sys; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningTaskInfo; +import android.content.Context; +import android.os.Build; +import android.os.PowerManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.List; + +public class SysInfoUtil { + public static final String getOsInfo() { + return Build.VERSION.RELEASE; + } + + public static final String getPhoneModelWithManufacturer() { + return Build.MANUFACTURER + " " + Build.MODEL; + } + + public static final String getPhoneMode() { + return Build.MODEL; + } + + public static final boolean isAppOnForeground(Context context) { + ActivityManager manager = (ActivityManager) context + .getApplicationContext().getSystemService( + Context.ACTIVITY_SERVICE); + String packageName = context.getApplicationContext().getPackageName(); + List list = manager + .getRunningAppProcesses(); + if (list == null) + return false; + boolean ret = false; + Iterator it = list.iterator(); + while (it.hasNext()) { + ActivityManager.RunningAppProcessInfo appInfo = it.next(); + if (appInfo.processName.equals(packageName) + && appInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + ret = true; + break; + } + } + return ret; + } + + public static final boolean isScreenOn(Context context) { + PowerManager powerManager = (PowerManager) context + .getSystemService(Context.POWER_SERVICE); + return powerManager.isScreenOn(); + } + + public static boolean stackResumed(Context context) { + ActivityManager manager = (ActivityManager) context + .getApplicationContext().getSystemService( + Context.ACTIVITY_SERVICE); + String packageName = context.getApplicationContext().getPackageName(); + List recentTaskInfos = manager.getRunningTasks(1); + if (recentTaskInfos != null && recentTaskInfos.size() > 0) { + RunningTaskInfo taskInfo = recentTaskInfos.get(0); + if (taskInfo.baseActivity.getPackageName().equals(packageName) && taskInfo.numActivities > 1) { + return true; + } + } + + return false; + } + + public static final boolean mayOnEmulator(Context context) { + if (mayOnEmulatorViaBuild()) { + return true; + } + + if (mayOnEmulatorViaTelephonyDeviceId(context)) { + return true; + } + + if (mayOnEmulatorViaQEMU(context)) { + return true; + } + + return false; + } + + private static final boolean mayOnEmulatorViaBuild() { + /** + * ro.product.model likes sdk + */ + if (!TextUtils.isEmpty(Build.MODEL) && Build.MODEL.toLowerCase().contains("sdk")) { + return true; + } + + /** + * ro.product.manufacturer likes unknown + */ + if (!TextUtils.isEmpty(Build.MANUFACTURER) && Build.MANUFACTURER.toLowerCase().contains("unknown")) { + return true; + } + + /** + * ro.product.device likes generic + */ + if (!TextUtils.isEmpty(Build.DEVICE) && Build.DEVICE.toLowerCase().contains("generic")) { + return true; + } + + return false; + } + + private static final boolean mayOnEmulatorViaTelephonyDeviceId(Context context) { + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (tm == null) { + return false; + } + + String deviceId = tm.getDeviceId(); + if (TextUtils.isEmpty(deviceId)) { + return false; + } + + /** + * device id of telephony likes '0*' + */ + for (int i = 0; i < deviceId.length(); i++) { + if (deviceId.charAt(i) != '0') { + return false; + } + } + + return true; + } + + private static final boolean mayOnEmulatorViaQEMU(Context context) { + String qemu = getProp(context, "ro.kernel.qemu"); + return "1".equals(qemu); + } + + private static final String getProp(Context context, String property) { + try { + ClassLoader cl = context.getClassLoader(); + Class SystemProperties = cl.loadClass("android.os.SystemProperties"); + Method method = SystemProperties.getMethod("get", String.class); + Object[] params = new Object[1]; + params[0] = property; + return (String)method.invoke(SystemProperties, params); + } catch (Exception e) { + return null; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SystemUtil.java b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SystemUtil.java new file mode 100644 index 000000000..aef5e92fe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/utils/sys/SystemUtil.java @@ -0,0 +1,46 @@ +package com.yizhuan.erban.ui.utils.sys; + +import android.app.ActivityManager; +import android.content.Context; +import android.text.TextUtils; + +/** + * 系统工具箱 + */ +public class SystemUtil { + + /** + * 获取当前进程名 + * @param context + * @return 进程名 + */ + public static final String getProcessName(Context context) { + String processName = null; + + // ActivityManager + ActivityManager am = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)); + + while (true) { + for (ActivityManager.RunningAppProcessInfo info : am.getRunningAppProcesses()) { + if (info.pid == android.os.Process.myPid()) { + processName = info.processName; + + break; + } + } + + // go home + if (!TextUtils.isEmpty(processName)) { + return processName; + } + + // take a rest and again + try { + Thread.sleep(100L); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/ExchangeGoldActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/ExchangeGoldActivity.java new file mode 100644 index 000000000..4a5fab0b3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/ExchangeGoldActivity.java @@ -0,0 +1,229 @@ +package com.yizhuan.erban.ui.wallet; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.widget.password.PassWordFragment; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +/** + * @author chenran + * @date 2017/10/2 + */ + +public class ExchangeGoldActivity extends BaseActivity { + private TextView jewNumber; + private TextView goldNumber; + private EditText exchangeJewNumber; + private TextView exchangeGoldNumber; + // private TextView tvExchangeHammarNum; + private Button confirm; + private WalletInfo walletInfo; + private TextView exchangeGoldTips; + private TextView tvInputTip; + + public static void start(Context context) { + if (context == null) return; + Intent intent = new Intent(context, ExchangeGoldActivity.class); + context.startActivity(intent); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_exchange_gold); + initTitleBar("金币兑换"); + walletInfo = PayModel.get().getCurrentWalletInfo(); + initView(); + updateView(); + } + + private void initView() { + tvInputTip = (TextView) findViewById(R.id.tv_input_tip); + jewNumber = (TextView) findViewById(R.id.gew_number); + goldNumber = (TextView) findViewById(R.id.gold_number); + exchangeJewNumber = (EditText) findViewById(R.id.gew_exchange_number); + exchangeGoldNumber = (TextView) findViewById(R.id.gold_exchange_number); +// tvExchangeHammarNum = findViewById(R.id.tv_hammar_exchange_number); + confirm = (Button) findViewById(R.id.confirm_exchange); + exchangeGoldTips = (TextView) findViewById(R.id.tv_exchange_gold_tips); + String tips = getString(R.string.exchange_gold_tips, + String.valueOf(SharedPreferenceUtils.getExchangeGoldRate())); +// tips = tips.replaceAll("\\n", "
"); + exchangeGoldTips.setText(tips); + confirm.setOnClickListener(v -> { + String str = exchangeJewNumber.getText().toString(); + if (isNumeric(str)) { + if (StringUtil.isEmpty(str)) { + toast("请输入要兑换的钻石数量"); + return; + } + + int value = Integer.parseInt(str); + if (!isTenMultiple(value)) { + toast("兑换的钻石必须为10的整数倍"); + return; + } + if (walletInfo == null || value > walletInfo.getDiamondNum()) { + toast("钻石数量少于兑换数量"); + return; + } + PassWordFragment.newInstace(value, value / 1000 * 2).show(getSupportFragmentManager()); + } + }); + exchangeJewNumber.addTextChangedListener(textWatcher); + } + + private void updateView() { + setWalletNum(walletInfo); + } + + private void setWalletNum(WalletInfo walletNum) { + if (walletNum != null) { + long value = (long) (walletNum.getDiamondNum() - walletNum.getDiamondNum() % 10); + int result = (int) (value * SharedPreferenceUtils.getExchangeGoldRate()); + exchangeJewNumber.setHint(String.format("请输入兑换的钻石数量 (最多可兑换%1$s)", result + "")); + jewNumber.setText(getString(R.string.jewel_format, FormatUtils.formatBigDecimal(walletNum.getDiamondNum()))); + goldNumber.setText(getString(R.string.gold_format, FormatUtils.formatBigDecimal(walletNum.getGoldNum()))); + exchangeGoldNumber.setText("0金币"); +// tvExchangeHammarNum.setText("0锤子"); + changeResultNumStyle(); + PayModel.get().setCurrentWalletInfo(walletNum); + } + } + + private TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (exchangeJewNumber.getText().toString().equals("0")) { + exchangeJewNumber.setText(""); + } + boolean btnEnable = false; + String str = exchangeJewNumber.getText().toString(); + if (!StringUtil.isEmpty(str) && isNumeric(str)) { + Long value = Long.parseLong(str); + if (isTenMultiple(value)) { + int result = (int) (value * SharedPreferenceUtils.getExchangeGoldRate()); + exchangeGoldNumber.setText(result + "金币"); +// tvExchangeHammarNum.setText((result/1000*2) + "锤子"); + changeResultNumStyle(); + if (walletInfo != null && value <= walletInfo.getDiamondNum()) { + btnEnable = true; + } + tvInputTip.setVisibility(View.GONE); + exchangeJewNumber.setTextColor(getResources().getColor(R.color.text_tertiary)); + } else { + exchangeGoldNumber.setText("0金币"); +// tvExchangeHammarNum.setText("0锤子"); + changeResultNumStyle(); + tvInputTip.setVisibility(View.VISIBLE); + exchangeJewNumber.setTextColor(getResources().getColor(R.color.color_FF3852)); + } + } else { + exchangeGoldNumber.setText("0金币"); +// tvExchangeHammarNum.setText("0锤子"); + changeResultNumStyle(); + tvInputTip.setVisibility(View.GONE); + exchangeJewNumber.setTextColor(getResources().getColor(R.color.text_tertiary)); + } + if (btnEnable) { + confirm.setEnabled(true); + confirm.setTextColor(ContextCompat.getColor(ExchangeGoldActivity.this, R.color.color_333333)); + confirm.setBackground(getResources().getDrawable(R.drawable.shape_semi_round_gray_solid)); + } else { + confirm.setEnabled(false); + confirm.setTextColor(ContextCompat.getColor(ExchangeGoldActivity.this, R.color.color_B3B3B3)); + confirm.setBackground(getResources().getDrawable(R.drawable.shape_semi_round_grey_e5_solid)); + } + } + }; + + private boolean isTenMultiple(long number) { + long value = number % 10; + return value == 0; + } + + private boolean isNumeric(String str) { + for (int i = str.length(); --i >= 0; ) { + if (!Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } + + private void changeResultNumStyle() { +// if("0锤子".equals(tvExchangeHammarNum.getText().toString())){ +// tvExchangeHammarNum.setTextColor(getResources().getColor(R.color.text_color_secondary)); +// } else { +// tvExchangeHammarNum.setTextColor(getResources().getColor(R.color.text_color_primary)); +// } + if ("0金币".equals(exchangeGoldNumber.getText().toString())) { + exchangeGoldNumber.setTextColor(getResources().getColor(R.color.text_color_secondary)); + } else { + exchangeGoldNumber.setTextColor(getResources().getColor(R.color.text_color_primary)); + } + } + + public void onExchangeGold(WalletInfo walletInfo) { + getDialogManager().dismissDialog(); + toast("兑换成功"); + exchangeJewNumber.setText(""); + if (walletInfo == null) { + return; + } + this.walletInfo.setDiamondNum(walletInfo.getDiamondNum()); + setWalletNum(walletInfo); + } + + public void onExchangeGoldFail(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + public void commit(long value, int hammerNum, String pwd) { + getDialogManager().showProgressDialog(ExchangeGoldActivity.this, "请稍后..."); + PayModel.get().exchangeGold((int) value, hammerNum, DESAndBase64(pwd)) + .subscribe(new BeanObserver() { + @Override + public void onSuccess(WalletInfo info) { + onExchangeGold(info); + } + + @Override + public void onErrorMsg(String error) { + onExchangeGoldFail(error); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelActivity.java new file mode 100644 index 000000000..44c158ccd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelActivity.java @@ -0,0 +1,243 @@ +package com.yizhuan.erban.ui.wallet; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.StatusBarUtil; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.activities.BillGiftExpendActivity; +import com.yizhuan.erban.bills.activities.BillGiftInComeActivity; +import com.yizhuan.erban.bills.activities.BillGiftIncomeGroupActivity; +import com.yizhuan.erban.bills.activities.ChargeBillsActivity; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.withdraw.WithdrawActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.withdraw.bean.ExchangerInfo; +import com.yizhuan.xchat_android_core.withdraw.event.ExchangeInfoEvent; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class JewelActivity extends BaseActivity { + + TextView tvDiamondNum; + LinearLayout llGiftIncome; + LinearLayout llGiftRecord; +// TextView tvGiftExpend; + TextView tvJewelExchange; + TextView tvJewelTiXian; + boolean isRequest; + private final int BINDCODE = 100; + private final int BINDCODE_GOLD = 200; + private boolean isBindPhone; + + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_jewel); + EventBus.getDefault().register(this); + initTitleBar("礼物收入"); + initViews(); + initData(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(true); + mTitleBar.setTitleColor(getResources().getColor(R.color.color_333333)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setBackgroundColor(getResources().getColor(R.color.transparent)); + mTitleBar.setLeftClickListener(v -> finish()); + } + } + + private void initViews(){ + tvDiamondNum = findViewById(R.id.tv_diamon_num); + llGiftIncome = findViewById(R.id.ll_gift_income); + llGiftRecord = findViewById(R.id.ll_gift_record); +// tvGiftExpend = findViewById(R.id.tv_gift_expend); + tvJewelExchange = findViewById(R.id.tv_jewel_exchange); + tvJewelTiXian = findViewById(R.id.tv_jewel_tixian); + + llGiftIncome.setOnClickListener(v -> { +// startActivity(new Intent(JewelActivity.this, BillGiftInComeActivity.class)); +// startActivity(new Intent(JewelActivity.this, BillGiftIncomeGroupActivity.class)); + BillGiftIncomeGroupActivity.startActivity(JewelActivity.this, BillGiftIncomeGroupActivity.TYPE_BILL_INCOME); + }); + + llGiftRecord.setOnClickListener(v -> { + BillGiftIncomeGroupActivity.startActivity(JewelActivity.this, BillGiftIncomeGroupActivity.TYPE_BILL_OUTPUT); + }); +// tvGiftExpend.setOnClickListener(v -> { +//// startActivity(new Intent(JewelActivity.this, BillGiftExpendActivity.class)); +// BillGiftIncomeGroupActivity.startActivity(JewelActivity.this, BillGiftIncomeGroupActivity.TYPE_BILL_OUTPUT); +// }); + tvJewelExchange.setOnClickListener(v -> { + if (UserModel.get().getCacheLoginUserInfo() == null) { + return; + } + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() && UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()){ + startActivity(new Intent(JewelActivity.this, ExchangeGoldActivity.class)); + }else { + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() || isBindPhone){ + ModifyPwdActivity.start(JewelActivity.this,ModifyPwdActivity.FOGERT_PAY_PWD); + }else { + startActivityForResult(new Intent(JewelActivity.this, BinderPhoneActivity.class),BINDCODE_GOLD); + } + } + + StatisticManager.Instance().onEvent(context, + StatisticsProtocol.Event.EVENT_EXCHANGE_CLICK, + "我的礼物/我的金币 兑换金币", + null); + }); + tvJewelTiXian.setOnClickListener(v -> { + isRequest = true; + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onIsPhone(); + } + + @Override + public void onError(Throwable e) { + onIsphoneFail(e.getMessage()); + } + }); + tvJewelTiXian.setClickable(false); + + StatisticManager.Instance().onEvent(context, + StatisticsProtocol.Event.EVENT_ACCOUNT_WITHDRAW_CLICK, + "提现按钮", + null); + }); + } + + public void onIsPhone() { + if (UserModel.get().getCacheLoginUserInfo() == null) { + return; + } + tvJewelTiXian.setClickable(true); + if (!isRequest) { + return; + } + isRequest = false; + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() && UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()) { + startActivity(new Intent(this, WithdrawActivity.class)); + }else { + ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD); + } + // startActivity(new Intent(getContext(), WithdrawActivity.class)); + } + + public void onIsphoneFail(String error) { + tvJewelTiXian.setClickable(true); + if (!isRequest) { + return; + } + isRequest = false; + startActivityForResult(new Intent(this, BinderPhoneActivity.class), BINDCODE); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == BINDCODE && resultCode== Activity.RESULT_OK){ + startActivity(new Intent(this, WithdrawActivity.class)); + }else if (requestCode == BINDCODE_GOLD && resultCode== Activity.RESULT_OK){ + isBindPhone=true; + ModifyPwdActivity.start(this,ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRequestExchange(ExchangeInfoEvent event) { + ExchangerInfo exchangerInfo = event.getData(); + if (exchangerInfo != null) { + setDiamondNum(exchangerInfo.diamondNum); + } + } + + @SuppressLint("CheckResult") + public void initData() { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setDiamondNum(walletInfo.diamondNum); + } + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()) + .subscribe(info -> { + if (info != null) { + setDiamondNum(info.diamondNum); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setDiamondNum(walletInfo.diamondNum); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) + setDiamondNum(walletInfo.diamondNum); + } + + private void setDiamondNum(double diamondNum) { + tvDiamondNum.setText(FormatUtils.formatBigDecimal(diamondNum)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelFragment.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelFragment.java new file mode 100644 index 000000000..d9ba66e41 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/JewelFragment.java @@ -0,0 +1,186 @@ +package com.yizhuan.erban.ui.wallet; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.widget.Button; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.withdraw.WithdrawActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.withdraw.bean.ExchangerInfo; +import com.yizhuan.xchat_android_core.withdraw.event.ExchangeInfoEvent; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 我的钱包--钻石界面 + * + * @author Administrator + * @date 2017/7/3 + */ +public class JewelFragment extends BaseFragment { + TextView tvDiamondNum; + Button mButton; + Button mExchangeButton; + boolean isRequest; + private final int BINDCODE = 100; + private final int BINDCODE_GOLD=200; + private boolean isBindPhone; + + @Override + public int getRootLayoutId() { + return R.layout.wallet_fragment_jewel; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + tvDiamondNum = (TextView) mView.findViewById(R.id.tv_diamondNum); + mButton = (Button) mView.findViewById(R.id.wallet_jewel_tixian); + mExchangeButton = (Button) mView.findViewById(R.id.wallet_jewel_exchange); + } + + @Override + public void onSetListener() { + mButton.setOnClickListener(v -> { + isRequest = true; + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onIsPhone(); + } + + @Override + public void onError(Throwable e) { + onIsphoneFail(e.getMessage()); + } + }); + mButton.setClickable(false); + }); + mExchangeButton.setOnClickListener(v -> { + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() && UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()){ + startActivity(new Intent(getActivity(), ExchangeGoldActivity.class)); + }else { + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() || isBindPhone){ + ModifyPwdActivity.start(getActivity(),ModifyPwdActivity.FOGERT_PAY_PWD); + }else { + startActivityForResult(new Intent(getActivity(), BinderPhoneActivity.class),BINDCODE_GOLD); + } + } + // ExchangeGoldActivity.start(getContext()); + }); + } + + public void onIsPhone() { + mButton.setClickable(true); + if (!isRequest) { + return; + } + isRequest = false; + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() && UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()) { + startActivity(new Intent(getActivity(), WithdrawActivity.class)); + }else { + ModifyPwdActivity.start(getActivity(),ModifyPwdActivity.FOGERT_PAY_PWD); + } + // startActivity(new Intent(getContext(), WithdrawActivity.class)); + } + + public void onIsphoneFail(String error) { + mButton.setClickable(true); + if (!isRequest) { + return; + } + isRequest = false; + startActivityForResult(new Intent(getContext(), BinderPhoneActivity.class), BINDCODE); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == BINDCODE && resultCode== Activity.RESULT_OK){ + startActivity(new Intent(getActivity(), WithdrawActivity.class)); + }else if (requestCode == BINDCODE_GOLD && resultCode== Activity.RESULT_OK){ + isBindPhone=true; + ModifyPwdActivity.start(getActivity(),ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRequestExchange(ExchangeInfoEvent event) { + ExchangerInfo exchangerInfo = event.getData(); + if (exchangerInfo != null) { + setDiamondNum(exchangerInfo.diamondNum); + } + } + + @SuppressLint("CheckResult") + @Override + public void initiate() { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setDiamondNum(walletInfo.diamondNum); + } + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()) + .subscribe(info -> { + if (info != null) { + setDiamondNum(info.diamondNum); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + setDiamondNum(walletInfo.diamondNum); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) + setDiamondNum(walletInfo.diamondNum); + } + + private void setDiamondNum(double diamondNum) { + tvDiamondNum.setText(FormatUtils.formatBigDecimal(diamondNum)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagActivity.java new file mode 100644 index 000000000..ee42f2a92 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagActivity.java @@ -0,0 +1,272 @@ +package com.yizhuan.erban.ui.wallet; + +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.StatusBarUtil; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.activities.RedBagBillsActivity; +import com.yizhuan.erban.bills.activities.TotalBillsActivity; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.marqueeview.MarqueeView; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.redPacket.RedPacketModel; +import com.yizhuan.xchat_android_core.redPacket.bean.RedDrawListInfo; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfo; +import com.yizhuan.xchat_android_core.redPacket.event.GetRedInfoEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +public class RedBagActivity extends BaseActivity implements View.OnClickListener { + + private MarqueeView marqueeView; + private TextView redMoeny; + private TextView sharePeoples; + private TextView shareBonus; + private TextView redRank; + private TextView redRule; + private TextView redMethod; + private LinearLayout llSharePeople; + private LinearLayout llShareBonus; + private TextView tvWithdraw; + private boolean isRequest; + + private RedPacketInfo redPacketInfo; + + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_red_bag); + EventBus.getDefault().register(this); + initTitleBar("我的红包奖励"); + initViews(); + initData(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(true); + mTitleBar.setTitleColor(getResources().getColor(R.color.white)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left_white); + mTitleBar.setBackgroundColor(getResources().getColor(R.color.transparent)); + mTitleBar.setLeftClickListener(v -> finish()); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.white)); + mTitleBar.addAction(new TitleBar.TextAction("红包纪录") { + @Override + public void performAction(View view) { + startActivity(new Intent(RedBagActivity.this, RedBagBillsActivity.class)); + } + }); + } + + private void initViews(){ + marqueeView = findViewById(R.id.marqueeView); + redMoeny = findViewById(R.id.tv_red_money); + sharePeoples = findViewById(R.id.tv_share_count); + shareBonus = findViewById(R.id.tv_share); + + redRank = findViewById(R.id.tv_red_rank); + redRule = findViewById(R.id.tv_red_rule); + redMethod = findViewById(R.id.tv_red_method); + llSharePeople = findViewById(R.id.ll_people); + llShareBonus = findViewById(R.id.ll_share_bonus); + tvWithdraw = findViewById(R.id.tv_withdraw); + + redRank.setOnClickListener(this); + redRule.setOnClickListener(this); + redMethod.setOnClickListener(this); + llSharePeople.setOnClickListener(this); + llShareBonus.setOnClickListener(this); + tvWithdraw.setOnClickListener(this); + } + + private void initData(){ + loadData(); + } + + private void loadData() { + RedPacketModel.get().getRedPacketInfo().subscribe(); + RedPacketModel.get().getRedDrawList().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + showDefaultData(); + } + + @Override + public void onSuccess(List redDrawListInfos) { + onGetRedDrawList(redDrawListInfos); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetRedInfo(GetRedInfoEvent event) { + if (event.isFailed()) { + toast(event.getError()); + return; + } + redPacketInfo = event.getData(); + if (redPacketInfo != null) { + redMoeny.setText(String.valueOf(redPacketInfo.getPacketNum())); + sharePeoples.setText(String.valueOf(redPacketInfo.getRegisterCout() + "人")); + shareBonus.setText(String.valueOf(redPacketInfo.getChargeBonus() + "元")); + } + } + + + private void onGetRedDrawList(List redDrawListInfos) { + if (redDrawListInfos != null && redDrawListInfos.size() > 0) { + List info = new ArrayList<>(); + for (int i=0; i info = new ArrayList<>(); + info.add("article一分钟前提现了200"); + info.add("木马一分钟前提现了200"); + info.add("此乳胸险一分钟前提现了100"); + info.add("xiaoshihou一分钟前提现了100"); + info.add("夜袭寡妇一分钟前提现了200"); + info.add("玮哥一分钟前提现了200"); + info.add("xiaoSeSe一分钟前提现了400"); + info.add("一生懵逼一分钟前提现了600"); + info.add("小可爱一分钟前提现了100"); + info.add("ai人一分钟前提现了200"); + info.add("大叔一分钟前提现了400"); + info.add("小凳子一分钟前提现了800"); + info.add("小逍遥一分钟前提现了300"); + info.add("清新一分钟前提现了100"); + info.add("荔枝一分钟前提现了200"); + info.add("小明哥哥一分钟前提现了100"); + info.add("薇薇一分钟前提现了300"); + info.add("红高粱一分钟前提现了400"); + marqueeView.startWithList(info); + } + + @Override + public void onClick(View v) { + String url = null; + switch (v.getId()) { + case R.id.tv_red_rank: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/rankList.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.tv_red_rule: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/fight.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.tv_red_method: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/secret.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.ll_people: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/invitation.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.ll_share_bonus: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/revenue.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.tv_withdraw: +// if (redPacketInfo == null || redPacketInfo.getPacketNum() < 100) { +// toast("红包金额满100才可提现"); +// } else { + isRequest = true; + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onIsPhone(); + } + + @Override + public void onError(Throwable e) { + onIsphoneFail(e.getMessage()); + } + }); +// } + break; + } + if (!TextUtils.isEmpty(url)) + openWebView(url); + } + + private void openWebView(String url) { + if (TextUtils.isEmpty(url)) return; + Intent intent = new Intent(this, CommonWebViewActivity.class); + intent.putExtra("url", url); + startActivity(intent); + } + + public void onIsPhone() { + if (!isRequest) { + return; + } + isRequest = false; + if (UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()){ + startActivity(new Intent(this, RedPacketWithdrawActivity.class)); + }else { + ModifyPwdActivity.start(this,ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + public void onIsphoneFail(String error) { + if (!isRequest) { + return; + } + isRequest = false; + startActivity(new Intent(this, BinderPhoneActivity.class)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagFragment.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagFragment.java new file mode 100644 index 000000000..c0ef32f65 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedBagFragment.java @@ -0,0 +1,247 @@ +package com.yizhuan.erban.ui.wallet; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.FragmentEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseFragment; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.marqueeview.MarqueeView; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.redPacket.RedPacketModel; +import com.yizhuan.xchat_android_core.redPacket.bean.RedDrawListInfo; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfo; +import com.yizhuan.xchat_android_core.redPacket.event.GetRedInfoEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 我的钱包---红包 + * Created by ${Seven} on 2017/9/18. + */ +public class RedBagFragment extends BaseFragment implements View.OnClickListener { + private MarqueeView marqueeView; + private TextView redMoeny; + private TextView sharePeoples; + private TextView shareBonus; + private RelativeLayout redRank; + private RelativeLayout redRule; + private RelativeLayout redMethod; + private RelativeLayout rlySharePeople; + private RelativeLayout rlyShareBonus; + private ImageView unWithdraw; + private ImageView withdraw; + private boolean isRequest; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onFindViews() { + marqueeView = (MarqueeView) mView.findViewById(R.id.marqueeView); + redMoeny = (TextView) mView.findViewById(R.id.tv_red_money); + sharePeoples = (TextView) mView.findViewById(R.id.tv_share_count); + shareBonus = (TextView) mView.findViewById(R.id.tv_share); + + redRank = (RelativeLayout) mView.findViewById(R.id.rly_red_rank); + redRule = (RelativeLayout) mView.findViewById(R.id.rly_red_rule); + redMethod = (RelativeLayout) mView.findViewById(R.id.rly_red_method); + rlySharePeople = (RelativeLayout) mView.findViewById(R.id.rly_people); + rlyShareBonus = (RelativeLayout) mView.findViewById(R.id.rly_share_bonus); + unWithdraw = (ImageView) mView.findViewById(R.id.img_un_withdraw); + withdraw = (ImageView) mView.findViewById(R.id.img_withdraw); + + } + + @Override + public void onSetListener() { + redRank.setOnClickListener(this); + redRule.setOnClickListener(this); + redMethod.setOnClickListener(this); + rlySharePeople.setOnClickListener(this); + rlyShareBonus.setOnClickListener(this); + withdraw.setOnClickListener(this); + } + + @Override + public void initiate() { + loadData(); + } + + private void loadData() { + RedPacketModel.get().getRedPacketInfo().subscribe(); + RedPacketModel.get().getRedDrawList().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + showDefaultData(); + } + + @Override + public void onSuccess(List redDrawListInfos) { + onGetRedDrawList(redDrawListInfos); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetRedInfo(GetRedInfoEvent event) { + if (event.isFailed()) { + toast(event.getError()); + return; + } + RedPacketInfo redPacketInfo = event.getData(); + if (redPacketInfo != null) { + if (redPacketInfo.getPacketNum() >= 100) { + unWithdraw.setVisibility(View.GONE); + withdraw.setVisibility(View.VISIBLE); + } + redMoeny.setText(String.valueOf(redPacketInfo.getPacketNum())); + sharePeoples.setText(String.valueOf(redPacketInfo.getRegisterCout())); + shareBonus.setText(String.valueOf(redPacketInfo.getChargeBonus())); + } + } + + + private void onGetRedDrawList(List redDrawListInfos) { + if (redDrawListInfos != null && redDrawListInfos.size() > 0) { + List info = new ArrayList<>(); + for (int i=0; i info = new ArrayList<>(); + info.add("article一分钟前提现了200"); + info.add("木马一分钟前提现了200"); + info.add("此乳胸险一分钟前提现了100"); + info.add("xiaoshihou一分钟前提现了100"); + info.add("夜袭寡妇一分钟前提现了200"); + info.add("玮哥一分钟前提现了200"); + info.add("xiaoSeSe一分钟前提现了400"); + info.add("一生懵逼一分钟前提现了600"); + info.add("小可爱一分钟前提现了100"); + info.add("ai人一分钟前提现了200"); + info.add("大叔一分钟前提现了400"); + info.add("小凳子一分钟前提现了800"); + info.add("小逍遥一分钟前提现了300"); + info.add("清新一分钟前提现了100"); + info.add("荔枝一分钟前提现了200"); + info.add("小明哥哥一分钟前提现了100"); + info.add("薇薇一分钟前提现了300"); + info.add("红高粱一分钟前提现了400"); + marqueeView.startWithList(info); + } + + @Override + public int getRootLayoutId() { + return R.layout.wallet_fragment_redbag; + } + + + @Override + public void onClick(View v) { + String url = null; + switch (v.getId()) { + case R.id.rly_red_rank: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/rankList.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.rly_red_rule: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/fight.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.rly_red_method: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/secret.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.rly_people: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/invitation.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.rly_share_bonus: + url = UriProvider.IM_SERVER_URL + "/modules/bonus/revenue.html" + "?uid=" + AuthModel.get().getCurrentUid(); + break; + case R.id.img_withdraw: + isRequest = true; + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onIsPhone(); + } + + @Override + public void onError(Throwable e) { + onIsphoneFail(e.getMessage()); + } + }); + break; + } + if (!TextUtils.isEmpty(url)) + openWebView(url); + } + + private void openWebView(String url) { + if (TextUtils.isEmpty(url)) return; + Intent intent = new Intent(getContext(), CommonWebViewActivity.class); + intent.putExtra("url", url); + startActivity(intent); + } + + public void onIsPhone() { + if (!isRequest) { + return; + } + isRequest = false; + if (UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()){ + startActivity(new Intent(getActivity(), RedPacketWithdrawActivity.class)); + }else { + ModifyPwdActivity.start(getActivity(),ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + public void onIsphoneFail(String error) { + if (!isRequest) { + return; + } + isRequest = false; + startActivity(new Intent(getContext(), BinderPhoneActivity.class)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/RedPacketWithdrawActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedPacketWithdrawActivity.java new file mode 100644 index 000000000..a32d627ad --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/RedPacketWithdrawActivity.java @@ -0,0 +1,320 @@ +package com.yizhuan.erban.ui.wallet; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.wallet.adapter.WithdrawRedListAdapter; +import com.yizhuan.erban.ui.widget.password.PassWordFragment; +import com.yizhuan.erban.ui.withdraw.BinderAlipayActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.initial.bean.TaxInfo; +import com.yizhuan.xchat_android_core.redPacket.RedPacketModel; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfo; +import com.yizhuan.xchat_android_core.redPacket.bean.WithdrawRedListInfo; +import com.yizhuan.xchat_android_core.redPacket.bean.WithdrawRedSucceedInfo; +import com.yizhuan.xchat_android_core.redPacket.event.GetRedInfoEvent; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; +import com.yizhuan.xchat_android_core.withdraw.bean.RefreshInfo; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrawInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 红包提现 + */ +public class RedPacketWithdrawActivity extends BaseActivity implements View.OnClickListener { + + private TextView redNum; + private RelativeLayout binder; + private RelativeLayout binderSucceed; + private TextView alipayAccount; + private TextView alipayName; + private RecyclerView recyclerView; + private Button btnWithdraw; + private Button unBtnWithdraw; + private WithdrawInfo mWithdrawInfo; + private WithdrawRedListAdapter mRedListAdapter; + private WithdrawRedListInfo mSelectRedInfo; + + private TextView tvTip; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_red_packet_withdraw); + EventBus.getDefault().register(this); + initTitleBar(getString(R.string.red_packet_withdraw)); + initView(); + initData(); + setListener(); + } + + private void initView() { + redNum = (TextView) findViewById(R.id.tv_red_num); + binder = (RelativeLayout) findViewById(R.id.rly_binder); + binderSucceed = (RelativeLayout) findViewById(R.id.rly_binder_succeed); + alipayAccount = (TextView) findViewById(R.id.tv_user_zhifubao); + alipayName = (TextView) findViewById(R.id.tv_user_zhifubao_name); + recyclerView = (RecyclerView) findViewById(R.id.recyclerView); + btnWithdraw = (Button) findViewById(R.id.btn_withdraw); + unBtnWithdraw = (Button) findViewById(R.id.btn_withdraw_un); + tvTip = (TextView) findViewById(R.id.tv_tip); + } + + + private void initData() { + recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); + mRedListAdapter = new WithdrawRedListAdapter(); + recyclerView.setAdapter(mRedListAdapter); + mRedListAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter baseQuickAdapter, View view, int position) { + List list = mRedListAdapter.getData(); + if (ListUtils.isListEmpty(list)) return; + mSelectRedInfo = list.get(position); + int size = list.size(); + for (int i = 0; i < size; i++) { + list.get(i).isSelected = position == i; + } + mRedListAdapter.notifyDataSetChanged(); + redPackWithdraw(); + } + }); + loadAlipayInfo(); + loadingData(); + loadingListData(); + + //显示提示 + TaxInfo texInfo = WithdrawModel.get().getTaxInfo(); + if (null != texInfo){ + tvTip.setVisibility(View.VISIBLE); + tvTip.setText(texInfo.getTips()); + }else { + tvTip.setVisibility(View.GONE); + } + } + + private void loadAlipayInfo() { + WithdrawModel.get().getWithdrawUserInfo( + AuthModel.get().getCurrentUid() + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(WithdrawInfo withdrawInfo) { + onGetWithdrawUserInfo(withdrawInfo); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + public void onGetWithdrawUserInfo(WithdrawInfo withdrawInfo) { + if (withdrawInfo != null) { + mWithdrawInfo = withdrawInfo; + if (TextUtils.isEmpty(withdrawInfo.alipayAccount) || withdrawInfo.alipayAccount.equals("null")) { + binder.setVisibility(View.VISIBLE); + binderSucceed.setVisibility(View.GONE); + } else { + binder.setVisibility(View.GONE); + binderSucceed.setVisibility(View.VISIBLE); + alipayAccount.setText(withdrawInfo.alipayAccount); + alipayName.setText(withdrawInfo.alipayAccountName); + } + } + } + + private void loadingListData() { + RedPacketModel.get().getRedList().subscribe(new BeanObserver>() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(List withdrawRedListInfos) { + onGetRedList(withdrawRedListInfos); + } + }); + } + + private void onGetRedList(List withdrawRedListInfos) { + if (!withdrawRedListInfos.isEmpty()) { + mRedListAdapter.setNewData(withdrawRedListInfos); + } + } + + private void loadingData() { + RedPacketModel.get().getRedPacketInfo().subscribe(); + } + + private RedPacketInfo redPacketInfos; + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetRedInfo(GetRedInfoEvent event) { + if (event.isFailed()) { + toast(event.getError()); + return; + } + RedPacketInfo redPacketInfo = event.getData(); + if (null != redPacketInfo) { + redPacketInfos = redPacketInfo; + redNum.setText(String.valueOf(redPacketInfo.getPacketNum())); + } + } + + private void setListener() { + binder.setOnClickListener(this); + binderSucceed.setOnClickListener(this); + } + + private Intent intent; + private Bundle mBundle; + + @Override + public void onClick(View v) { + switch (v.getId()) { + //未绑定支付宝时可点---绑定支付宝账号 + case R.id.rly_binder: + intent = new Intent(getApplicationContext(), BinderAlipayActivity.class); + mBundle = new Bundle(); + mBundle.putSerializable("withdrawInfo", mWithdrawInfo); + intent.putExtras(mBundle); + startActivity(intent); + break; + //绑定成功支付宝后可点---更改支付宝账号 + case R.id.rly_binder_succeed: + intent = new Intent(getApplicationContext(), BinderAlipayActivity.class); + mBundle = new Bundle(); + mBundle.putSerializable("withdrawInfo", mWithdrawInfo); + intent.putExtras(mBundle); + startActivity(intent); + break; + } + } + + //eventbus监听绑定支付宝页面是否绑定成功,然后刷新红包提现页面 + @Subscribe(threadMode = ThreadMode.MAIN) + public void refreshEvent(RefreshInfo refreshInfo) { + loadAlipayInfo(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + private void redPackWithdraw() { + if (mSelectRedInfo == null) { + toast("兑换失败"); + return; + } + if (isWithdraw()) { + btnWithdraw.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //有账号才能提现 + if (!isAlipayValid()) { + toast(R.string.bind_your_alipay); + return; + } + //发起兑换 + getDialogManager().showOkCancelDialog( + getString(R.string.withdraw_dialog_notice, + mSelectRedInfo.getPacketNum(), mSelectRedInfo.getPacketNum()), + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + getDialogManager().dismissDialog(); + } + + @Override + public void onOk() { + getDialogManager().dismissDialog(); + PassWordFragment.newInstace(0).show(getSupportFragmentManager()); + } + }); + } + }); + } + } + + public void commit(String pwd) { + RedPacketModel.get().getRedWithdraw( + AuthModel.get().getCurrentUid(), + mSelectRedInfo.getPacketId(), DESAndBase64(pwd)) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + toast(error); + } + + @Override + public void onSuccess(WithdrawRedSucceedInfo info) { + onGetWithdraw(info); + } + }); + + } + + public boolean isWithdraw() { + if (!(mWithdrawInfo != null && mWithdrawInfo.isNotBoundPhone)) { + if (mSelectRedInfo != null) { + //用户的钻石余额 > 选中金额的钻石数时 + if (redPacketInfos.getPacketNum() >= mSelectRedInfo.getPacketNum()) { + unBtnWithdraw.setVisibility(View.GONE); + btnWithdraw.setVisibility(View.VISIBLE); + return true; + } else { + unBtnWithdraw.setVisibility(View.VISIBLE); + btnWithdraw.setVisibility(View.GONE); + return true; + } + } + } else { + return false; + } + //如果选中position不为空的时候 + return false; + } + + private boolean isAlipayValid() { + return mWithdrawInfo != null && !TextUtils.isEmpty(mWithdrawInfo.alipayAccount); + } + + private void onGetWithdraw(WithdrawRedSucceedInfo succeedInfo) { + toast("兑换成功"); + if (null != succeedInfo) { + redNum.setText(String.valueOf(succeedInfo.getPacketNum())); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletActivity.java new file mode 100644 index 000000000..d2067a361 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletActivity.java @@ -0,0 +1,109 @@ +package com.yizhuan.erban.ui.wallet; + +import android.content.Context; +import android.content.Intent; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.view.View; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.databinding.ActivityWalletBinding; +import com.yizhuan.erban.home.adapter.CommonMagicIndicatorAdapter; +import com.yizhuan.erban.bills.activities.TotalBillsActivity; +import com.yizhuan.erban.ui.widget.magicindicator.MagicIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.ViewPagerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import java.util.ArrayList; +import java.util.List; + +/** + * 我的钱包页面 + * + * @author Administrator + * @date 2017/7/1 + */ + +@ActLayoutRes(R.layout.activity_wallet) +public class WalletActivity extends BaseBindingActivity implements CommonMagicIndicatorAdapter.OnItemSelectListener { + + private ArrayList fragmentArrayList; + private FragmentManager fragmentManager; + public Context context; + private int mPosition; + + public static void start(Context context, int position) { + Intent intent = new Intent(context, WalletActivity.class); + intent.putExtra(Constants.KEY_POSITION, position); + context.startActivity(intent); + } + + @Override + protected void init() { + initTitleBar(getString(R.string.menu_my_wallet)); + initFragment(); + initViewPager(); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = mBinding.titleBar; + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.back_font)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setLeftClickListener(v -> finish()); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("账单") { + @Override + public void performAction(View view) { + startActivity(new Intent(WalletActivity.this, TotalBillsActivity.class)); + } + }); + } + + + private void initViewPager() { + mBinding.vPager.setAdapter(new WalletFragmentPagerAdapter(fragmentManager, fragmentArrayList)); + initMagicIndicator2(); + mBinding.vPager.setOffscreenPageLimit(3); + + mPosition = getIntent().getIntExtra(Constants.KEY_POSITION, 0); + mBinding.vPager.setCurrentItem(mPosition); + } + + private void initMagicIndicator2() { + List tabInfoList = new ArrayList<>(3); + tabInfoList.add(new TabInfo(1, getString(R.string.gift_expend_gold))); + tabInfoList.add(new TabInfo(2, getString(R.string.gift_income_gold))); + tabInfoList.add(new TabInfo(3, getString(R.string.red_package))); + final MagicIndicator magicIndicator = (MagicIndicator) findViewById(R.id.magic_indicator2); + CommonNavigator commonNavigator = new CommonNavigator(this); + commonNavigator.setAdjustMode(true); + CommonMagicIndicatorAdapter walletAdapter = new CommonMagicIndicatorAdapter(this, tabInfoList, 0); + walletAdapter.setOnItemSelectListener(this); + commonNavigator.setAdapter(walletAdapter); + magicIndicator.setNavigator(commonNavigator); + ViewPagerHelper.bind(magicIndicator, mBinding.vPager); + } + + @Override + public void onItemSelect(int position) { + mBinding.vPager.setCurrentItem(position); + } + + private void initFragment() { + fragmentArrayList = new ArrayList<>(); + fragmentArrayList.add(new WalletGoldFragment()); + fragmentArrayList.add(new JewelFragment()); + fragmentArrayList.add(new RedBagFragment()); + fragmentManager = getSupportFragmentManager(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletFragmentPagerAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletFragmentPagerAdapter.java new file mode 100644 index 000000000..4983546fb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletFragmentPagerAdapter.java @@ -0,0 +1,35 @@ +package com.yizhuan.erban.ui.wallet; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.view.ViewGroup; + +import java.util.ArrayList; + + +class WalletFragmentPagerAdapter extends FragmentPagerAdapter { + private ArrayList fragmentsList; + + WalletFragmentPagerAdapter(FragmentManager fm, ArrayList fragmentsList) { + super(fm); + this.fragmentsList = fragmentsList; + } + + @Override + public Fragment getItem(int position) { + return fragmentsList.get(position); + } + + @Override + public int getCount() { + return fragmentsList.size(); + } + + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + super.destroyItem(container, position, object); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldActivity.java new file mode 100644 index 000000000..2bccb186e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldActivity.java @@ -0,0 +1,188 @@ +package com.yizhuan.erban.ui.wallet; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.View; + +import com.netease.nim.uikit.StatusBarUtil; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.ActivityWalletGoldBinding; +import com.yizhuan.erban.ui.login.BinderPhoneActivity; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.wallet.sendgold.SendGoldActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +@ActLayoutRes(R.layout.activity_wallet_gold) +public class WalletGoldActivity extends BaseBindingActivity { + + private final int BINDCODE_GOLD = 200; + private boolean isBindPhone; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + initTitleBar("我的金币"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void initTitleBar(String title) { + mTitleBar = mBinding.titleBar; + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(true); + mTitleBar.setTitleColor(getResources().getColor(R.color.color_333333)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setBackgroundColor(getResources().getColor(R.color.transparent)); + mTitleBar.setLeftClickListener(v -> finish()); + } + } + + @Override + protected void init() { + mBinding.btnWallGoldGive.setVisibility(View.GONE); + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + mBinding.setWalletInfo(walletInfo); + mBinding.executePendingBindings(); + } + loadDiamondNum(); + mBinding.setClick(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) + mBinding.setWalletInfo(walletInfo); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + mBinding.setWalletInfo(walletInfo); + mBinding.btnWallGoldGive.setVisibility( + walletInfo.isSendGold() ? View.VISIBLE : View.GONE); + } + } + + @SuppressLint("CheckResult") + private void loadDiamondNum() { + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()).subscribe(); + } + + @Override + public void onClick(View v) { + super.onClick(v); + switch (v.getId()) { + case R.id.btn_wall_gold_charge: + startActivity(new Intent(this, ChargeActivity.class)); + + StatisticManager.Instance().onEvent(context, + StatisticsProtocol.Event.EVENT_RECHARGE_CLICK, + "金币充值", + null); + break; + + case R.id.btn_wall_gold_give: + SendGoldActivity.start(context); + break; + + case R.id.iv_gold_question: + CommonWebViewActivity.start(WalletGoldActivity.this, UriProvider.IM_SERVER_URL + "modules/nobles/faq.html?quesIndex=4"); + break; + + case R.id.tv_goto_change_gold: + AuthModel.get().isBindPhone() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + onBindPhone(); + } + + @Override + public void onError(Throwable e) { + onNoBindPhone(e.getMessage()); + } + }); + + break; + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == BINDCODE_GOLD && resultCode == Activity.RESULT_OK) { + isBindPhone = true; + ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD); + } + + } + + public void onBindPhone() { + mBinding.btnWallGoldCharge.setEnabled(true); + if (UserModel.get().getCacheLoginUserInfo() == null) { + return; + } + if (UserModel.get().getCacheLoginUserInfo().isBindPhone() && UserModel.get().getCacheLoginUserInfo().isBindPaymentPwd()) { + ExchangeGoldActivity.start(WalletGoldActivity.this); + } else { + ModifyPwdActivity.start(this, ModifyPwdActivity.FOGERT_PAY_PWD); + } + } + + public void onNoBindPhone(String error) { + mBinding.btnWallGoldCharge.setEnabled(true); + startActivityForResult(new Intent(this, BinderPhoneActivity.class), BINDCODE_GOLD); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldFragment.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldFragment.java new file mode 100644 index 000000000..26eefc573 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/WalletGoldFragment.java @@ -0,0 +1,84 @@ +package com.yizhuan.erban.ui.wallet; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.FragmentWalletGoldBinding; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + + +/** + * 金币页面 + * + * @author Administrator + * @date 2017/7/3 + */ + +@ActLayoutRes(R.layout.fragment_wallet_gold) +public class WalletGoldFragment extends BaseBindingFragment { + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void initiate() { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + mBinding.setWalletInfo(walletInfo); + mBinding.executePendingBindings(); + } + loadDiamondNum(); + + mBinding.btnWallGoldCharge.setOnClickListener( + v -> startActivity(new Intent(getContext(), ChargeActivity.class))); + mBinding.ivWalletQuestion.setOnClickListener(v -> + CommonWebViewActivity.start(mContext, UriProvider.IM_SERVER_URL + "modules/nobles/faq.html?quesIndex=4")); + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) + mBinding.setWalletInfo(walletInfo); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo != null) { + mBinding.setWalletInfo(walletInfo); + } + } + + @SuppressLint("CheckResult") + private void loadDiamondNum() { + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawJewelAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawJewelAdapter.java new file mode 100644 index 000000000..55bd91fa2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawJewelAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.wallet.adapter; + +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrwaListInfo; + +/** + *

钻石提现界面

+ * Created by Administrator on 2017/11/21. + */ +public class WithdrawJewelAdapter extends BaseQuickAdapter { + public WithdrawJewelAdapter() { + super(R.layout.withdraw_item); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, WithdrwaListInfo withdrwaListInfo) { + if (withdrwaListInfo == null) return; + baseViewHolder.setText(R.id.tv_jewel, (int)withdrwaListInfo.diamondNum + "钻"); + baseViewHolder.setText(R.id.tv_money, "" + withdrwaListInfo.cashNum); + + LinearLayout ll_gold_charge = baseViewHolder.getView(R.id.ll_gold_charge); + TextView tv_jewel = baseViewHolder.getView(R.id.tv_jewel); + TextView tv_money = baseViewHolder.getView(R.id.tv_money); + ll_gold_charge.setSelected(withdrwaListInfo.isSelected); + if(withdrwaListInfo.isSelected){ + tv_jewel.setTextColor(mContext.getResources().getColor(R.color.appColor)); + tv_money.setTextColor(mContext.getResources().getColor(R.color.appColor)); + } else { + tv_jewel.setTextColor(mContext.getResources().getColor(R.color.text_color_secondary)); + tv_money.setTextColor(mContext.getResources().getColor(R.color.text_color_secondary)); + } +// baseViewHolder.setText(R.id.list_name, withdrwaListInfo.cashProdName); +// ImageView imageView = baseViewHolder.getView(R.id.select_withdraw); +// imageView.setSelected(withdrwaListInfo.isSelected); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawRedListAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawRedListAdapter.java new file mode 100644 index 000000000..e9522f6ae --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/adapter/WithdrawRedListAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.wallet.adapter; + +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.redPacket.bean.WithdrawRedListInfo; + +/** + *

红包提现展示列表

+ * Created by Administrator on 2017/11/20. + */ +public class WithdrawRedListAdapter extends BaseQuickAdapter { + public WithdrawRedListAdapter() { + super(R.layout.list_red_packet_item); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, WithdrawRedListInfo withdrawRedListInfo) { + if (withdrawRedListInfo == null) return; + baseViewHolder.setText(R.id.tv_money, "¥" + withdrawRedListInfo.getPacketNum()); + + LinearLayout ll_gold_charge = baseViewHolder.getView(R.id.ll_gold_charge); + TextView tv_money = baseViewHolder.getView(R.id.tv_money); + ll_gold_charge.setSelected(withdrawRedListInfo.isSelected); + if(withdrawRedListInfo.isSelected){ + tv_money.setTextColor(mContext.getResources().getColor(R.color.appColor)); + } else { + tv_money.setTextColor(mContext.getResources().getColor(R.color.text_color_secondary)); + } + /*baseViewHolder.setText(R.id.list_name, + mContext.getString(R.string.withdraw_prod_name, + withdrawRedListInfo.getPacketNum(), withdrawRedListInfo.getPacketNum()) + ); + ImageView selectWithdraw = baseViewHolder.getView(R.id.select_withdraw); + selectWithdraw.setSelected(withdrawRedListInfo.isSelected);*/ + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldActivity.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldActivity.java new file mode 100644 index 000000000..cf2501f42 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldActivity.java @@ -0,0 +1,329 @@ +package com.yizhuan.erban.ui.wallet.sendgold; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.bills.activities.ChargeBillsActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.TextWatcherSimple; +import com.yizhuan.erban.ui.widget.password.PassWordFragment; +import com.yizhuan.erban.ui.widget.password.PasswordEvent; +import com.yizhuan.erban.ui.widget.password.PasswordView; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.GridSpacingItemDecoration; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.pay.GoldGiveModel; +import com.yizhuan.xchat_android_core.pay.IGoldGiveModel; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.GiveInfo; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.GetWalletInfoEvent; +import com.yizhuan.xchat_android_core.pay.event.SendGoldSuccessEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.JavaUtil; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * create by lvzebiao @2019/12/1 + */ +public class SendGoldActivity extends BaseActivity { + + @BindView(R.id.tv_wall_gold_remain) + TextView tvWallGoldRemain; + @BindView(R.id.et_account) + EditText etAccount; + @BindView(R.id.tv_give_value) + TextView tvGiveValue; + @BindView(R.id.rv_gold) + RecyclerView rvGold; + @BindView(R.id.et_custom_input) + EditText etCustomInput; + @BindView(R.id.btn_give) + Button btnGive; + @BindView(R.id.tv_my_give_record) + TextView tvMyGiveRecord; + @BindView(R.id.sv_container) + ScrollView svContainer; + + private IGoldGiveModel model = new GoldGiveModel(); + + private SendGoldListAdpater adapter; + + private int sendGoldValue = 0; + + private UserInfo doneeInfo; + + public static void start(Context context) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + SingleToastUtil.showToast("用户信息为空,请重新登录"); + return; + } + if (!userInfo.isBindPhone() || !userInfo.isBindPaymentPwd()) { + SingleToastUtil.showToast("请去绑定手机/设置支付密码"); + return; + } + Intent intent = new Intent(context, SendGoldActivity.class); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_send_gold); + ButterKnife.bind(this); + initTitleBar(R.string.gold_give); + EventBus.getDefault().register(this); + //查询钱包 + PayModel.get().getWalletInfo(AuthModel.get().getCurrentUid()) + .subscribe(); + initRvGoldList(); + initView(); + //获取金币转赠列表 + model.getGiveItemList() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver>() { + @Override + public void accept(List giveInfos, String error) { + super.accept(giveInfos, error); + if (error != null) { + toast(error); + return; + } + for (int i = 0; i < giveInfos.size(); i++) { + giveInfos.get(i).setSelected(i == 0); + } + adapter.setNewData(giveInfos); + } + }); + + + } + + private void initRvGoldList() { + rvGold.setLayoutManager(new GridLayoutManager(context, 2)); + rvGold.addItemDecoration(new GridSpacingItemDecoration(context, 2, 15)); + adapter = new SendGoldListAdpater(); + rvGold.setAdapter(adapter); + + adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter a, View view, int position) { + etCustomInput.setText(""); + etCustomInput.clearFocus(); + adapter.selectItem(position); + updateViewStatus(); + } + }); + } + + private void initView() { + etAccount.addTextChangedListener(new TextWatcherSimple() { + @Override + public void afterTextChanged(Editable s) { + updateViewStatus(); + } + }); + etCustomInput.clearFocus(); + etCustomInput.addTextChangedListener(new TextWatcherSimple() { + @Override + public void afterTextChanged(Editable s) { + adapter.clearAllSelected(); + updateViewStatus(); + } + }); + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGetWalletInfo(GetWalletInfoEvent event) { + WalletInfo walletInfo = PayModel.get().getCurrentWalletInfo(); + if (walletInfo == null) { + return; + } + updateGoldRemain(walletInfo.chargeGoldNum); + } + + private void updateGoldRemain(double value) { + tvWallGoldRemain.setText(FormatUtils.formatBigDecimal(value)); + } + + private void updateViewStatus() { + if (TextUtils.isEmpty(etCustomInput.getText().toString())) { + etCustomInput.setBackgroundResource(R.drawable.shape_gold_input_false); + } else { + etCustomInput.setBackgroundResource(R.drawable.shape_gold_input_true); + } + if (TextUtils.isEmpty(etAccount.getText().toString())) { + btnGive.setEnabled(false); + return; + } + if (adapter.hasSelectedItem()) { + btnGive.setEnabled(true); + return; + } + if (!TextUtils.isEmpty(etCustomInput.getText().toString())) { + btnGive.setEnabled(true); + } else { + btnGive.setEnabled(false); + } + } + + + @OnClick({R.id.btn_give, R.id.tv_my_give_record}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.btn_give: + this.doneeInfo = null; + getDialogManager().showProgressDialog(context); + UserModel.get().getSimpleUser(etAccount.getText().toString()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(UserInfo info, String error) { + super.accept(info, error); + getDialogManager().dismissDialog(); + if (error != null) { + toast(error); + return; + } + doneeInfo = info; + sendGoldValue = getSendGoldValue(); + if (isValidSendValue()) { + handleConfirmSendGoldView(info); + } + } + }); + break; + case R.id.tv_my_give_record: + startActivity(new Intent(context, ChargeBillsActivity.class)); + break; + } + } + + + private void handleConfirmSendGoldView(UserInfo info) { + View confirmSendGoldView = View.inflate(context, R.layout.dialog_custom_confirm_send_gold, null); + ImageView ivAvatar = confirmSendGoldView.findViewById(R.id.iv_avatar); + TextView tvInfo = confirmSendGoldView.findViewById(R.id.tv_info); + TextView tvSendNumber = confirmSendGoldView.findViewById(R.id.tv_send_number); + + ImageLoadUtils.loadAvatar(info.getAvatar(), ivAvatar); + tvInfo.setText(getString(R.string.send_gold_confirm_info, RegexUtil.getPrintableString(info.getNick()), + String.valueOf(info.getErbanNo()))); + SpannableBuilder builder = new SpannableBuilder(); + builder.append("转赠") + .append(String.valueOf(sendGoldValue), new ForegroundColorSpan(getResources().getColor(R.color.color_FE4C62))) + .append("金币?"); + tvSendNumber.setText(builder.build()); + getDialogManager().showOkCancelCustomDialog(confirmSendGoldView, false, () -> { + hideIME(); + PassWordFragment.newInstance(PassWordFragment.TYPE_SEND_GOLD) + .show(getSupportFragmentManager()); + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onPasswordEvent(PasswordEvent event) { + if (TextUtils.isEmpty(event.getPassword())) { + toast("密码为空"); + return; + } + + if (event.getType() != PassWordFragment.TYPE_SEND_GOLD) { + return; + } + if (!isValidSendValue()) { + return; + } + if (doneeInfo == null) { + return; + } + getDialogManager().showProgressDialog(context, "", false, false, null); + model.giveGold(doneeInfo.getUid(), sendGoldValue, event.getPassword()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Integer integer, String error) { + super.accept(integer, error); + getDialogManager().dismissDialog(); + doneeInfo = null; + if (error != null) { + toast(error); + return; + } + toast("转赠成功"); + } + }); + } + + public int getSendGoldValue() { + int value; + String customInput = etCustomInput.getText().toString(); + if (!TextUtils.isEmpty(customInput)) { + value = JavaUtil.str2int(customInput); + } else { + value = adapter.getSelectItemValue(); + } + return value; + } + + private boolean isValidSendValue() { + if (sendGoldValue <= 0) { + toast("请输入有效金额"); + } + return sendGoldValue > 0; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSendGoldSuccessEvent(SendGoldSuccessEvent event) { + if (event.getData() == null) { + return; + } + updateGoldRemain(event.getData()); + } + + @Override + protected void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + @Override + public void finish() { + hideIME(); + super.finish(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldListAdpater.java b/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldListAdpater.java new file mode 100644 index 000000000..36e72ac60 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/wallet/sendgold/SendGoldListAdpater.java @@ -0,0 +1,80 @@ +package com.yizhuan.erban.ui.wallet.sendgold; + +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.pay.bean.GiveInfo; + +import java.util.List; + +/** + * create by lvzebiao @2019/12/1 + */ +public class SendGoldListAdpater extends BaseQuickAdapter { + + public SendGoldListAdpater() { + super(R.layout.item_give_gold_list); + } + + @Override + protected void convert(BaseViewHolder baseViewHolder, GiveInfo item) { + if (item == null) return; + + + ImageView iv_gold = baseViewHolder.getView(R.id.iv_gold); + TextView tv_money_gold = baseViewHolder.getView(R.id.tv_money_gold); + + tv_money_gold.setText(item.getGoldProdName()); + baseViewHolder.getView(R.id.ll_gold_charge).setSelected(item.isSelected()); + if (item.isSelected()) { + iv_gold.setImageResource(R.mipmap.ic_wallet_gold); + tv_money_gold.setTextColor(mContext.getResources().getColor(R.color.color_333333)); + } else { + iv_gold.setImageResource(R.mipmap.ic_wallet_gold_unchecked); + tv_money_gold.setTextColor(mContext.getResources().getColor(R.color.color_999999)); + } + } + + public boolean hasSelectedItem() { + List data = getData(); + for (GiveInfo info : data) { + if (info.isSelected()) { + return true; + } + } + return false; + } + + public void clearAllSelected() { + List data = getData(); + for (GiveInfo info : data) { + info.setSelected(false); + } + notifyDataSetChanged(); + } + + public void selectItem(int position) { + List data = getData(); + for (int i = 0; i < data.size(); i++) { + data.get(i).setSelected(i == position); + } + notifyDataSetChanged(); + } + + public int getSelectItemValue() { + List data = getData(); + for (GiveInfo info : data) { + if (info.isSelected()) { + return info.getGoldNum(); + } + } + return 0; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewActivity.java b/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewActivity.java new file mode 100644 index 000000000..d67a76c6a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewActivity.java @@ -0,0 +1,470 @@ +package com.yizhuan.erban.ui.webview; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.net.http.SslError; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.ActivityCompat; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.SslErrorHandler; +import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.google.gson.Gson; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.orhanobut.logger.Logger; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.webview.event.CloseWebViewEvent; +import com.yizhuan.erban.ui.webview.event.ShowNavEvent; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.erban.utils.WebViewUtils; +import com.yizhuan.xchat_android_core.certification.event.CertificationResultEvent; +import com.yizhuan.xchat_android_core.share.ShareModel; +import com.yizhuan.xchat_android_core.web.bean.WebJsBeanInfo; +import com.yizhuan.xchat_android_core.web.event.WebViewRefreshEvent; +import com.yizhuan.xchat_android_library.rxbus.RxBus; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.lang.ref.WeakReference; + +import cn.sharesdk.framework.Platform; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + + +/** + * @author Administrator + */ +public class CommonWebViewActivity extends BaseActivity implements ShareDialog.OnShareDialogItemClick { + + private FrameLayout layoutTitleBar; + private WebView webView; + private ProgressBar mProgressBar; + private CommonWebViewActivity mActivity; + private WebChromeClient wvcc; + private ImageView imgShare; + private TextView mTvRightText; + private ImageView mIvBack; + private ImageView mIvClose; + private TextView mTitle; + + private WebJsBeanInfo mWebJsBeanInfo; + private String url; + private String targetUrl; + + private ValueCallback mUploadMessage; + private ValueCallback mUploadMessage5; + public static final int FILECHOOSER_RESULTCODE = 5173; + public static final int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 5174; + + private static final String POSITION = "position"; + private int mPosition; + + private int mProgress; + + private Handler mHandler = new Handler(); + + private ProgressRunnable mProgressRunnable = new ProgressRunnable(this); + + private static class ProgressRunnable implements Runnable { + private WeakReference mWeakReference; + + ProgressRunnable(CommonWebViewActivity activity) { + mWeakReference = new WeakReference<>(activity); + } + + @Override + public void run() { + CommonWebViewActivity activity = mWeakReference.get(); + if (activity == null) return; + if (activity.mProgress < 96) { + activity.mProgress += 3; + activity.mProgressBar.setProgress(activity.mProgress); + activity.mHandler.postDelayed(activity.mProgressRunnable, 10); + } + } + } + + + public static void start(Context context, String url) { + Intent intent = new Intent(context, CommonWebViewActivity.class); + intent.putExtra("url", url); + context.startActivity(intent); + } + + /** + * 排行榜专用 + */ + public static void start(Context context, String url, int position) { + Intent intent = new Intent(context, CommonWebViewActivity.class); + intent.putExtra("url", url); + intent.putExtra(POSITION, position); + context.startActivity(intent); + } + + /** + * webView 某些h5 功能页面 需要在h5 使用结束后做一些操作 + * + * @param context + * @param url + * @param callBack 回调 + */ + public static void start(Context context, String url, WebViewCallBack callBack) { + Intent intent = new Intent(context, CommonWebViewActivity.class); + intent.putExtra("url", url); + context.startActivity(intent); + webViewCallBack = callBack; + } + + @SuppressLint("CheckResult") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_common_web_view); + Intent intent = getIntent(); + url = intent.getStringExtra("url"); + mPosition = intent.getIntExtra(POSITION, 0) + 1; + mActivity = this; + initView(); + initData(); + setListener(); + ShowWebView(url); + RxBus.get().toFlowable(ShareH5Event.class) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(shareH5Event -> { + WebJsBeanInfo webJsBeanInfo = shareH5Event.getWebJsBeanInfo(); + if (webJsBeanInfo != null) { + if (XChatApplication.isDebug()) { + toast("WebJsBeanInfo->" + new Gson().toJson(webJsBeanInfo)); + } + mWebJsBeanInfo = webJsBeanInfo; + showMenu(webJsBeanInfo.getData()); + } + }); + EventBus.getDefault().register(this); + } + + private void setListener() { + imgShare.setOnClickListener(v -> { + ShareDialog shareDialog = new ShareDialog(mActivity); + shareDialog.setOnShareDialogItemClick(CommonWebViewActivity.this); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.show(); + }); + + mIvBack.setOnClickListener(v -> { + if (webView.canGoBack()) { + webView.goBack(); + } else { + finish(); + } + }); + + mIvClose.setOnClickListener(v -> { + finish(); + }); + } + + @SuppressLint("SetJavaScriptEnabled") + private void initData() { + mHandler.post(mProgressRunnable); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setUseWideViewPort(true); + // 设置 WebView 可以在 HTTPS 通道上加载 HTTP 资源,Android 4.4 后的暗坑 + // 因为 Android 4.4 后默认不允许在 HTTPS 通道上加载 HTTP 资源 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + } + webView.getSettings().setTextZoom(100); + JSInterface jsInterface = new JSInterface(webView, this); + jsInterface.setPosition(mPosition); + webView.addJavascriptInterface(jsInterface, "androidJsObj"); + webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); + webView.setWebViewClient(new WebViewClient() { + + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Logger.e("shouldOverrideUrlLoading--------" + url); + LogUtil.e("shouldOverrideUrlLoading" + url); + targetUrl = url; + //modules/noble/paySuccess.html + //modules/noble/order.html?nobleIndex=1 // 获取上下文, H5PayDemoActivity为当前页面 + // ------ 对alipays:相关的scheme处理 ------- + if (url.startsWith("alipays:") || url.startsWith("alipay")) { + try { + CommonWebViewActivity.this.startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url))); + } catch (Exception e) { + new AlertDialog.Builder(CommonWebViewActivity.this) + .setMessage("未检测到支付宝客户端,请安装后重试。") + .setPositiveButton("立即安装", (dialog, which) -> { + Uri alipayUrl = Uri.parse("https://d.alipay.com"); + CommonWebViewActivity.this.startActivity(new Intent("android.intent.action.VIEW", alipayUrl)); + }).setNegativeButton("取消", null).show(); + } + return true; + } + if (url.contains("tel:")) { + //删除直接拨打电话的功能 + return true; + } + // ------- 处理结束 ------- + + if (!(url.startsWith("http") || url.startsWith("https"))) { + return true; + } + + view.loadUrl(url); + return true; + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { +// super.onReceivedSslError(view, handler, error); //一定要去掉 + // handler.cancel();// Android默认的处理方式 + handler.proceed();// 接受所有网站的证书 + // handleMessage(Message msg);// 进行其他处理 + } + + @Override + public void onPageFinished(WebView view, String url) { + Logger.e("onPageFinished--------" + url); + mProgressBar.setProgress(100); + mProgressBar.setVisibility(View.GONE); + super.onPageFinished(view, url); + } + }); + //获取webviewtitle作为titlebar的title + wvcc = new WebChromeClient() { + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + mTitle.setText(title + ""); + } + + // For Android >= 4.1 + public void openFileChooser(ValueCallback uploadMsg, + String acceptType, String capture) { + mUploadMessage = uploadMsg; + Intent i = new Intent(Intent.ACTION_GET_CONTENT); + i.addCategory(Intent.CATEGORY_OPENABLE); + i.setType("*/*"); + startActivityForResult(Intent.createChooser(i, "File Browser"), + FILECHOOSER_RESULTCODE); + } + + // For Lollipop 5.0+ Devices + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public boolean onShowFileChooser(WebView mWebView, + ValueCallback filePathCallback, + FileChooserParams fileChooserParams) { + if (mUploadMessage5 != null) { + mUploadMessage5.onReceiveValue(null); + mUploadMessage5 = null; + } + mUploadMessage5 = filePathCallback; + Intent intent = fileChooserParams.createIntent(); + try { + startActivityForResult(intent, + FILECHOOSER_RESULTCODE_FOR_ANDROID_5); + } catch (ActivityNotFoundException e) { + mUploadMessage5 = null; + return false; + } + return true; + } + + }; + // 设置setWebChromeClient对象 + webView.setWebChromeClient(wvcc); + // 设置Webview的user-agent + webView.getSettings().setUserAgentString(webView.getSettings().getUserAgentString() + " tutuAppAndroid erbanAppAndroid"); + } + + @SuppressLint("NewApi") + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if (requestCode == FILECHOOSER_RESULTCODE) { + if (null == mUploadMessage) { + return; + } + Uri result = intent == null || resultCode != Activity.RESULT_OK ? null + : intent.getData(); + mUploadMessage.onReceiveValue(result); + mUploadMessage = null; + } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) { + if (null == mUploadMessage5) { + return; + } + mUploadMessage5.onReceiveValue(WebChromeClient.FileChooserParams + .parseResult(resultCode, intent)); + mUploadMessage5 = null; + } + } + + private void initView() { + layoutTitleBar = findViewById(R.id.layout_title_bar); + layoutTitleBar.setVisibility(View.VISIBLE); + + webView = (WebView) findViewById(R.id.webview); + imgShare = (ImageView) findViewById(R.id.img_share); + mProgressBar = (ProgressBar) findViewById(R.id.progress_bar); + mTvRightText = (TextView) findViewById(R.id.tv_title_right); + + mIvBack = findViewById(R.id.iv_back); + mIvClose = findViewById(R.id.iv_close); + mTitle = findViewById(R.id.tv_title); + } + + private void showMenu(WebJsBeanInfo.DataBean data) { + switch (mWebJsBeanInfo.getType()) { + case WebJsBeanInfo.TEXT: + mTvRightText.setVisibility(View.VISIBLE); + mTvRightText.setText(data.getTitle()); + mTvRightText.setOnClickListener(v -> webView.loadUrl(data.getLink())); + break; + case WebJsBeanInfo.SHARE: + imgShare.setVisibility(View.VISIBLE); + break; + case WebJsBeanInfo.JUMP_APP_PAGE: + mTvRightText.setVisibility(View.VISIBLE); + mTvRightText.setText(data.getTitle()); + mTvRightText.setOnClickListener(v -> + RouterHandler.handle(this, data.getRouterType(), data.getRouterVal())); + break; + case WebJsBeanInfo.RESET_UI: + imgShare.setVisibility(View.GONE); + mTvRightText.setText(""); + mTvRightText.setVisibility(View.GONE); + break; + default: + } + } + + public void ShowWebView(String url) { + Logger.d("ShowWebView--------" + url); + webView.loadUrl(url); + + } + + @Override + public void onBackPressed() { + if (webView.canGoBack()) { + if (!TextUtils.isEmpty(targetUrl) && targetUrl.contains("modules/nobles/paySuccess.html")) { + finish(); + } else + webView.goBack(); + } else { + this.finish(); + } + } + + + @Override + public void onInAppSharingItemClick() { +// SelectFriendActivity.startForSharingH5(this); + } + + @Override + public void onSharePlatformClick(Platform platform) { + if (mWebJsBeanInfo != null && mWebJsBeanInfo.getData() != null) { + switch (mWebJsBeanInfo.getType()) { + case WebJsBeanInfo.IMAGE: + if (TextUtils.isEmpty(mWebJsBeanInfo.getData().getImgUrl())) { + break; + } + ShareModel.get().shareImage(platform, mWebJsBeanInfo.getData().getImgUrl()); + break; + default: + ShareModel.get().shareH5(mWebJsBeanInfo.getData(), platform).subscribe(); + } + } else { + toast("无分享数据。"); + } + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRecieveNeedRefreshWebView(WebViewRefreshEvent event) { + if (!StringUtil.isEmpty(url)) { + ShowWebView(url); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void handleCertificationResultEvent(CertificationResultEvent event) { + webView.evaluateJavascript("renderByStatus(" + event.getStatus() + ")", null); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void closeWebViewEvent(CloseWebViewEvent event) { + if (event != null) { + finish(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void showNavEvent(ShowNavEvent event) { + if (event != null) { + // true为显示,false为关闭 + if (event.isShowNav()) { + layoutTitleBar.setVisibility(View.VISIBLE); + } else { + layoutTitleBar.setVisibility(View.GONE); + } + } + } + + @Override + protected void onDestroy() { + if (mHandler != null) { + mHandler.removeCallbacks(mProgressRunnable); + mProgressRunnable = null; + mHandler = null; + } + EventBus.getDefault().unregister(this); + + if (webViewCallBack != null) { + webViewCallBack.onResult(""); + webViewCallBack = null; + } + super.onDestroy(); + WebViewUtils.releaseWeb(webView); + } + + private static WebViewCallBack webViewCallBack; + + public interface WebViewCallBack { + void onResult(String str); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewFragment.java b/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewFragment.java new file mode 100644 index 000000000..edb4e0472 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/CommonWebViewFragment.java @@ -0,0 +1,114 @@ +package com.yizhuan.erban.ui.webview; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.net.http.SslError; +import android.os.Build; +import android.support.v4.app.ActivityCompat; +import android.text.TextUtils; +import android.webkit.SslErrorHandler; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingFragment; +import com.yizhuan.erban.databinding.FragmentCommonWebViewBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +@ActLayoutRes(R.layout.fragment_common_web_view) +public class CommonWebViewFragment extends BaseBindingFragment { + + private WebView webView; + protected String url; + + @Override + public void initiate() { + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setUseWideViewPort(true); + // 设置 WebView 可以在 HTTPS 通道上加载 HTTP 资源,Android 4.4 后的暗坑 + // 因为 Android 4.4 后默认不允许在 HTTPS 通道上加载 HTTP 资源 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); + } + webView.getSettings().setTextZoom(100); + JSInterface jsInterface = new JSInterface(webView, getActivity()); + webView.addJavascriptInterface(jsInterface, "androidJsObj"); + webView.setWebViewClient(new WebViewClient() { + + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Logger.e("shouldOverrideUrlLoading--------" + url); + //modules/noble/paySuccess.html + //modules/noble/order.html?nobleIndex=1 // 获取上下文, H5PayDemoActivity为当前页面 + // ------ 对alipays:相关的scheme处理 ------- + if (url.startsWith("alipays:") || url.startsWith("alipay")) { + try { + CommonWebViewFragment.this.startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url))); + } catch (Exception e) { + new AlertDialog.Builder(CommonWebViewFragment.this.mContext) + .setMessage("未检测到支付宝客户端,请安装后重试。") + .setPositiveButton("立即安装", (dialog, which) -> { + Uri alipayUrl = Uri.parse("https://d.alipay.com"); + CommonWebViewFragment.this.startActivity(new Intent("android.intent.action.VIEW", alipayUrl)); + }).setNegativeButton("取消", null).show(); + } + return true; + } + if (url.contains("tel:")) { + //删除直接拨打电话的功能 + return true; + } + // ------- 处理结束 ------- + + if (!(url.startsWith("http") || url.startsWith("https"))) { + return true; + } + + view.loadUrl(url); + return true; + } + + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { +// super.onReceivedSslError(view, handler, error); //一定要去掉 + // handler.cancel();// Android默认的处理方式 + handler.proceed();// 接受所有网站的证书 + // handleMessage(Message msg);// 进行其他处理 + } + + @Override + public void onPageFinished(WebView view, String url) { + Logger.e("onPageFinished--------" + url); + super.onPageFinished(view, url); + } + }); + // 设置Webview的user-agent + webView.getSettings().setUserAgentString(webView.getSettings().getUserAgentString() + " tutuAppAndroid erbanAppAndroid"); + } + + @Override + public void onFindViews() { + super.onFindViews(); + webView = mBinding.webview; + } + + public void ShowWebView(String url) { + webView.loadUrl(url); + + } + + @Override + public void onResume() { + super.onResume(); + if (!TextUtils.isEmpty(url)) { + // 强制每次点到这个 tab 的时候就刷新数据 + ShowWebView(url); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/JSInterface.java b/app/src/main/java/com/yizhuan/erban/ui/webview/JSInterface.java new file mode 100644 index 000000000..b544be506 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/JSInterface.java @@ -0,0 +1,512 @@ +package com.yizhuan.erban.ui.webview; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.media.MediaRecorder; +import android.os.Build; +import android.os.Environment; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import android.webkit.JavascriptInterface; +import android.webkit.WebView; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.security.rp.RPSDK; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.orhanobut.logger.Logger; +import com.umeng.commonsdk.statistics.common.DeviceConfig; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.decoration.view.DecorationStoreActivity; +import com.yizhuan.erban.family.view.activity.FamilyHomeActivity; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.im.avtivity.NimP2PMessageActivity; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.webview.event.CloseDialogWebViewEvent; +import com.yizhuan.erban.ui.webview.event.CloseWebViewEvent; +import com.yizhuan.erban.ui.webview.event.H5NotifyClientEvent; +import com.yizhuan.erban.ui.webview.event.ShowNavEvent; +import com.yizhuan.erban.ui.widget.ShareDialog; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.certification.event.CertificationResultEvent; +import com.yizhuan.xchat_android_core.decoration.bean.DecorationStoreRouterType; +import com.yizhuan.xchat_android_core.file.FileModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.public_chat_hall.manager.PublicChatHallDataManager; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.web.bean.WebJsBeanInfo; +import com.yizhuan.xchat_android_library.record.AuditRecorderConfiguration; +import com.yizhuan.xchat_android_library.record.ExtAudioRecorder; +import com.yizhuan.xchat_android_library.rxbus.RxBus; +import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil; +import com.yizhuan.xchat_android_library.utils.AppUtils; +import com.yizhuan.xchat_android_library.utils.DeviceUuidFactory; +import com.yizhuan.xchat_android_library.utils.SystemUtils; +import com.yizhuan.xchat_android_library.utils.VersionUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import org.greenrobot.eventbus.EventBus; + +import java.io.File; +import java.util.Locale; + +import static android.content.Context.CLIPBOARD_SERVICE; + +/** + *

html js 与webview 交互接口

+ * Created by ${user} on 2017/11/6. + */ +public class JSInterface { + private static final String TAG = JSInterface.class.getSimpleName(); + private WebView mWebView; + private CommonWebViewActivity mActivity; + private Context context; + private int mPosition; + private MediaRecorder recorder; + private File myRecAudioFile; + + public JSInterface(WebView webView, CommonWebViewActivity activity) { + mWebView = webView; + mActivity = activity; + context = activity; + } + + public JSInterface(WebView webView, Context context) { + mWebView = webView; + this.context = context; + } + + public void setPosition(int position) { + mPosition = position; + } + + /** + * 调转个人主页 + * + * @param uid 用户id + */ + @JavascriptInterface + public void openPersonPage(String uid) { + LogUtil.i(TAG, "openPersonPage:" + uid); + if (!TextUtils.isEmpty(uid)) { + try { + long uidLong = Long.parseLong(uid); + UIHelper.showUserInfoAct(context, uidLong); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + + /** + * 跳转充值页面 + */ + @JavascriptInterface + public void openChargePage() { + if (context != null) { + ChargeActivity.start(context); + } + } + + @JavascriptInterface + public void openSharePage() { + if (mActivity != null) { + ShareDialog shareDialog = new ShareDialog(mActivity); + shareDialog.setOnShareDialogItemClick(mActivity); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.show(); + } + } + + @JavascriptInterface + public void openSharePage(String json) { + Logger.e("openSharePage: " + json); + WebJsBeanInfo webJsBeanInfo = JSON.parseObject(json, WebJsBeanInfo.class); + RxBus.get().post(new ShareH5Event().setWebJsBeanInfo(webJsBeanInfo)); + if (mActivity != null) { + ShareDialog shareDialog = new ShareDialog(mActivity); + shareDialog.setOnShareDialogItemClick(mActivity); + shareDialog.setType(ShareDialog.TYPE_SHARE_H5); + shareDialog.show(); + } + } + + /** + * 调转钱包页 + */ + @JavascriptInterface + public void openPurse() { + LogUtil.i(TAG, "openPurse:"); + } + + /** + * 调转房间 + * + * @param uid 房主uid + */ + @JavascriptInterface + public void openRoom(String uid) { + LogUtil.i(TAG, "openRoom:" + uid); + if (!TextUtils.isEmpty(uid)) { + try { + long uidLong = Long.parseLong(uid); + long publicChatHallUid = 0; + if (PublicChatHallDataManager.get().getPublicChatHallUid() != null) { + publicChatHallUid = Long.parseLong(PublicChatHallDataManager.get().getPublicChatHallUid()); + } + if (uidLong == publicChatHallUid) { + PublicChatHallHomeActivity.openPublicChatHallPage(context); + } else { + AVRoomActivity.start(context, uidLong); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + + } + + /** + * 获取用户ticket + * + * @return + */ + @JavascriptInterface + public String getTicket() { + return AuthModel.get().getTicket(); + } + + /** + * 获取设备ID + * + * @return 设备id + */ + @JavascriptInterface + public String getDeviceId() { + return DeviceUuidFactory.getDeviceId(BasicConfig.INSTANCE.getAppContext()); + } + + /** + * 获取房间的uid + * + * @return - + */ + @JavascriptInterface + public String getRoomUid() { + RoomInfo mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (mCurrentRoomInfo == null || mCurrentRoomInfo.getUid() == 0) return null; + return String.valueOf(mCurrentRoomInfo.getUid()); + } + + /** + * 获取uid + * + * @return uid + */ + @JavascriptInterface + public String getUid() { + /* if (mActivity != null && mWebView != null) { + LogUtil.i(TAG, "getUid.........................."); + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + String args = "'uid'," + String.valueOf(AuthModel.get().getCurrentUid()); + mWebView.loadUrl("javascript:getMessage(" + args + ")"); + } + }); + }*/ + return String.valueOf(AuthModel.get().getCurrentUid()); + } + + @JavascriptInterface + public String getPosition() { + return String.valueOf(mPosition); + } + + @JavascriptInterface + public void challenge(long uid, String gameId) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.gamelist_challenge, "挑战按钮"); + NimP2PMessageActivity.start(context, uid + "", gameId); + } + + @JavascriptInterface + public void clipboardToPhone(String content) { + ClipboardManager myClipboard; + myClipboard = (ClipboardManager) BasicConfig.INSTANCE.getAppContext().getSystemService(CLIPBOARD_SERVICE); + ClipData myClip; + myClip = ClipData.newPlainText("text", content); + if (myClipboard != null) + myClipboard.setPrimaryClip(myClip); + } + + @JavascriptInterface + public void initNav(String json) { + Logger.e("initNav: " + json); + WebJsBeanInfo webJsBeanInfo = JSON.parseObject(json, WebJsBeanInfo.class); + RxBus.get().post(new ShareH5Event().setWebJsBeanInfo(webJsBeanInfo)); + } + + /** + * 初始化导航栏 + * + * @param b true为显示,false为关闭 + */ + @JavascriptInterface + public void initShowNav(boolean b) { + Logger.e("initShowNav: " + b); + EventBus.getDefault().post(new ShowNavEvent(b)); + } + + /** + * 关闭浏览器 + */ + @JavascriptInterface + public void closeWebView() { + EventBus.getDefault().post(new CloseWebViewEvent()); + } + + /** + * 联系客服 + * + * @param uid 客服 UID + */ + @JavascriptInterface + public void contactSomeOne(String uid) { + NimP2PMessageActivity.start(context, uid); + } + + private ExtAudioRecorder extAudioRecorder; + + @JavascriptInterface + public boolean startRecode() { + // recorder 实例 + AuditRecorderConfiguration configuration = new AuditRecorderConfiguration.Builder() + .uncompressed(true) + .builder(); + extAudioRecorder = new ExtAudioRecorder(configuration); + // 录音地址 + File sdcardDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath() + + File.separator + "wewawa"); + if (!sdcardDir.exists()) { + boolean mkdirResult = sdcardDir.mkdir(); + Log.e(TAG, "startRecode: mkdirResult: " + mkdirResult); + } + myRecAudioFile = new File(sdcardDir.getAbsolutePath(), "wewawa-" + System.currentTimeMillis() + ".wav"); + Log.i(TAG, "startRecode: myRecAudioFile path: " + myRecAudioFile.getAbsolutePath()); + // 设置输出文件 + extAudioRecorder.setOutputFile(myRecAudioFile.getAbsolutePath()); + extAudioRecorder.prepare(); + extAudioRecorder.start(); + return true; + } + + @JavascriptInterface + public String stopRecode() { + if (extAudioRecorder == null || myRecAudioFile == null) + return null; + if (!myRecAudioFile.exists()) { + return null; + } + extAudioRecorder.stop(); + extAudioRecorder.release(); + String url = FileModel.get() + .uploadFile(myRecAudioFile.getAbsolutePath()) + .blockingGet(); + myRecAudioFile.delete(); + Log.i(TAG, "stopRecord: url: " + url); + return url; + } + + @JavascriptInterface + public void openFamilyPage(String familyId) { + FamilyHomeActivity.start(context, familyId); + } + + /** + * 打开装扮商城 + * + * @param type {@link DecorationStoreRouterType#TYPE_HEAD_WEAR} + * {@link DecorationStoreRouterType#TYPE_CAR} + * {@link DecorationStoreRouterType#TYPE_BACKGROUND} + */ + @JavascriptInterface + public void openDecorateMallPage(int type) { + if (type <= 0) return; + DecorationStoreActivity.start(context, AuthModel.get().getCurrentUid(), type - 1); + } + + /** + * 获取应用版本号 + */ + @JavascriptInterface + public String getAppVersion() { + return VersionUtil.getLocalName(context); + } + + /** + * 获取渠道 + * + * @return 渠道名称 + */ + @JavascriptInterface + public String getChannel() { + return AppMetaDataUtil.getChannelID(); + } + + /** + * 获取是否审核中状态 + * + * @return 1 正常审核中 + */ + @JavascriptInterface + public int loadingStatus() { + return MarketVerifyModel.get().isMarketChecking() ? 1 : 0; + } + + /** + * 根据 routerType 协议跳转不同的页面 + * + * @param json + */ + @JavascriptInterface + public void jumpAppointPage(String json) { + Logger.e("jumpAppointPage: " + json); + WebJsBeanInfo.DataBean webDataBean = JSON.parseObject(json, WebJsBeanInfo.DataBean.class); + if (Looper.myLooper() == Looper.getMainLooper()) { + RouterHandler.handle(context, webDataBean.getRouterType(), + String.valueOf(webDataBean.getRouterVal())); + } else { + mWebView.post(new Runnable() { + @Override + public void run() { + + RouterHandler.handle(context, webDataBean.getRouterType(), + String.valueOf(webDataBean.getRouterVal())); + } + }); + } + + } + + /** + * 获取 deviceInfo + * + * @return + */ + @JavascriptInterface + public String getDeviceInfo() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("os", "android"); + jsonObject.put("osVersion", Build.VERSION.RELEASE); + jsonObject.put("app", "tutu"); + jsonObject.put("ispType", String.valueOf(SystemUtils.getIspType(context))); + jsonObject.put("netType", String.valueOf(SystemUtils.getNetworkType(context))); + jsonObject.put("model", SystemUtils.getPhoneModel()); + jsonObject.put("appVersion", VersionUtil.getLocalName(context)); + jsonObject.put("appVersionCode", String.valueOf(AppUtils.getVersionCode(context))); + jsonObject.put("deviceId", DeviceConfig.getDeviceId(context)); + jsonObject.put("channel", AppMetaDataUtil.getChannelID()); + jsonObject.put("macAddress", DeviceConfig.getMac(context)); + Log.e(TAG, "getDeviceInfo: " + jsonObject); + return jsonObject.toJSONString(); + } + + + /** + * 刷脸 + *

+ * AUDIT_EXCEPTION = -2, //认证异常,网络不通或者环境问题 + * AUDIT_NOT = -1, //未认证,用户主动取消 + * AUDIT_IN_AUDIT = 0, //认证中 + * AUDIT_FAIL = 1, //审核失败 + * AUDIT_PASS = 2, //审核通过 + * + * @param verifyToken + */ + @JavascriptInterface + public void openFaceLiveness(String verifyToken) { + Log.d(TAG, "openFaceLiveness() called with: verifyToken = [" + verifyToken + "]"); + RPSDK.start(verifyToken, mActivity, + (audit, s, s1) -> { + Log.d(TAG, String.format(Locale.getDefault(), "openFaceLiveness: auit: %s, s: %s, s1: %s", + audit, s, s1)); + int result = -3; + if (audit == RPSDK.AUDIT.AUDIT_PASS) { + // 认证通过 + result = 2; + // 更新本地缓存 + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + userInfo.setCertified(true); + } + // 认证通过的时候刷新用户信息 + UserModel.get().updateCurrentUserInfo().subscribe(); + } else if (audit == RPSDK.AUDIT.AUDIT_FAIL) { + // 认证不通过 + result = 1; + } else if (audit == RPSDK.AUDIT.AUDIT_IN_AUDIT) { + // 认证中,通常不会出现,只有在认证审核系统内部出现超时, + // 未在限定时间内返回认证结果时出现。此时提示用户系统处理中, + // 稍后查看认证结果即可。 + result = 0; + } else if (audit == RPSDK.AUDIT.AUDIT_NOT) { + // 未认证,用户取消 + result = -1; + } else if (audit == RPSDK.AUDIT.AUDIT_EXCEPTION) { + // 系统异常 + result = -2; + } + EventBus.getDefault().post(new CertificationResultEvent().setStatus(result)); + }); + } + + /** + * h5操作成功后,回调的客户端方法 + * + * @param json {"type": 1} + */ + @JavascriptInterface + public void onNotifyClient(String json) { + EventBus.getDefault().post(new H5NotifyClientEvent(json)); + } + + + /** + * h5更新当前登录用户信息 + */ + @JavascriptInterface + public void updateCurrentUserInfo() { + UserModel.get().updateCurrentUserInfo().subscribe(); + } + + @JavascriptInterface + public void h5CallAppStatistics(String json) { + try { + org.json.JSONObject jsonObject = new org.json.JSONObject(json); + String funcName = jsonObject.getString("funcName"); + String title = jsonObject.getString("title"); + + if (!TextUtils.isEmpty(funcName) && !TextUtils.isEmpty(title)) + StatisticManager.Instance().onEvent(funcName, title); + + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @JavascriptInterface + public void closeDialogWebView() { + EventBus.getDefault().post(new CloseDialogWebViewEvent()); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/ShareH5Event.java b/app/src/main/java/com/yizhuan/erban/ui/webview/ShareH5Event.java new file mode 100644 index 000000000..1f65511f9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/ShareH5Event.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.ui.webview; + +import com.yizhuan.xchat_android_core.web.bean.WebJsBeanInfo; + +/** + * Created by MadisonRong on 26/06/2018. + */ + +public class ShareH5Event { + + private WebJsBeanInfo webJsBeanInfo; + + public WebJsBeanInfo getWebJsBeanInfo() { + return webJsBeanInfo; + } + + public ShareH5Event setWebJsBeanInfo(WebJsBeanInfo webJsBeanInfo) { + this.webJsBeanInfo = webJsBeanInfo; + return this; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/WebServer.java b/app/src/main/java/com/yizhuan/erban/ui/webview/WebServer.java new file mode 100644 index 000000000..24d5ccce6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/WebServer.java @@ -0,0 +1,82 @@ +package com.yizhuan.erban.ui.webview; + +import android.os.Environment; +import android.util.Log; + +import com.netease.nim.uikit.common.util.log.LogUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import fi.iki.elonen.NanoHTTPD; + +public class WebServer extends NanoHTTPD { + public static final String MIME_JAVASCRIPT = "text/javascript"; + public static final String MIME_CSS = "text/css"; + public static final String MIME_JPEG = "image/jpeg"; + public static final String MIME_PNG = "image/png"; + public static final String MIME_SVG = "image/svg+xml"; + public static final String MIME_JSON = "application/json"; + + + public WebServer() { + super(8080); + } + + @Override + public Response serve(IHTTPSession session) { + + String mime_type = NanoHTTPD.MIME_PLAINTEXT; + Method method = session.getMethod(); + String uri = session.getUri(); + System.out.println(method + " '" + uri + "' "); + InputStream descriptor = null; + + if (method.toString().equalsIgnoreCase("GET")) { + String path; + if (uri.equals("/")) { + path = "/index.html"; + } else { + path = uri; + try { + if (path.endsWith(".js")) { + mime_type = MIME_JAVASCRIPT; + } else if (path.endsWith(".css")) { + mime_type = MIME_CSS; + } else if (path.endsWith(".html")) { + mime_type = MIME_HTML; + } else if (path.endsWith(".jpeg")) { + mime_type = MIME_JPEG; + } else if (path.endsWith(".png")) { + mime_type = MIME_PNG; + } else if (path.endsWith(".jpg")) { + mime_type = MIME_JPEG; + } else if (path.endsWith(".svg")) { + mime_type = MIME_SVG; + } else if (path.endsWith(".json")) { + mime_type = MIME_JSON; + } + } catch (Exception e) { + + } + } + String sub = path.substring(path.indexOf("feidao") + 7); +// LogUtil.e("path:" + path); +// LogUtil.e("sub:" + sub); + try { + File file = new File(Environment.getExternalStorageDirectory() + "/feidao/" + sub); + descriptor = new FileInputStream(file); + } catch (IOException ioe) { + Log.w("Httpd", ioe.toString()); + } + } + try { + return newFixedLengthResponse(Response.Status.OK, mime_type, descriptor, descriptor.available()); + } catch (IOException e) { + return null; + + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseDialogWebViewEvent.java b/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseDialogWebViewEvent.java new file mode 100644 index 000000000..7e36ea85c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseDialogWebViewEvent.java @@ -0,0 +1,7 @@ +package com.yizhuan.erban.ui.webview.event; + +/** + * create by lvzebiao @2019/12/3 + */ +public class CloseDialogWebViewEvent { +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseWebViewEvent.java b/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseWebViewEvent.java new file mode 100644 index 000000000..b65432089 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/event/CloseWebViewEvent.java @@ -0,0 +1,8 @@ +package com.yizhuan.erban.ui.webview.event; + +import lombok.Data; + +@Data +public class CloseWebViewEvent { + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/event/H5NotifyClientEvent.java b/app/src/main/java/com/yizhuan/erban/ui/webview/event/H5NotifyClientEvent.java new file mode 100644 index 000000000..9d68f9e32 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/event/H5NotifyClientEvent.java @@ -0,0 +1,15 @@ +package com.yizhuan.erban.ui.webview.event; + +import com.yizhuan.xchat_android_core.base.BaseBusEvent; + +/** + * h5通知客户端的事件 + * Created by lvzebiao on 2019/2/25. + */ + +public class H5NotifyClientEvent extends BaseBusEvent{ + + public H5NotifyClientEvent(String data) { + super(data); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/webview/event/ShowNavEvent.java b/app/src/main/java/com/yizhuan/erban/ui/webview/event/ShowNavEvent.java new file mode 100644 index 000000000..49a8d4f85 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/webview/event/ShowNavEvent.java @@ -0,0 +1,19 @@ +package com.yizhuan.erban.ui.webview.event; + +import lombok.Data; + +/** + * 初始化导航栏 + */ +@Data +public class ShowNavEvent { + private boolean isShowNav; + + public ShowNavEvent(boolean isShowNav) { + this.isShowNav = isShowNav; + } + + public boolean isShowNav() { + return isShowNav; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/Anticlockwise.java b/app/src/main/java/com/yizhuan/erban/ui/widget/Anticlockwise.java new file mode 100644 index 000000000..b50c164de --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/Anticlockwise.java @@ -0,0 +1,91 @@ +package com.yizhuan.erban.ui.widget; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Chronometer; + +@SuppressLint( + {"ViewConstructor", "SimpleDateFormat"}) +public class Anticlockwise extends Chronometer { + public Anticlockwise(Context context, AttributeSet attrs) { + super(context, attrs); + mTimeFormat = new SimpleDateFormat("mm:ss"); + this.setOnChronometerTickListener(listener); + } + + private long mTime; + private long mNextTime; + private OnTimeCompleteListener mListener; + private SimpleDateFormat mTimeFormat; + + public Anticlockwise(Context context) { + super(context); + + } + + public void reStart(long _time_s) { + if (_time_s == -1) { + mNextTime = mTime; + } else { + mTime = mNextTime = _time_s; + } + this.start(); + } + + public void reStart() { + reStart(-1); + } + + public void onResume() { + this.start(); + } + public void onPause() { + this.stop(); + } + + public void setTimeFormat(String pattern) { + mTimeFormat = new SimpleDateFormat(pattern); + } + + public void setOnTimeCompleteListener(OnTimeCompleteListener l) { + mListener = l; + } + + OnChronometerTickListener listener = new OnChronometerTickListener() { + @Override + public void onChronometerTick(Chronometer chronometer) { + if (mNextTime <= 0) { + if (mNextTime == 0) { + Anticlockwise.this.stop(); + if (null != mListener) + mListener.onTimeComplete(); + } + mNextTime = 0; + updateTimeText(); + return; + } + + mNextTime--; + + updateTimeText(); + } + }; + + public void initTime(long _time_s) { + mTime = mNextTime = _time_s; + updateTimeText(); + } + + private void updateTimeText() { + this.setText(mTimeFormat.format(new Date(mNextTime * 1000))); + } + + public interface OnTimeCompleteListener { + void onTimeComplete(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ButtonItem.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ButtonItem.java new file mode 100644 index 000000000..c2a59c13d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ButtonItem.java @@ -0,0 +1,105 @@ +package com.yizhuan.erban.ui.widget; + + +import com.yizhuan.erban.R; + +public class ButtonItem { + public static final int BUTTON_TYPE_NORMAL = 0; + public static final int BUTTON_TYPE_CANCEL = 1; + + /**房间个人信息的弹窗button,放在网格里面的*/ + public static final int BUTTON_TYPE_GIRD = 2; + /**房间个人信息的弹窗button,放在底下的,和主页按钮一起的*/ + public static final int BUTTON_TYPE_BOTTOM = 3; + + + /** 发送礼物 */ + public static final int SEND_GIFT_ITEM = 0; + /** 锁坑 */ + public static final int SEND_LOCK_MIC_ITEM = 1; + /** 踢下麦 个人弹窗 */ + public static final int KICKDOWN_MIC_ITEM = 2; + /** 踢出房间 */ + public static final int KICKOUT_ROOM_ITEM = 3; + /** 查看个人信息 */ + public static final int SEND_SHOW_USER_INCO_ITEM = 4; + /** 下麦 */ + public static final int DOWN_MIC_ITEM = 5; + /** 释放麦 */ + public static final int SEND_FREE_MIC_ITEM = 6; + /** 设置管理员 */ + public static final int SET_MANAGER_ITEM = 7; + /** 取消管理员 */ + public static final int CLEAR_MANAGER_ITEM = 11; + /** 加入黑名单 */ + public static final int MARK_BLACK_ITEM = 8; + + /** 个人资料开麦 */ + public static final int OPEN_MUTE_ITEM = 9; + /** 个人资料闭麦 */ + public static final int CLOSE_MUTE_ITEM = 10; + /** 抱上麦 */ + public static final int SEND_INVITE_MIC_ITEM = 12; + /** 发起竞拍 */ + public static final int START_AUCTION = 13; + /** 送魔法 */ + public static final int SEND_MAGIC_ITEM = 14; + /** 送装扮 */ + public static final int SEND_DECORATION_ITEM = 15; + /** 关注or取消 */ + public static final int ATTENT_ITEM = 15; + + public String mText; + public int textColor; + public int mLayout; + public OnClickListener mClickListener; + public int mButtonType; + public int mTheme = -1; + public int mIcon; + + public ButtonItem() { + } + + public ButtonItem(String text, int icon, OnClickListener clickListener) { + this(text, icon, BUTTON_TYPE_GIRD, R.layout.room_user_dialog_grid_button, clickListener); + } + +// public ButtonItem(String text, int buttonType, OnClickListener l) { +// mText = text; +// mClickListener = l; +// mButtonType = buttonType; +// resourceID = R.layout.layout_common_popup_dialog_button; +// +// } + public ButtonItem(String text, OnClickListener l) { + this(text, 0, BUTTON_TYPE_NORMAL, R.layout.layout_common_popup_dialog_button, l); + } + + public ButtonItem(String text, int icon, int buttonType, int layout, OnClickListener clickListener) { + mText = text; + mIcon = icon; + mClickListener = clickListener; + mButtonType = buttonType; + mLayout = layout; + } + + public void setText(String text) { + this.mText = text; + } + + public int getTextColor() { + return textColor; + } + + public void setTextColor(int textColor) { + this.textColor = textColor; + } + + public void setClickListener(OnClickListener mClickListener) { + this.mClickListener = mClickListener; + } + + public interface OnClickListener { + void onClick(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/CharAlignTextView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/CharAlignTextView.java new file mode 100644 index 000000000..8b3566377 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/CharAlignTextView.java @@ -0,0 +1,67 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatTextView; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; + +/** + * create by lvzebiao @2019/12/2 + */ +public class CharAlignTextView extends AppCompatTextView { + + private TextPaint textPaint; + + private float textYOffset; + + private Rect rect; + + public CharAlignTextView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + rect = new Rect(); + textPaint = getPaint(); + //textPaint.setColor(textColor); + textPaint.setTextAlign(Paint.Align.CENTER); + //textPaint.setTextSize(textSize); + Paint.FontMetrics textFontMetrics = textPaint.getFontMetrics(); + /* + * drawText从baseline开始,baseline的值为0,baseline的上面为负值,baseline的下面为正值, + * 即这里ascent为负值,descent为正值。 + * 比如ascent为-20,descent为5,那需要移动的距离就是20 - (20 + 5)/ 2 + */ + textYOffset = -textFontMetrics.ascent - (-textFontMetrics.ascent + textFontMetrics.descent) / 2; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int height = MeasureSpec.getSize(heightMeasureSpec); + int textWidth = 0; + String text = getText().toString(); + if (!TextUtils.isEmpty(getText()) && text.length() >= 2) { + //测量文本的长度 + rect.setEmpty(); + textPaint.getTextBounds(text, 0, text.length(), rect); + textWidth = rect.width(); + } + //noinspection SuspiciousNameCombination + setMeasuredDimension(textWidth, height); + } + + @Override + protected void onDraw(Canvas canvas) { + if (getCurrentTextColor() != 0) { + textPaint.setColor(getCurrentTextColor()); + } + String text = getText().toString(); + if (!TextUtils.isEmpty(text)) { + canvas.drawText(text, (float) getWidth() / 2, (float) getHeight() / 2 + textYOffset, + textPaint); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ContentWrapViewPager.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ContentWrapViewPager.java new file mode 100644 index 000000000..3e8b9d9f5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ContentWrapViewPager.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.View; + +/** + * @author jack + * @Description + * @Date 2018/10/31 + */ +public class ContentWrapViewPager extends ViewPager { + public ContentWrapViewPager(@NonNull Context context) { + super(context); + } + + public ContentWrapViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int height = 0; + //下面遍历所有child的高度 + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.measure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int h = child.getMeasuredHeight(); + if (h > height) //采用最大的view的高度。 + height = h; + } + + heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/CustSlidingTabLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/CustSlidingTabLayout.java new file mode 100644 index 000000000..b926df720 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/CustSlidingTabLayout.java @@ -0,0 +1,990 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; +import android.os.Parcelable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.util.Log; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.flyco.tablayout.listener.OnTabSelectListener; +import com.flyco.tablayout.utils.UnreadMsgUtils; +import com.flyco.tablayout.widget.MsgView; +import com.yizhuan.erban.R; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; + +/** + * 复制SlidingTabLayout源码,添加字体大小 + * tab宽度自适应 + * tab左内距20,其他内距0 + */ +public class CustSlidingTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener { + private Context mContext; + private ViewPager mViewPager; + private ArrayList mTitles; + private LinearLayout mTabsContainer; + private int mCurrentTab; + private float mCurrentPositionOffset; + private int mTabCount; + /** 用于绘制显示器 */ + private Rect mIndicatorRect = new Rect(); + /** 用于实现滚动居中 */ + private Rect mTabRect = new Rect(); + private GradientDrawable mIndicatorDrawable = new GradientDrawable(); + + private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Path mTrianglePath = new Path(); + private static final int STYLE_NORMAL = 0; + private static final int STYLE_TRIANGLE = 1; + private static final int STYLE_BLOCK = 2; + private int mIndicatorStyle = STYLE_NORMAL; + + private float mTabPadding; + private boolean mTabSpaceEqual; + private float mTabWidth; + + /** indicator */ + private int mIndicatorColor; + private float mIndicatorHeight; + private float mIndicatorWidth; + private float mIndicatorCornerRadius; + private float mIndicatorMarginLeft; + private float mIndicatorMarginTop; + private float mIndicatorMarginRight; + private float mIndicatorMarginBottom; + private int mIndicatorGravity; + private boolean mIndicatorWidthEqualTitle; + + /** underline */ + private int mUnderlineColor; + private float mUnderlineHeight; + private int mUnderlineGravity; + + /** divider */ + private int mDividerColor; + private float mDividerWidth; + private float mDividerPadding; + + /** title */ + private static final int TEXT_BOLD_NONE = 0; + private static final int TEXT_BOLD_WHEN_SELECT = 1; + private static final int TEXT_BOLD_BOTH = 2; + private float mTextsize; + protected float mTextSizeNormal; + private int mTextSelectColor; + private int mTextUnselectColor; + private int mTextBold; + private boolean mTextAllCaps; + + private int mLastScrollX; + private int mHeight; + private boolean mSnapOnTabClick; + + public CustSlidingTabLayout(Context context) { + this(context, null, 0); + } + + public CustSlidingTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CustSlidingTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口 + setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag + setClipChildren(false); + setClipToPadding(false); + + this.mContext = context; + mTabsContainer = new LinearLayout(context); + addView(mTabsContainer); + + obtainAttributes(context, attrs); + + //get layout_height + String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height"); + + if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) { + } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) { + } else { + int[] systemAttrs = {android.R.attr.layout_height}; + TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs); + mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT); + a.recycle(); + } + } + + private void obtainAttributes(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustSlidingTabLayout); + + mIndicatorStyle = ta.getInt(R.styleable.CustSlidingTabLayout_tl_indicator_style, STYLE_NORMAL); + mIndicatorColor = ta.getColor(R.styleable.CustSlidingTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff")); + mIndicatorHeight = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_height, + dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2))); + mIndicatorWidth = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1)); + mIndicatorCornerRadius = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0)); + mIndicatorMarginLeft = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_margin_left, dp2px(0)); + mIndicatorMarginTop = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorMarginRight = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_margin_right, dp2px(0)); + mIndicatorMarginBottom = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0)); + mIndicatorGravity = ta.getInt(R.styleable.CustSlidingTabLayout_tl_indicator_gravity, Gravity.BOTTOM); + mIndicatorWidthEqualTitle = ta.getBoolean(R.styleable.CustSlidingTabLayout_tl_indicator_width_equal_title, false); + + mUnderlineColor = ta.getColor(R.styleable.CustSlidingTabLayout_tl_underline_color, Color.parseColor("#ffffff")); + mUnderlineHeight = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_underline_height, dp2px(0)); + mUnderlineGravity = ta.getInt(R.styleable.CustSlidingTabLayout_tl_underline_gravity, Gravity.BOTTOM); + + mDividerColor = ta.getColor(R.styleable.CustSlidingTabLayout_tl_divider_color, Color.parseColor("#ffffff")); + mDividerWidth = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_divider_width, dp2px(0)); + mDividerPadding = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_divider_padding, dp2px(12)); + + mTextsize = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_textsize, sp2px(14)); + mTextSizeNormal = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_textsize_normal, mTextsize); + + mTextSelectColor = ta.getColor(R.styleable.CustSlidingTabLayout_tl_textSelectColor, Color.parseColor("#ffffff")); + mTextUnselectColor = ta.getColor(R.styleable.CustSlidingTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff")); + mTextBold = ta.getInt(R.styleable.CustSlidingTabLayout_tl_textBold, TEXT_BOLD_NONE); + mTextAllCaps = ta.getBoolean(R.styleable.CustSlidingTabLayout_tl_textAllCaps, false); + + mTabSpaceEqual = ta.getBoolean(R.styleable.CustSlidingTabLayout_tl_tab_space_equal, false); + mTabWidth = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_tab_width, dp2px(-1)); + mTabPadding = ta.getDimension(R.styleable.CustSlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20)); + mTabPadding = dp2px(20); + + ta.recycle(); + } + + /** 关联ViewPager */ + public void setViewPager(ViewPager vp) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + this.mViewPager = vp; + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + + } + + /** 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */ + public void setViewPager(ViewPager vp, String[] titles) { + if (vp == null || vp.getAdapter() == null) { + throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + if (titles.length != vp.getAdapter().getCount()) { + throw new IllegalStateException("Titles length must be the same as the page count !"); + } + + this.mViewPager = vp; + mTitles = new ArrayList<>(); + Collections.addAll(mTitles, titles); + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** 关联ViewPager,用于连适配器都不想自己实例化的情况 */ + public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments) { + if (vp == null) { + throw new IllegalStateException("ViewPager can not be NULL !"); + } + + if (titles == null || titles.length == 0) { + throw new IllegalStateException("Titles can not be EMPTY !"); + } + + this.mViewPager = vp; + this.mViewPager.setAdapter(new InnerPagerAdapter(fa.getSupportFragmentManager(), fragments, titles)); + + this.mViewPager.removeOnPageChangeListener(this); + this.mViewPager.addOnPageChangeListener(this); + notifyDataSetChanged(); + } + + /** 更新数据 */ + public void notifyDataSetChanged() { + mTabsContainer.removeAllViews(); + this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size(); + View tabView; + for (int i = 0; i < mTabCount; i++) { + tabView = View.inflate(mContext, R.layout.layout_cust_sliding_tab, null); + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles.get(i); + addTab(i, pageTitle.toString(), tabView); + } + + updateTabStyles(); + } + + public void addNewTab(String title) { + View tabView = View.inflate(mContext, R.layout.layout_cust_sliding_tab, null); + if (mTitles != null) { + mTitles.add(title); + } + + CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(mTabCount) : mTitles.get(mTabCount); + addTab(mTabCount, pageTitle.toString(), tabView); + this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size(); + + updateTabStyles(); + } + + /** 创建并添加tab */ + private void addTab(final int position, String title, View tabView) { + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + if (tv_tab_title != null) { + if (title != null) tv_tab_title.setText(title); + } + + tabView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int position = mTabsContainer.indexOfChild(v); + if (position != -1) { + if (mViewPager.getCurrentItem() != position) { + if (mSnapOnTabClick) { + mViewPager.setCurrentItem(position, false); + } else { + mViewPager.setCurrentItem(position); + } + + if (mListener != null) { + mListener.onTabSelect(position); + } + } else { + if (mListener != null) { + mListener.onTabReselect(position); + } + } + } + } + }); + + /** 每一个Tab的布局参数 */ + LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ? + new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) : + new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + if (mTabWidth > 0) { +// lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT); + lp_tab = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + } + Log.i("CustSlidingTabLayout", "======================"); + Log.i("CustSlidingTabLayout", "mTabWidth:" + mTabWidth); + Log.i("CustSlidingTabLayout", "tabViewWidth:" + tabView.getMeasuredWidth()); + + mTabsContainer.addView(tabView, position, lp_tab); + } + + private void updateTabStyles() { + for (int i = 0; i < mTabCount; i++) { + View v = mTabsContainer.getChildAt(i); +// v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom()); + TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title); + if (tv_tab_title != null) { + tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, i == mCurrentTab ? mTextsize : mTextSizeNormal); +// tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0); + tv_tab_title.setPadding((int) mTabPadding, 0, 0, 0); + if (mTextAllCaps) { + tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase()); + } + + if (mTextBold == TEXT_BOLD_BOTH) { + tv_tab_title.getPaint().setFakeBoldText(true); + } else if (mTextBold == TEXT_BOLD_NONE) { + tv_tab_title.getPaint().setFakeBoldText(false); + } + } + } + } + + private boolean isScrolled = false; + private float lastPercent = 0f; + + private void setScrollAnimation(int currentPosition, int nextPosition, float offsetPercent) { + if (isScrolled) { + + int scale = 1;//设置位数 + int roundingMode = 4;//表示四舍五入,可以选择其他舍值方式,例如去尾,等等. + BigDecimal bd = new BigDecimal((double)offsetPercent); + bd = bd.setScale(scale,roundingMode); + offsetPercent = bd.floatValue(); + if (offsetPercent == lastPercent) { +// Log.i("setScrollAnimation", "offsetPercent:" + true); + return; + } + lastPercent = offsetPercent; +// Log.i("setScrollAnimation", "offsetPercent:" + offsetPercent); + + float offset = mTextsize - mTextSizeNormal; + + float temp = offset * offsetPercent; + float temp2 = offset - temp; + + if (mTabsContainer != null) { + View v = mTabsContainer.getChildAt(currentPosition); + if (v != null) { + TextView tv_tab_title = v.findViewById(R.id.tv_tab_title); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSizeNormal + temp2); + } + + View nextV = mTabsContainer.getChildAt(nextPosition); + + if (nextV != null) { + TextView tv_tab_title = nextV.findViewById(R.id.tv_tab_title); + tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSizeNormal + temp); + } + + } + + } + + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + /** + * position:当前View的位置 + * mCurrentPositionOffset:当前View的偏移量比例.[0,1) + */ + this.mCurrentTab = position; + this.mCurrentPositionOffset = positionOffset; +// Log.i("setScrollAnimation", "positionOffset:" + positionOffset); + +// setScrollAnimation(this.mCurrentTab, this.mCurrentTab + 1, mCurrentPositionOffset); + + scrollToCurrentTab(); + invalidate(); + } + + @Override + public void onPageSelected(int position) { + updateTabSelection(position); + if (mListener != null) { + mListener.onTabSelect(position); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + isScrolled = state == 1 || state == 2; +// Log.i("setScrollAnimation", "state:" + state); + } + + /** HorizontalScrollView滚到当前tab,并且居中显示 */ + private void scrollToCurrentTab() { + if (mTabCount <= 0) { + return; + } + + int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth()); + /**当前Tab的left+当前Tab的Width乘以positionOffset*/ + int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset; + + if (mCurrentTab > 0 || offset > 0) { + /**HorizontalScrollView移动到当前tab,并居中*/ + newScrollX -= getWidth() / 2 - getPaddingLeft(); + calcIndicatorRect(); + newScrollX += ((mTabRect.right - mTabRect.left) / 2); + } + + if (newScrollX != mLastScrollX) { + mLastScrollX = newScrollX; + /** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量 + * x:表示离起始位置的x水平方向的偏移量 + * y:表示离起始位置的y垂直方向的偏移量 + */ + scrollTo(newScrollX, 0); + } + } + + private void updateTabSelection(int position) { +// Log.i("setScrollAnimation", "updateTabSelection:" + position); + for (int i = 0; i < mTabCount; ++i) { + View tabView = mTabsContainer.getChildAt(i); + final boolean isSelect = i == position; + TextView tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + + if (tab_title != null) { + tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor); + tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, isSelect ? mTextsize : mTextSizeNormal); + if (mTextBold == TEXT_BOLD_WHEN_SELECT) { + tab_title.getPaint().setFakeBoldText(isSelect); + } + } + } + } + + private float margin; + + private void calcIndicatorRect() { + View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab); + float left = currentTabView.getLeft(); + float right = currentTabView.getRight(); + + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + TextView tab_title = (TextView) currentTabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextSizeNormal); + float textWidth = mTextPaint.measureText(tab_title.getText().toString()); + margin = (right - left - textWidth) / 2; + } + + if (this.mCurrentTab < mTabCount - 1) { + View nextTabView = mTabsContainer.getChildAt(this.mCurrentTab + 1); + float nextTabLeft = nextTabView.getLeft(); + float nextTabRight = nextTabView.getRight(); + + left = left + mCurrentPositionOffset * (nextTabLeft - left); + right = right + mCurrentPositionOffset * (nextTabRight - right); + + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + TextView next_tab_title = (TextView) nextTabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextSizeNormal); + float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString()); + float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2; + margin = margin + mCurrentPositionOffset * (nextMargin - margin); + } + } + + mIndicatorRect.left = (int) left; + mIndicatorRect.right = (int) right; + //for mIndicatorWidthEqualTitle + if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) { + mIndicatorRect.left = (int) (left + margin - 1); + mIndicatorRect.right = (int) (right - margin - 1); + } + + mTabRect.left = (int) left; + mTabRect.right = (int) right; + + if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip + + } else {//indicatorWidth大于0时,圆角矩形以及三角形 + float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2; + + if (this.mCurrentTab < mTabCount - 1) { + View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1); + indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2); + } + + mIndicatorRect.left = (int) indicatorLeft; + mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (isInEditMode() || mTabCount <= 0) { + return; + } + + int height = getHeight(); + int paddingLeft = getPaddingLeft(); + // draw divider + if (mDividerWidth > 0) { + mDividerPaint.setStrokeWidth(mDividerWidth); + mDividerPaint.setColor(mDividerColor); + for (int i = 0; i < mTabCount - 1; i++) { + View tab = mTabsContainer.getChildAt(i); + canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint); + } + } + + // draw underline + if (mUnderlineHeight > 0) { + mRectPaint.setColor(mUnderlineColor); + if (mUnderlineGravity == Gravity.BOTTOM) { + canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint); + } else { + canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint); + } + } + + //draw indicator line + + calcIndicatorRect(); + if (mIndicatorStyle == STYLE_TRIANGLE) { + if (mIndicatorHeight > 0) { + mTrianglePaint.setColor(mIndicatorColor); + mTrianglePath.reset(); + mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight); + mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height); + mTrianglePath.close(); + canvas.drawPath(mTrianglePath, mTrianglePaint); + } + } else if (mIndicatorStyle == STYLE_BLOCK) { + if (mIndicatorHeight < 0) { + mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom; + } else { + + } + + if (mIndicatorHeight > 0) { + if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) { + mIndicatorCornerRadius = mIndicatorHeight / 2; + } + + mIndicatorDrawable.setColor(mIndicatorColor); + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight), + (int) (mIndicatorMarginTop + mIndicatorHeight)); + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } else { + /* mRectPaint.setColor(mIndicatorColor); + calcIndicatorRect(); + canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight, + mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/ + + if (mIndicatorHeight > 0) { + mIndicatorDrawable.setColor(mIndicatorColor); + + if (mIndicatorGravity == Gravity.BOTTOM) { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + height - (int) mIndicatorMarginBottom); + } else { + mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left, + (int) mIndicatorMarginTop, + paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight, + (int) mIndicatorHeight + (int) mIndicatorMarginTop); + } + mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius); + mIndicatorDrawable.draw(canvas); + } + } + } + + //setter and getter + public void setCurrentTab(int currentTab) { + this.mCurrentTab = currentTab; + mViewPager.setCurrentItem(currentTab); + + } + + public void setCurrentTab(int currentTab, boolean smoothScroll) { + this.mCurrentTab = currentTab; + mViewPager.setCurrentItem(currentTab, smoothScroll); + } + + public void setIndicatorStyle(int indicatorStyle) { + this.mIndicatorStyle = indicatorStyle; + invalidate(); + } + + public void setTabPadding(float tabPadding) { + this.mTabPadding = dp2px(tabPadding); + updateTabStyles(); + } + + public void setTabSpaceEqual(boolean tabSpaceEqual) { + this.mTabSpaceEqual = tabSpaceEqual; + updateTabStyles(); + } + + public void setTabWidth(float tabWidth) { + this.mTabWidth = dp2px(tabWidth); + updateTabStyles(); + } + + public void setIndicatorColor(int indicatorColor) { + this.mIndicatorColor = indicatorColor; + invalidate(); + } + + public void setIndicatorHeight(float indicatorHeight) { + this.mIndicatorHeight = dp2px(indicatorHeight); + invalidate(); + } + + public void setIndicatorWidth(float indicatorWidth) { + this.mIndicatorWidth = dp2px(indicatorWidth); + invalidate(); + } + + public void setIndicatorCornerRadius(float indicatorCornerRadius) { + this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius); + invalidate(); + } + + public void setIndicatorGravity(int indicatorGravity) { + this.mIndicatorGravity = indicatorGravity; + invalidate(); + } + + public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop, + float indicatorMarginRight, float indicatorMarginBottom) { + this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft); + this.mIndicatorMarginTop = dp2px(indicatorMarginTop); + this.mIndicatorMarginRight = dp2px(indicatorMarginRight); + this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom); + invalidate(); + } + + public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) { + this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle; + invalidate(); + } + + public void setUnderlineColor(int underlineColor) { + this.mUnderlineColor = underlineColor; + invalidate(); + } + + public void setUnderlineHeight(float underlineHeight) { + this.mUnderlineHeight = dp2px(underlineHeight); + invalidate(); + } + + public void setUnderlineGravity(int underlineGravity) { + this.mUnderlineGravity = underlineGravity; + invalidate(); + } + + public void setDividerColor(int dividerColor) { + this.mDividerColor = dividerColor; + invalidate(); + } + + public void setDividerWidth(float dividerWidth) { + this.mDividerWidth = dp2px(dividerWidth); + invalidate(); + } + + public void setDividerPadding(float dividerPadding) { + this.mDividerPadding = dp2px(dividerPadding); + invalidate(); + } + + public void setTextsize(float textsize) { + this.mTextsize = sp2px(textsize); + updateTabStyles(); + } + + public void setTextSelectColor(int textSelectColor) { + this.mTextSelectColor = textSelectColor; + updateTabStyles(); + } + + public void setTextUnselectColor(int textUnselectColor) { + this.mTextUnselectColor = textUnselectColor; + updateTabStyles(); + } + + public void setTextBold(int textBold) { + this.mTextBold = textBold; + updateTabStyles(); + } + + public void setTextAllCaps(boolean textAllCaps) { + this.mTextAllCaps = textAllCaps; + updateTabStyles(); + } + + public void setSnapOnTabClick(boolean snapOnTabClick) { + mSnapOnTabClick = snapOnTabClick; + } + + + public int getTabCount() { + return mTabCount; + } + + public int getCurrentTab() { + return mCurrentTab; + } + + public int getIndicatorStyle() { + return mIndicatorStyle; + } + + public float getTabPadding() { + return mTabPadding; + } + + public boolean isTabSpaceEqual() { + return mTabSpaceEqual; + } + + public float getTabWidth() { + return mTabWidth; + } + + public int getIndicatorColor() { + return mIndicatorColor; + } + + public float getIndicatorHeight() { + return mIndicatorHeight; + } + + public float getIndicatorWidth() { + return mIndicatorWidth; + } + + public float getIndicatorCornerRadius() { + return mIndicatorCornerRadius; + } + + public float getIndicatorMarginLeft() { + return mIndicatorMarginLeft; + } + + public float getIndicatorMarginTop() { + return mIndicatorMarginTop; + } + + public float getIndicatorMarginRight() { + return mIndicatorMarginRight; + } + + public float getIndicatorMarginBottom() { + return mIndicatorMarginBottom; + } + + public int getUnderlineColor() { + return mUnderlineColor; + } + + public float getUnderlineHeight() { + return mUnderlineHeight; + } + + public int getDividerColor() { + return mDividerColor; + } + + public float getDividerWidth() { + return mDividerWidth; + } + + public float getDividerPadding() { + return mDividerPadding; + } + + public float getTextsize() { + return mTextsize; + } + + public int getTextSelectColor() { + return mTextSelectColor; + } + + public int getTextUnselectColor() { + return mTextUnselectColor; + } + + public int getTextBold() { + return mTextBold; + } + + public boolean isTextAllCaps() { + return mTextAllCaps; + } + + public TextView getTitleView(int tab) { + View tabView = mTabsContainer.getChildAt(tab); + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + return tv_tab_title; + } + + //setter and getter + + // show MsgTipView + private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private SparseArray mInitSetMap = new SparseArray<>(); + + /** + * 显示未读消息 + * + * @param position 显示tab位置 + * @param num num小于等于0显示红点,num大于0显示数字 + */ + public void showMsg(int position, int num) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + UnreadMsgUtils.show(tipView, num); + + if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) { + return; + } + + setMsgMargin(position, 4, 2); + mInitSetMap.put(position, true); + } + } + + /** + * 显示未读红点 + * + * @param position 显示tab位置 + */ + public void showDot(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + showMsg(position, 0); + } + + /** 隐藏未读消息 */ + public void hideMsg(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + tipView.setVisibility(View.GONE); + } + } + + /** 设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */ + public void setMsgMargin(int position, float leftPadding, float bottomPadding) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + if (tipView != null) { + TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); + mTextPaint.setTextSize(mTextSizeNormal); + float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString()); + float textHeight = mTextPaint.descent() - mTextPaint.ascent(); + MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams(); + lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + dp2px(leftPadding)) : (int) (mTabPadding + textWidth + dp2px(leftPadding)); + lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : 0; + tipView.setLayoutParams(lp); + } + } + + /** 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */ + public MsgView getMsgView(int position) { + if (position >= mTabCount) { + position = mTabCount - 1; + } + View tabView = mTabsContainer.getChildAt(position); + MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); + return tipView; + } + + private OnTabSelectListener mListener; + + public void setOnTabSelectListener(OnTabSelectListener listener) { + this.mListener = listener; + } + + class InnerPagerAdapter extends FragmentPagerAdapter { + private ArrayList fragments = new ArrayList<>(); + private String[] titles; + + public InnerPagerAdapter(FragmentManager fm, ArrayList fragments, String[] titles) { + super(fm); + this.fragments = fragments; + this.titles = titles; + } + + @Override + public int getCount() { + return fragments.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return titles[position]; + } + + @Override + public Fragment getItem(int position) { + return fragments.get(position); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + // 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁 + // super.destroyItem(container, position, object); + } + + @Override + public int getItemPosition(Object object) { + return PagerAdapter.POSITION_NONE; + } + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("instanceState", super.onSaveInstanceState()); + bundle.putInt("mCurrentTab", mCurrentTab); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + mCurrentTab = bundle.getInt("mCurrentTab"); + state = bundle.getParcelable("instanceState"); + if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) { + updateTabSelection(mCurrentTab); + scrollToCurrentTab(); + } + } + super.onRestoreInstanceState(state); + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + protected int sp2px(float sp) { + final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity; + return (int) (sp * scale + 0.5f); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/CustomExpandableText.java b/app/src/main/java/com/yizhuan/erban/ui/widget/CustomExpandableText.java new file mode 100644 index 000000000..e45de7b23 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/CustomExpandableText.java @@ -0,0 +1,256 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseBooleanArray; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Transformation; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +public class CustomExpandableText extends LinearLayout implements View.OnClickListener { + protected TextView mTv; + protected ImageButton mButton; + private boolean mRelayout; + private boolean mCollapsed; + private int mCollapsedHeight; + private int mTextHeightWithMaxLines; + private int mMaxCollapsedLines; + private int mMarginBetweenTxtAndBottom; + private Drawable mExpandDrawable; + private Drawable mCollapseDrawable; + private int mAnimationDuration; + private boolean mAnimating; + private CustomExpandableText.OnExpandStateChangeListener mListener; + private SparseBooleanArray mCollapsedStatus; + private int mPosition; + + public CustomExpandableText(Context context) { + this(context, null); + } + + public CustomExpandableText(Context context, AttributeSet attrs) { + super(context, attrs); + this.mCollapsed = true; + this.init(attrs); + } + + @TargetApi(11) + public CustomExpandableText(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.mCollapsed = true; + this.init(attrs); + } + + public void setOrientation(int orientation) { + super.setOrientation(orientation); + } + + public void onClick(View view) { + if (this.mButton.getVisibility() == VISIBLE) { + this.mCollapsed = !this.mCollapsed; + this.mButton.setImageDrawable(this.mCollapsed ? this.mExpandDrawable : this.mCollapseDrawable); + if (this.mCollapsedStatus != null) { + this.mCollapsedStatus.put(this.mPosition, this.mCollapsed); + } + + this.mAnimating = true; + CustomExpandableText.ExpandCollapseAnimation animation; + if (this.mCollapsed) { + if (this.mCollapsedHeight == 0) + this.mCollapsedHeight = this.getHeight(); + animation = new CustomExpandableText.ExpandCollapseAnimation(this, this.getHeight(), this.mCollapsedHeight); + } else { + if (this.mTextHeightWithMaxLines == 0) + this.mTextHeightWithMaxLines = this.getHeight(); + animation = new CustomExpandableText.ExpandCollapseAnimation(this, this.getHeight(), this.mTextHeightWithMaxLines); + } + + animation.setFillAfter(true); + animation.setAnimationListener(new Animation.AnimationListener() { + public void onAnimationStart(Animation animation) { + } + + public void onAnimationEnd(Animation animation) { + CustomExpandableText.this.clearAnimation(); + CustomExpandableText.this.mAnimating = false; + if (CustomExpandableText.this.mListener != null) { + CustomExpandableText.this.mListener.onExpandStateChanged(CustomExpandableText.this.mTv, !CustomExpandableText.this.mCollapsed); + } + + } + + public void onAnimationRepeat(Animation animation) { + } + }); + this.clearAnimation(); + this.startAnimation(animation); + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + return this.mAnimating; + } + + protected void onFinishInflate() { + super.onFinishInflate(); + this.findViews(); + } + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (this.mRelayout && this.getVisibility() != GONE) { + this.mRelayout = false; + this.mTv.setMaxLines(2147483647); + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (this.mTv.getLineCount() > this.mMaxCollapsedLines) { + this.mTextHeightWithMaxLines = getRealTextViewHeight(this.mTv); + + if (this.mCollapsed) { + this.mTv.setMaxLines(this.mMaxCollapsedLines); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (this.mCollapsed) { + this.mTv.post(() -> + CustomExpandableText.this.mMarginBetweenTxtAndBottom = CustomExpandableText.this.getHeight() - CustomExpandableText.this.mTv.getHeight() + ); + } + + } + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + //避免首次高度获取失败 + if (this.mCollapsedHeight == 0) + this.mCollapsedHeight = this.getMeasuredHeight(); + } + + public void setOnExpandStateChangeListener(@Nullable CustomExpandableText.OnExpandStateChangeListener listener) { + this.mListener = listener; + } + + public void setText(@Nullable CharSequence text) { + this.mRelayout = true; + this.mTv.setText(text); + this.setVisibility(TextUtils.isEmpty(text) ? GONE : VISIBLE); + } + + public void setTextColor(int textColor) { + this.mTv.setTextColor(textColor); + } + + public void setText(@Nullable CharSequence text, @NonNull SparseBooleanArray collapsedStatus, int position) { + this.mCollapsedStatus = collapsedStatus; + this.mPosition = position; + boolean isCollapsed = collapsedStatus.get(position, true); + this.clearAnimation(); + this.mCollapsed = isCollapsed; + this.mButton.setImageDrawable(this.mCollapsed ? this.mExpandDrawable : this.mCollapseDrawable); + this.setText(text); + this.getLayoutParams().height = -2; + this.requestLayout(); + } + + @Nullable + public CharSequence getText() { + return this.mTv == null ? "" : this.mTv.getText(); + } + + private void init(AttributeSet attrs) { + TypedArray typedArray = this.getContext().obtainStyledAttributes(attrs, R.styleable.CustomExpandableText); + this.mMaxCollapsedLines = typedArray.getInt(R.styleable.CustomExpandableText_cus_maxCollapsedLines, 8); + this.mAnimationDuration = typedArray.getInt(R.styleable.CustomExpandableText_cus_animDuration, 300); + this.mExpandDrawable = typedArray.getDrawable(R.styleable.CustomExpandableText_cus_expandDrawable); + this.mCollapseDrawable = typedArray.getDrawable(R.styleable.CustomExpandableText_cus_collapseDrawable); + if (this.mExpandDrawable == null) { + this.mExpandDrawable = getDrawable(this.getContext(), R.drawable.ic_textview_close); + } + + if (this.mCollapseDrawable == null) { + this.mCollapseDrawable = getDrawable(this.getContext(), R.drawable.ic_textview_open); + } + + typedArray.recycle(); + this.setVisibility(GONE); + } + + private void findViews() { + this.mTv = this.findViewById(R.id.cus_expandable_text); + this.mTv.setOnClickListener(this); + this.mButton = this.findViewById(R.id.cus_expand_collapse); + this.mButton.setImageDrawable(this.mCollapsed ? this.mExpandDrawable : this.mCollapseDrawable); + this.mButton.setOnClickListener(this); + } + + private static boolean isPostLollipop() { + return Build.VERSION.SDK_INT >= 21; + } + + @TargetApi(21) + private static Drawable getDrawable(@NonNull Context context, int resId) { + Resources resources = context.getResources(); + return isPostLollipop() ? resources.getDrawable(resId, context.getTheme()) : resources.getDrawable(resId); + } + + private static int getRealTextViewHeight(@NonNull TextView textView) { + int textHeight = textView.getLayout().getLineTop(textView.getLineCount()); + int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom(); + + return textHeight + padding; + } + + public interface OnExpandStateChangeListener { + void onExpandStateChanged(TextView var1, boolean var2); + } + + class ExpandCollapseAnimation extends Animation { + private final View mTargetView; + private final int mStartHeight; + private final int mEndHeight; + + ExpandCollapseAnimation(View view, int startHeight, int endHeight) { + this.mTargetView = view; + this.mStartHeight = startHeight; + this.mEndHeight = endHeight; + this.setDuration((long)CustomExpandableText.this.mAnimationDuration); + } + + protected void applyTransformation(float interpolatedTime, Transformation t) { + int newHeight = (int)((float)(this.mEndHeight - this.mStartHeight) * interpolatedTime + (float)this.mStartHeight); + + if (mStartHeight < mEndHeight) { + CustomExpandableText.this.mTv.setMaxHeight(newHeight + CustomExpandableText.this.mMarginBetweenTxtAndBottom); + this.mTargetView.getLayoutParams().height = newHeight + CustomExpandableText.this.mMarginBetweenTxtAndBottom; + } else { + CustomExpandableText.this.mTv.setMaxHeight(newHeight - CustomExpandableText.this.mMarginBetweenTxtAndBottom); + this.mTargetView.getLayoutParams().height = newHeight; + } + + this.mTargetView.requestLayout(); + } + + public void initialize(int width, int height, int parentWidth, int parentHeight) { + super.initialize(width, height, parentWidth, parentHeight); + } + + public boolean willChangeBounds() { + return true; + } + } +} + diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/DefaultToolBar.java b/app/src/main/java/com/yizhuan/erban/ui/widget/DefaultToolBar.java new file mode 100644 index 000000000..4a78a9d87 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/DefaultToolBar.java @@ -0,0 +1,93 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + *

默认工具toolbar 界面

+ * + * @author Administrator + * @date 2017/11/29 + */ +public class DefaultToolBar extends Toolbar implements View.OnClickListener { + private TextView mTvCenterTitle; + private TextView mTvRightText; + + public DefaultToolBar(Context context) { + this(context, null); + } + + public DefaultToolBar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public DefaultToolBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + inflate(context, R.layout.default_toolbar_layout, this); + //ThemeOverlay.AppCompat.Dark.ActionBar + + MarginLayoutParams layoutParams = new MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + getResources().getDimensionPixelOffset(R.dimen.common_toolbar_height)); + setLayoutParams(layoutParams); + setContentInsetsAbsolute(0, 0); + setContentInsetsRelative(0, 0); + setBackgroundColor(ContextCompat.getColor(context,R.color.white)); + setPopupTheme(R.style.AppTheme_PopupOverlay); + setId(R.id.toolbar); + mTvCenterTitle = (TextView) findViewById(R.id.tv_center_title); + mTvRightText = (TextView) findViewById(R.id.tv_right_text); + + + mTvRightText.setVisibility(GONE); + mTvRightText.setOnClickListener(this); + } + + public void setCenterTitle(int resId) { + mTvCenterTitle.setText(resId); + } + + public void setCenterTitle(CharSequence title) { + mTvCenterTitle.setText(title); + } + + public void setRightText(CharSequence rightText) { + mTvRightText.setVisibility(TextUtils.isEmpty(rightText) ? GONE : VISIBLE); + mTvRightText.setText(rightText); + } + + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.toolbar: + + break; + case R.id.tv_right_text: + if (mOnRightTextClickListener != null) { + mOnRightTextClickListener.onRightTextClick(); + } + break; + default: + } + } + + private OnRightTextClickListener mOnRightTextClickListener; + + public void setOnRightTextClickListener(OnRightTextClickListener onRightTextClickListener) { + mOnRightTextClickListener = onRightTextClickListener; + } + + public interface OnRightTextClickListener { + void onRightTextClick(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/DividerItemDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/DividerItemDecoration.java new file mode 100644 index 000000000..0138b9555 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/DividerItemDecoration.java @@ -0,0 +1,115 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.TypedValue; +import android.view.View; + + +/** + * Created by moon.zhong on 2015/2/11. + */ +public class DividerItemDecoration extends RecyclerView.ItemDecoration{ + + /* + * RecyclerView的布局方向,默认先赋值 + * 为纵向布局 + * RecyclerView 布局可横向,也可纵向 + * 横向和纵向对应的分割想画法不一样 + * */ + private int mOrientation = LinearLayoutManager.VERTICAL ; + + /** + * item之间分割线的size,默认为1 + */ + private int mItemSize = 1 ; + + /** + * 绘制item分割线的画笔,和设置其属性 + * 来绘制个性分割线 + */ + private Paint mPaint ; + + /** + * 构造方法传入布局方向,不可不传 + * @param context + * @param orientation + */ + public DividerItemDecoration(Context context, int orientation, int mItemSize, int colorResId) { + this.mOrientation = orientation; + this.mItemSize = mItemSize; + if(orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL){ + throw new IllegalArgumentException("请传入正确的参数") ; + } + mItemSize = (int) TypedValue.applyDimension(mItemSize, TypedValue.COMPLEX_UNIT_DIP,context.getResources().getDisplayMetrics()); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG) ; + mPaint.setColor(context.getResources().getColor(colorResId)); + /*设置填充*/ + mPaint.setStyle(Paint.Style.FILL); + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + if(mOrientation == LinearLayoutManager.VERTICAL){ + drawVertical(c,parent) ; + }else { + drawHorizontal(c,parent) ; + } + } + + /** + * 绘制纵向 item 分割线 + * @param canvas + * @param parent + */ + private void drawVertical(Canvas canvas, RecyclerView parent){ + final int left = parent.getPaddingLeft() ; + final int right = parent.getMeasuredWidth() - parent.getPaddingRight() ; + final int childSize = parent.getChildCount() ; + for(int i = 0 ; i < childSize ; i ++){ + final View child = parent.getChildAt( i ) ; + RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int top = child.getBottom() + layoutParams.bottomMargin ; + final int bottom = top + mItemSize ; + canvas.drawRect(left,top,right,bottom,mPaint); + } + } + + /** + * 绘制横向 item 分割线 + * @param canvas + * @param parent + */ + private void drawHorizontal(Canvas canvas, RecyclerView parent){ + final int top = parent.getPaddingTop() ; + final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom() ; + final int childSize = parent.getChildCount() ; + for(int i = 0 ; i < childSize ; i ++){ + final View child = parent.getChildAt( i ) ; + RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int left = child.getRight() + layoutParams.rightMargin ; + final int right = left + mItemSize ; + canvas.drawRect(left,top,right,bottom,mPaint); + } + } + + /** + * 设置item分割线的size + * @param outRect + * @param view + * @param parent + * @param state + */ + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + if(mOrientation == LinearLayoutManager.VERTICAL){ + outRect.set(0,0,0,mItemSize); + }else { + outRect.set(0,0,mItemSize,0); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/DividerUtil.java b/app/src/main/java/com/yizhuan/erban/ui/widget/DividerUtil.java new file mode 100644 index 000000000..583d000ff --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/DividerUtil.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.ui.widget; + +import android.graphics.Rect; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.yizhuan.xchat_android_library.utils.SizeUtils; + +public class DividerUtil { + public static void addhorizontalDivider(RecyclerView recyclerView, float dp) { + final int px = SizeUtils.dp2px(recyclerView.getContext(), dp); + recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + outRect.set(0, 0, px, 0); + } + }); + } + + /** + * + * 添加水平间隔 + * @param dp 普通间隔 比如有个些界面10dp间隔 + * @param lastDp 最后一项间隔,为15dp + */ + public static void addhorizontalDivider(RecyclerView recyclerView, float dp, float lastDp) { + final int px = SizeUtils.dp2px(recyclerView.getContext(), dp); + final int lastPx = SizeUtils.dp2px(recyclerView.getContext(), lastDp); + recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + //最后一项的间距重新画 + int position = parent.getChildAdapterPosition(view); + if (lastPx > 0 && position == (parent.getAdapter().getItemCount() - 1)) { + outRect.set(0, 0, lastPx, 0); + } else { + outRect.set(0, 0, px, 0); + } + + } + }); + } + + /** + * 先简单添加,后续再优化成通用方法 + * @param recyclerView recyclerView + * @param dp dp + */ + public static void addGridlDivider(RecyclerView recyclerView, float dp) { + final int px = SizeUtils.dp2px(recyclerView.getContext(), dp); + int spanCount = ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount(); + recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int pos = parent.getChildAdapterPosition(view); + int top; + if (pos < spanCount) { // 第一行 + top = px; + } else { + top = 0; + } + int left, right; + if (pos % spanCount == 0) { //第一列 + left = 0; + right = px / 2; + } else { + left = px / 2; + right = 0; + } + outRect.set(left, top, right, px); + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/FixedTouchViewPager.java b/app/src/main/java/com/yizhuan/erban/ui/widget/FixedTouchViewPager.java new file mode 100644 index 000000000..2dc317570 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/FixedTouchViewPager.java @@ -0,0 +1,61 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.yizhuan.xchat_android_library.utils.log.MLog; + + +/** + * Created by wa on 14-9-28. + */ +public class FixedTouchViewPager extends ViewPager { + private boolean isCanScroll = true; + + public FixedTouchViewPager(Context context) { + super(context); + } + + public FixedTouchViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + try { + if(!isCanScroll){ + return false; + } + return super.onTouchEvent(ev); + } catch (Throwable ex) { + MLog.error(this, "xuwakao, onTouchEvent fix touch viewpager error happens, ev = " + ev); + } + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + try { + if(!isCanScroll){ + return false; + } + return super.onInterceptTouchEvent(ev); + } catch (Exception ex) { + MLog.error(this, "xuwakao, onInterceptTouchEvent fix touch viewpager error happens, ev= " + ev); + } + return false; + } + + public void setCanScroll(boolean isCanScroll){ + this.isCanScroll = isCanScroll; + } + + @Override + public void scrollTo(int x, int y){ + if (isCanScroll){ + super.scrollTo(x, y); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/FlickerAvatarView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/FlickerAvatarView.java new file mode 100644 index 000000000..98901558c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/FlickerAvatarView.java @@ -0,0 +1,103 @@ +package com.yizhuan.erban.ui.widget; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.LayoutFlickerAvatarBinding; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; + +public class FlickerAvatarView extends FrameLayout { + private LayoutFlickerAvatarBinding mBinding; + private Disposable subscribe; + + public FlickerAvatarView(@NonNull Context context) { + this(context, null); + } + + public FlickerAvatarView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + subscribe = Observable.interval(5, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> { + animSmall(mBinding.ivAvatar1); + postDelayed(() -> animSmall(mBinding.ivAvatar2), 500); + postDelayed(() -> animSmall(mBinding.ivAvatar3), 1000); + }); + } + + @Override + protected void onDetachedFromWindow() { + if (subscribe != null) { + subscribe.dispose(); + } + super.onDetachedFromWindow(); + } + + private void init() { + inflate(getContext(), R.layout.layout_flicker_avatar, this); + mBinding = DataBindingUtil.bind(findViewById(R.id.root)); + } + + private void animBig(View view) { + ObjectAnimator transY = ObjectAnimator.ofFloat(view, "scaleY", 0, 1); + transY.setDuration(800).start(); + transY.setInterpolator(new AccelerateInterpolator()); + ObjectAnimator transX = ObjectAnimator.ofFloat(view, "scaleX", 0, 1); + transX.setDuration(800).start(); + transX.setInterpolator(new AccelerateInterpolator()); + + } + + private void animSmall(View view) { + ObjectAnimator transY = ObjectAnimator.ofFloat(view, "scaleY", 1, 0); + transY.setDuration(800).start(); + transY.setInterpolator(new AccelerateInterpolator()); + + ObjectAnimator transX = ObjectAnimator.ofFloat(view, "scaleX", 1, 0); + transX.setDuration(800).start(); + transX.setInterpolator(new AccelerateInterpolator()); + + transX.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + animBig(view); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/GiftAvatarAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftAvatarAdapter.java new file mode 100644 index 000000000..c958cff63 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftAvatarAdapter.java @@ -0,0 +1,227 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.drawable.GradientDrawable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.coorchice.library.SuperTextView; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_core.room.pk.bean.PKTeamInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by chenran + * on 2017/10/25. + */ + +public class GiftAvatarAdapter extends RecyclerView.Adapter implements View.OnClickListener { + public final static int SELECT_TYPE_WHOLE_MIC = 0; + public final static int SELECT_TYPE_MULTI_MIC = 1; + + private List micMemberInfos; + private Context context; + private OnItemSelectedListener onItemSelectedListener; + private int selectType = SELECT_TYPE_MULTI_MIC;//0:全麦,1: 非全麦 + + + public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) { + this.onItemSelectedListener = onItemSelectedListener; + } + + public GiftAvatarAdapter(Context context) { + this.context = context; + } + + public void setMicMemberInfos(List micMemberInfos) { + this.micMemberInfos = micMemberInfos; + } + + public void setSelectType(int selectType) { + this.selectType = selectType; + } + + public int getSelectType() { + return selectType; + } + + public List getSelectedMember() { + if (selectType == SELECT_TYPE_WHOLE_MIC) { + return micMemberInfos; + } else { + List selectedMembers = new ArrayList<>(); + for (MicMemberInfo micMemberInfo : micMemberInfos) { + if (micMemberInfo.isSelected()) { + selectedMembers.add(micMemberInfo); + } + } + return selectedMembers; + } + } + + @Override + public GiftAvatarAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()). + inflate(R.layout.list_item_gift_avatar, parent, false); + return new GiftAvatarAdapter.ViewHolder(item); + } + + @Override + public void onBindViewHolder(GiftAvatarAdapter.ViewHolder holder, int position) { + holder.avatarContainer.setTag(holder.getAdapterPosition()); + if (position == 0) { + holder.allMicState.setVisibility(View.GONE); + holder.micNumber.setVisibility(View.GONE); + holder.tvRoomOwner.setVisibility(View.GONE); + holder.avatar.setBorderWidth(0); + holder.avatar.setImageResource( + selectType == SELECT_TYPE_WHOLE_MIC ? R.drawable.icon_gift_all_mic_ture : R.drawable.icon_gift_all_mic_false); + holder.avatarCover.setVisibility(View.GONE); + holder.roomOwnerCover.setVisibility(View.GONE); + holder.micNumberCover.setVisibility(View.GONE); + } else { + final MicMemberInfo micMemberInfo = micMemberInfos.get(position - 1); + holder.allMicState.setVisibility(View.GONE); + ImageLoadUtils.loadAvatar(holder.avatar.getContext(), micMemberInfo.getAvatar(), holder.avatar); + // 强制给一个透明的边框,避免因为复用导致的出现边框 + holder.avatar.setBorderColor(context.getResources().getColor(R.color.transparent)); + // 房主位 + if (micMemberInfo.getMicPosition() == -1) { + holder.tvRoomOwner.setVisibility(View.VISIBLE); + if (micMemberInfo.isInPkMode()) { + int boardColor = context.getResources().getColor(R.color.color_FFFFFF); + GradientDrawable drawable = (GradientDrawable) holder.tvRoomOwner.getBackground(); + if (micMemberInfo.getTeamId() == PKTeamInfo.TEAM_RED) { + boardColor = context.getResources().getColor(R.color.color_female_FE3F77); + drawable.setColor(boardColor); + } else if (micMemberInfo.getTeamId() == PKTeamInfo.TEAM_BLUE) { + boardColor = context.getResources().getColor(R.color.color_male_16AEFD); + drawable.setColor(boardColor); + } else { + drawable.setColor(context.getResources().getColor(R.color.appColor)); + } + holder.avatar.setBorderColor(boardColor); + } + holder.micNumber.setVisibility(View.GONE); + } else { + // 其他坑位 + holder.tvRoomOwner.setVisibility(View.GONE); + holder.micNumber.setVisibility(View.VISIBLE); + holder.micNumber.setText(String.valueOf(micMemberInfo.getMicPosition() + 1)); + if (micMemberInfo.isInPkMode()) { + int boardColor = context.getResources().getColor(R.color.color_FFFFFF); + int solidColor = context.getResources().getColor(R.color.appColor); + if (micMemberInfo.getTeamId() == PKTeamInfo.TEAM_RED) { + boardColor = solidColor = context.getResources().getColor(R.color.color_female_FE3F77); + } else if (micMemberInfo.getTeamId() == PKTeamInfo.TEAM_BLUE) { + boardColor = solidColor = context.getResources().getColor(R.color.color_male_16AEFD); + } + holder.micNumber.setSolid(solidColor); + holder.avatar.setBorderColor(boardColor); + } + } + if (selectType == SELECT_TYPE_WHOLE_MIC || micMemberInfo.isSelected()) { + //选中 + holder.avatarCover.setVisibility(View.GONE); + holder.roomOwnerCover.setVisibility(View.GONE); + holder.micNumberCover.setVisibility(View.GONE); + holder.avatar.setBorderColor(context.getResources().getColor(R.color.appColor)); + } else { + if (micMemberInfo.getMicPosition() == -1) { + holder.micNumberCover.setVisibility(View.GONE); + holder.roomOwnerCover.setVisibility(View.VISIBLE); + } else { + holder.micNumberCover.setVisibility(View.VISIBLE); + holder.roomOwnerCover.setVisibility(View.GONE); + } + holder.avatarCover.setVisibility(View.VISIBLE); + } + } + } + + @Override + public int getItemCount() { + if (ListUtils.isListEmpty(micMemberInfos)) { + return 0; + } else { + return micMemberInfos.size() + 1; + } + } + + @Override + public void onClick(View v) { + Integer position = (Integer) v.getTag(); + if (position > 0) { + micMemberInfos.get(position - 1).setSelected(!micMemberInfos.get(position - 1).isSelected()); + if (selectType == SELECT_TYPE_WHOLE_MIC && !isSelectAll()) { + selectType = SELECT_TYPE_MULTI_MIC; + } else if (selectType == SELECT_TYPE_MULTI_MIC && isSelectAll()) { + selectType = SELECT_TYPE_WHOLE_MIC; + } + } else { + if (selectType == SELECT_TYPE_WHOLE_MIC && position == 0) { + selectType = SELECT_TYPE_MULTI_MIC; + for (MicMemberInfo micMemberInfo : micMemberInfos) { + micMemberInfo.setSelected(false); + } + micMemberInfos.get(0).setSelected(true); + } else { + selectType = SELECT_TYPE_WHOLE_MIC; + for (MicMemberInfo micMemberInfo : micMemberInfos) { + micMemberInfo.setSelected(true); + } + } + } + notifyDataSetChanged(); + if (onItemSelectedListener != null) { + onItemSelectedListener.onItemSelected(position); + } + } + + private boolean isSelectAll() { + for (MicMemberInfo micMemberInfo : micMemberInfos) { + if (!micMemberInfo.isSelected()) { + return false; + } + } + return true; + } + + public class ViewHolder extends RecyclerView.ViewHolder { + private CircleImageView avatar; + private View avatarCover; + private SuperTextView micNumber; + private TextView allMicState; + private RelativeLayout avatarContainer; + private TextView tvRoomOwner; + private View roomOwnerCover; + private View micNumberCover; + + public ViewHolder(View itemView) { + super(itemView); + avatar = (CircleImageView) itemView.findViewById(R.id.avatar); + avatarCover = itemView.findViewById(R.id.avatar_cover); + micNumber = itemView.findViewById(R.id.mic_number); + allMicState = itemView.findViewById(R.id.all_mic_state); + tvRoomOwner = (TextView) itemView.findViewById(R.id.tv_room_owner); + avatarContainer = (RelativeLayout) itemView.findViewById(R.id.avatar_container); + avatarContainer.setOnClickListener(GiftAvatarAdapter.this); + roomOwnerCover = itemView.findViewById(R.id.room_owner_cover); + micNumberCover = itemView.findViewById(R.id.mic_number_cover); + } + } + + public interface OnItemSelectedListener { + void onItemSelected(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/GiftDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftDialog.java new file mode 100644 index 000000000..a2602b9c7 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftDialog.java @@ -0,0 +1,1398 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.SuppressLint; +import android.arch.lifecycle.Observer; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.ForegroundColorSpan; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.SparseArray; +import android.view.Display; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.common.ui.recyclerview.decoration.SpacingDecoration; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; +import com.yizhuan.erban.BR; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.radish.task.activity.TaskCenterActivity; +import com.yizhuan.erban.radish.wallet.RadishWalletManager; +import com.yizhuan.erban.ui.gift.dialog.GiftInfoVm; +import com.yizhuan.erban.ui.gift.dialog.MagicInfoVm; +import com.yizhuan.erban.ui.gift.dialog.PageIndicatorView; +import com.yizhuan.erban.ui.pay.ChargeActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.dialog.GiftManualQuantityDialog; +import com.yizhuan.erban.ui.widget.higuide.TuTuGuideHelper; +import com.yizhuan.erban.ui.widget.magicindicator.GiftIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.recyclerview.decoration.VerticalDecoration; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.gift.GiftModel; +import com.yizhuan.xchat_android_core.gift.bean.GiftInfo; +import com.yizhuan.xchat_android_core.gift.bean.GiftTab; +import com.yizhuan.xchat_android_core.gift.bean.GiftType; +import com.yizhuan.xchat_android_core.gift.event.UpdateKnapEvent; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.magic.MagicModel; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; +import com.yizhuan.xchat_android_core.magic.exception.MagicOutOfDateException; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.pay.PayModel; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.pay.event.UpdateWalletInfoEvent; +import com.yizhuan.xchat_android_core.radish.RadishModel; +import com.yizhuan.xchat_android_core.radish.RadishWalletInfo; +import com.yizhuan.xchat_android_core.room.pk.model.PkModel; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.net.BalanceNotEnoughExeption; +import com.yizhuan.xchat_android_core.utils.net.FreezeException; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.bindinglist.IItem; +import com.yizhuan.xchat_android_library.bindinglist.MultiTypeAdapter; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.zyyoona7.lib.EasyPopup; +import com.zyyoona7.lib.HorizontalGravity; +import com.zyyoona7.lib.VerticalGravity; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +/** + * @author chenran + * @date 2017/7/27 + */ + +public class GiftDialog extends BottomSheetDialog implements View.OnClickListener, GiftAvatarAdapter.OnItemSelectedListener { + + private static final String TAG = "GiftDialog"; + private Context context; + private ViewPager gridView; + private PageIndicatorView indicatorView; + private RecyclerView avatarList; + private GiftAvatarAdapter avatarListAdapter; + private GiftInfo current; + /** + * 当前选中的魔法礼物 + */ + private MagicInfo currentMagicInfo; + private List currentGiftInfoList; + private List currentMagicInfoList; + + private OnGiftDialogBtnClickListener giftDialogBtnClickListener; + + private CircleImageView avatarImage; + private TextView nickText; + private EasyPopup easyPopup; + private TextView giftNumberText; + private ImageView giftNumberOptions; + private ImageView ivOpenNoble; + private EditText etSendMessage; + private Button sendGiftButton; + private View layoutEmpty; + private View layoutLoading; + private View layoutLoadFiled; + private View loadingView; + private View reloadView; + private GiftIndicator giftIndicator; + private int giftNumber = 1; + private View sendContainer; + private Button btnSendMagic; + + private TextView tvTextGold; + private TextView tvRecharge; + /** + * 被送礼物的人的uid + */ + private long uid; + /** + * 被送礼物的人的昵称 + */ + private String nick; + /** + * 被送礼物的人的头像 + */ + private String avatar; + private List micMemberInfos; + private MicMemberInfo defaultMicMemberInfo; + private View giftNumLayout; + private static boolean isInNormalGiftTab = true; + private SpacingDecoration spacingDecoration; + private Disposable mSubscribe; + private CompositeDisposable compositeDisposable; + private boolean isMagic; + private boolean isInRoom; + /** + * ture则隐藏魔法,默认false + */ + private boolean isHideMagicTab; + /** + * 被选中的uid是否在麦上 + */ + private boolean userOnMic; + + private IItem LastSelectedItem; + private List> pagerList; + + public static String GIFT_DIALOG_FROM = ""; // 埋点用,标识从哪个位置打开弹框 + + public void setGiftDialogBtnClickListener(OnGiftDialogBtnClickListener giftDialogBtnClickListener) { + this.giftDialogBtnClickListener = giftDialogBtnClickListener; + } + + public GiftDialog(Context context, long OtherUid, boolean isInRoom) { + this(context, OtherUid, isInRoom, false); + } + + public GiftDialog(Context context, long OtherUid, boolean isInRoom, boolean isMagic) { + this(context, OtherUid, isInRoom, isMagic, false); + } + + /*** + * + * @param context context + * @param OtherUid 默认选中的人 如果0则表示没选中任何人 + * @param isInRoom true表示在房间内且在麦上,并且此时OtherUid就是默认选中人,礼物框显示麦上用户 + * false表示不在房间,此时OtherUid就是被赠送人的ID + * @param isHideMagicTab true则隐藏魔法,默认false + */ + public GiftDialog(Context context, long OtherUid, boolean isInRoom, boolean isMagic, boolean isHideMagicTab) { + super(context, R.style.ErbanBottomSheetDialogDimFalse); + this.context = context; + this.uid = OtherUid; + this.micMemberInfos = new ArrayList<>(); + this.micMemberInfos.addAll(transformAvatarList(OtherUid)); + this.isInRoom = isInRoom; + this.isMagic = isMagic; + this.isHideMagicTab = isHideMagicTab; + //判断用户在不在麦上 + this.userOnMic = AvRoomDataManager.get().checkIsOnMicByAccount(String.valueOf(uid)); + } + + private List transformAvatarList(long account) { + List micMemberInfos = new ArrayList<>(); + SparseArray micMemberMap = AvRoomDataManager.get().mMicQueueMemberMap; + if (micMemberMap == null) { + micMemberMap = new SparseArray<>(); + } + for (int i = 0; i < micMemberMap.size(); i++) { + MicMemberInfo micMemberInfo = new MicMemberInfo(); + RoomQueueInfo roomQueueInfo = micMemberMap.get(micMemberMap.keyAt(i)); + ChatRoomMember mChatRoomMember = roomQueueInfo.mChatRoomMember; + if (mChatRoomMember == null) continue; + // 合法判断 + if (TextUtils.isEmpty(mChatRoomMember.getAccount()) || + TextUtils.isEmpty(mChatRoomMember.getNick()) || + TextUtils.isEmpty(mChatRoomMember.getAvatar())) continue; + // 排除自己 + if (AvRoomDataManager.get().isOwner(mChatRoomMember.getAccount())) continue; + // 设置默认人员 + if (String.valueOf(account).equals(mChatRoomMember.getAccount())) { + this.defaultMicMemberInfo = micMemberInfo; + micMemberInfo.setSelected(true); + } + // 设置房主 + if (AvRoomDataManager.get().isRoomOwner(mChatRoomMember.getAccount())) { + micMemberInfo.setRoomOwnner(true); + } + + micMemberInfo.setInPkMode(AvRoomDataManager.get().isOpenPKMode()); + micMemberInfo.setTeamId(PkModel.get().getTeamIdInPKMemberList(mChatRoomMember.getAccount())); + micMemberInfo.setNick(mChatRoomMember.getNick()); + micMemberInfo.setAvatar(mChatRoomMember.getAvatar()); + micMemberInfo.setMicPosition(micMemberMap.keyAt(i)); + micMemberInfo.setUid(Long.valueOf(mChatRoomMember.getAccount())); + //添加性别信息 + micMemberInfo.setGender(roomQueueInfo.gender); + micMemberInfos.add(micMemberInfo); + } + + // 离开模式本地添加房主 + if (AvRoomDataManager.get().isLeaveMode() && !AvRoomDataManager.get().isRoomOwner()) { + MicMemberInfo micMemberInfo = new MicMemberInfo(); + micMemberInfo.setRoomOwnner(true); + micMemberInfo.setInPkMode(AvRoomDataManager.get().isOpenPKMode()); + micMemberInfo.setTeamId(PkModel.get().getTeamIdInPKMemberList(String.valueOf(AvRoomDataManager.get().getRoomUid()))); + micMemberInfo.setNick(AvRoomDataManager.get().nick); + micMemberInfo.setAvatar(AvRoomDataManager.get().avatar); + micMemberInfo.setMicPosition(-1); + micMemberInfo.setUid(AvRoomDataManager.get().getRoomUid()); + //添加性别信息 + micMemberInfo.setGender(AvRoomDataManager.get().gender); + micMemberInfos.add(0, micMemberInfo); + } + + return micMemberInfos; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EventBus.getDefault().register(this); + setCanceledOnTouchOutside(true); + setContentView(R.layout.dialog_bottom_gift); + compositeDisposable = new CompositeDisposable(); + init(findViewById(R.id.ll_dialog_bottom_gift)); + FrameLayout bottomSheet = findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + BottomSheetBehavior.from(bottomSheet).setHideable(false); + } + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(params); + mSubscribe = IMNetEaseManager.get().getChatRoomEventObservable().subscribe(this::onReceiveRoomEvent); + } + + @Override + protected void onStop() { + super.onStop(); + GIFT_DIALOG_FROM = ""; + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + int event = roomEvent.getEvent(); + switch (event) { + case RoomEvent.GIFT_OUT_OF_DATE: + onGiftOutOfDate(roomEvent.getMessage()); + break; + default: + break; + } + + } + + @SuppressLint("CheckResult") + private void init(View root) { + root.findViewById(R.id.tv_recharge).setOnClickListener(this); + sendGiftButton = root.findViewById(R.id.btn_send); + layoutEmpty = root.findViewById(R.id.layout_empty); + layoutLoading = root.findViewById(R.id.layout_loading); + layoutLoadFiled = root.findViewById(R.id.layout_load_failed); + reloadView = root.findViewById(R.id.tv_reload); + reloadView.setOnClickListener(this); + loadingView = root.findViewById(R.id.iv_loading); + showLoadingView(); + showLoadingAnimation(); + sendGiftButton.setOnClickListener(this); + root.findViewById(R.id.gift_number_layout).setOnClickListener(this); + initEasyPop(); + + giftNumLayout = root.findViewById(R.id.gift_number_layout); + List tabInfoList = new ArrayList<>(); + tabInfoList.add(new GiftTab(GiftIndicator.TYPE_NORMAL, "礼物", "礼物")); + tabInfoList.add(new GiftTab(GiftIndicator.TYPE_NOBLE, "贵族", "贵族")); + tabInfoList.add(new GiftTab(GiftIndicator.TYPE_MAGIC, "魔法", "魔法")); + tabInfoList.add(new GiftTab(GiftIndicator.TYPE_KNAP, "背包", "背包")); + giftIndicator = root.findViewById(R.id.gift_indicator); + giftIndicator.initTab( + tabInfoList, + context.getResources().getColor(R.color.white_transparent_30), + context.getResources().getColor(R.color.white) + ); + //noinspection ResultOfMethodCallIgnored + giftIndicator.addClick() + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::updateGiftView); + + if (isMagic) { //如果是送魔法,则直接指向魔法的tab + giftIndicator.setPosition(GiftIndicator.TYPE_MAGIC); + } else { + giftIndicator.setPosition(GiftIndicator.TYPE_NORMAL); + } + if (isHideMagicTab) { + giftIndicator.hidePosition(GiftIndicator.TYPE_MAGIC); + } else { + giftIndicator.showPosition(GiftIndicator.TYPE_MAGIC); + } + gridView = root.findViewById(R.id.gridView); + indicatorView = root.findViewById(R.id.indicator); + indicatorView.setVisibility(View.INVISIBLE); + tvTextGold = root.findViewById(R.id.tv_text_gold); + tvRecharge = root.findViewById(R.id.tv_recharge); + + giftNumberText = root.findViewById(R.id.gift_number_text); + giftNumberOptions = root.findViewById(R.id.iv_gift_number_options); + avatarImage = root.findViewById(R.id.avatar); + nickText = root.findViewById(R.id.nick); + avatarList = root.findViewById(R.id.avatar_list); + LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); + avatarList.setLayoutManager(mLayoutManager); + avatarList.addItemDecoration(new VerticalDecoration(UIUtil.dip2px(context, 10), false, true)); + + ivOpenNoble = root.findViewById(R.id.iv_open_noble); + etSendMessage = root.findViewById(R.id.et_gift_message); + ivOpenNoble.setOnClickListener(this); + sendContainer = root.findViewById(R.id.send_container); + btnSendMagic = root.findViewById(R.id.btn_sendMagic); + btnSendMagic.setOnClickListener(this); + layoutEmpty.setVisibility(View.GONE); + // 更新所有礼物 + updateGiftView(giftIndicator.getCurrrentType()); + goldWalletInfo = PayModel.get().getCurrentWalletInfo(); + // 如果自己是贵族,则不需要显示开通贵族的入口 + UserInfo myUserInfo = UserModel.get().getCacheLoginUserInfo(); + if (myUserInfo != null) { + if (myUserInfo.getNobleInfo() != null && myUserInfo.getNobleInfo().getLevel() > 0) { + ivOpenNoble.setVisibility(View.GONE); + } else { + ivOpenNoble.setVisibility(View.VISIBLE); + } + } + + View descLayout = root.findViewById(R.id.desc_layout); + + if (isInRoom && (userOnMic || (uid == 0))) { + avatarList.setVisibility(View.VISIBLE); + descLayout.setVisibility(View.GONE); + if (micMemberInfos != null && micMemberInfos.size() > 0) { + avatarListAdapter = new GiftAvatarAdapter(getContext()); + avatarListAdapter.setMicMemberInfos(micMemberInfos); + avatarListAdapter.setOnItemSelectedListener(this); + avatarList.setAdapter(avatarListAdapter); + + //添加高亮引导 + if (TuTuGuideHelper.isNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_GIFT_DIALOG)) { + avatarList.post(() -> { + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (!GiftDialog.this.isShowing()) { + return; + } + TuTuGuideHelper.setNoNeedHiGuide(TuTuGuideHelper.KEY_GUIDE_GIFT_DIALOG); + TuTuGuideHelper helper = new TuTuGuideHelper(context, GiftDialog.this); + helper.createHiGuide(() -> helper.createGiftDialogOverLayer(avatarList)); + }); + } + } + } else { + avatarList.setVisibility(View.INVISIBLE); + descLayout.setVisibility(View.VISIBLE); + + Single single = UserModel.get().getUserInfo(uid); + + if (context instanceof RxAppCompatActivity) { + single = single.compose(((RxAppCompatActivity) context).bindToLifecycle()); + } + single.subscribe(userInfo -> { + nickText.setText(RegexUtil.getPrintableString(userInfo.getNick())); + ImageLoadUtils.loadAvatar(context, userInfo.getAvatar(), avatarImage); + }); + } + + etSendMessage.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (s.toString().trim().length() > 15) { + SingleToastUtil.showToast(getContext().getString(R.string.tips_input_gift_message_limit)); + sendGiftButton.setEnabled(false); + } + } + }); + + compositeDisposable.add(GiftModel.get().requestKnapGiftInfos().subscribe()); + compositeDisposable.add(getMagicData()); + + radishObserver = info -> { + if (info == null) { + return; + } + radishWalletInfo = info; + setRadishText(); + }; + RadishWalletManager.get().getLdRadishNumber().observeForever(radishObserver); + RadishModel.get().updateRadishWallet().subscribe(); + } + + @NonNull + private Disposable getMagicData() { + return MagicModel.get().getRemoteMagicList() + .subscribe(new Consumer>() { + @Override + public void accept(List magicInfos) throws Exception { + currentMagicInfoList = magicInfos; + if (giftIndicator.getCurrrentType() == GiftIndicator.TYPE_MAGIC) { + updateGiftView(GiftIndicator.TYPE_MAGIC); + } + } + }); + } + + private void showLoadingAnimation() { + Animation rotateAnimation = new RotateAnimation(0, 360, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation.setFillAfter(true); + rotateAnimation.setDuration(1000); + rotateAnimation.setRepeatCount(-1); + rotateAnimation.setInterpolator(new LinearInterpolator()); + loadingView.startAnimation(rotateAnimation); + } + + private Observer radishObserver; + + private RadishWalletInfo radishWalletInfo; + + private WalletInfo goldWalletInfo; + + private int itemType = ITEM_TYPE_GOLD; + private static final int ITEM_TYPE_GOLD = 0; // 金币 + private static final int ITEM_TYPE_RADISH = 1; // 萝卜 + + private void setGoldOrRadishText(IItem lastSelectedItem) { + itemType = ITEM_TYPE_GOLD; + + if (lastSelectedItem == null) { + setTvGoldText(); + return; + } + + if (lastSelectedItem instanceof GiftInfoVm) { + GiftInfoVm giftInfoVm = (GiftInfoVm) lastSelectedItem; + GiftInfo giftInfo = giftInfoVm.data; + sendGiftButton.setEnabled(true); + switch (giftInfo.getConsumeType()) { + case GiftInfo.CONSUME_TYPE_GOLD: + setTvGoldText(); + break; + + case GiftInfo.CONSUME_TYPE_RADISH: + setRadishText(); + break; + + default: + // 未匹配的类型,不允许进行交易 + sendGiftButton.setEnabled(false); + setUpdateTipsText(); + } + } else if (lastSelectedItem instanceof MagicInfoVm) { + MagicInfoVm magicInfoVm = (MagicInfoVm) lastSelectedItem; + MagicInfo magicInfo = magicInfoVm.data; + btnSendMagic.setEnabled(true); + switch (magicInfo.getConsumeType()) { + case GiftInfo.CONSUME_TYPE_GOLD: + setTvGoldText(); + break; + + case GiftInfo.CONSUME_TYPE_RADISH: + setRadishText(); + break; + + default: + // 未匹配的类型,不允许进行交易 + btnSendMagic.setEnabled(false); + setUpdateTipsText(); + } + } + } + + private void setTvGoldText() { + itemType = ITEM_TYPE_GOLD; + + tvRecharge.setVisibility(View.VISIBLE); + tvRecharge.setText(context.getText(R.string.charge)); + if (goldWalletInfo == null) { + return; + } + String goldNumText = getContext().getString(R.string.gold_num_text, goldWalletInfo.getGoldNum()); + SpannableBuilder builder = new SpannableBuilder(); + builder.append(context.getText(R.string.gift_wallet_overage), new ForegroundColorSpan( + context.getResources().getColor(R.color.white_transparent_50))) + .append(goldNumText); + tvTextGold.setText(builder.build()); + } + + private void setRadishText() { + itemType = ITEM_TYPE_RADISH; + + tvRecharge.setVisibility(View.VISIBLE); + tvRecharge.setText(context.getText(R.string.text_gift_radish_obtain_tips)); + if (radishWalletInfo == null) { + return; + } + String radishNumText = getContext().getString(R.string.how_much_radish, radishWalletInfo.getAmount()); + SpannableBuilder builder = new SpannableBuilder(); + builder.append(context.getText(R.string.gift_wallet_overage), new ForegroundColorSpan( + context.getResources().getColor(R.color.white_transparent_50))) + .append(radishNumText); + tvTextGold.setText(builder.build()); + } + + private void setUpdateTipsText() { + tvRecharge.setVisibility(View.GONE); + tvTextGold.setText(context.getText(R.string.text_need_update)); + } + + private void updateMagicView() { + btnSendMagic.setVisibility(View.VISIBLE); + sendContainer.setVisibility(View.GONE); + current = null; + List nobleGiftInfos = getNobleGiftInfos(); + if (ListUtils.isListEmpty(nobleGiftInfos)) { + giftIndicator.hidePosition(GiftIndicator.TYPE_NOBLE); + } else { + giftIndicator.showPosition(GiftIndicator.TYPE_NOBLE); + } + if (ListUtils.isListEmpty(currentMagicInfoList)) { + showEmptyView(); + return; + } + currentMagicInfo = currentMagicInfoList.get(0); + etSendMessage.setVisibility(View.GONE); + List> pagerList = beanTransformVm(context, currentMagicInfoList, false, 8); + setGridViewData(pagerList); + } + + private void updateGiftView(int position) { + if (position == GiftIndicator.TYPE_MAGIC) { + updateMagicView(); + return; + } + showDataView(); + btnSendMagic.setVisibility(View.GONE); + sendContainer.setVisibility(View.VISIBLE); + currentMagicInfo = null; + // 获得对应的普通礼物/贵族礼物/背包礼物 + List normalGiftInfos = getNormalGiftInfos(); + List nobleGiftInfos = getNobleGiftInfos(); + List knapGiftInfos = GiftModel.get().getKnapList(); + if (position == GiftIndicator.TYPE_KNAP) { + currentGiftInfoList = knapGiftInfos; + } else if (position == GiftIndicator.TYPE_NOBLE) { + currentGiftInfoList = nobleGiftInfos; + } else if (position == GiftIndicator.TYPE_NORMAL) { + currentGiftInfoList = normalGiftInfos; + } + // 有贵族礼物才显示贵族礼物的tab + if (ListUtils.isListEmpty(nobleGiftInfos)) { + giftIndicator.hidePosition(GiftIndicator.TYPE_NOBLE); + } else { + giftIndicator.showPosition(GiftIndicator.TYPE_NOBLE); + } + //是否背包礼物 + final boolean isKnap = (position == GiftIndicator.TYPE_KNAP); + if (ListUtils.isListEmpty(currentGiftInfoList)) { + if (isKnap) { + showEmptyView(); + } else { + showLoadFailedView(); + } + return; + } + current = currentGiftInfoList.get(0); + etSendMessage.setVisibility(current.isSendMsg() ? View.VISIBLE : View.GONE); + pagerList = beanTransformVm(context, currentGiftInfoList, isKnap, 8); + setGridViewData(pagerList); + } + + private void showEmptyView() { + //tab对应的礼物列表为空的情况 + layoutEmpty.setVisibility(View.VISIBLE); + layoutLoadFiled.setVisibility(View.GONE); + layoutLoading.setVisibility(View.GONE); + gridView.setVisibility(View.INVISIBLE); + etSendMessage.setVisibility(View.GONE); + indicatorView.setVisibility(View.INVISIBLE); + } + + private void showLoadFailedView() { + layoutLoading.setVisibility(View.GONE); + layoutLoadFiled.setVisibility(View.VISIBLE); + layoutEmpty.setVisibility(View.GONE); + gridView.setVisibility(View.GONE); + etSendMessage.setVisibility(View.GONE); + indicatorView.setVisibility(View.GONE); + } + + private void showLoadingView() { + layoutLoading.setVisibility(View.VISIBLE); + layoutLoadFiled.setVisibility(View.GONE); + layoutEmpty.setVisibility(View.GONE); + } + + private void showDataView() { + layoutLoading.setVisibility(View.GONE); + layoutLoadFiled.setVisibility(View.GONE); + layoutEmpty.setVisibility(View.GONE); + gridView.setVisibility(View.VISIBLE); + etSendMessage.setVisibility(View.GONE); + indicatorView.setVisibility(View.VISIBLE); + } + + private void setGridViewData(List> pagerList) { + if (ListUtils.isListEmpty(pagerList)) { + return; + } + indicatorView.initIndicator(pagerList.size()); + indicatorView.setSelectedPage(0); + layoutEmpty.setVisibility(View.GONE); + gridView.setVisibility(View.VISIBLE); + indicatorView.setVisibility(pagerList.size() > 1 ? View.VISIBLE : View.INVISIBLE); + SparseArray cacheItemView = new SparseArray<>(); + LastSelectedItem = pagerList.get(0).get(0); + setGoldOrRadishText(LastSelectedItem); + gridView.setAdapter(new PagerAdapter() { + + @Override + public int getCount() { + return pagerList.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int pagePos) { + RecyclerView recyclerView; + MultiTypeAdapter giftAdapter; + if (cacheItemView.get(pagePos) == null) { + recyclerView = new RecyclerView(context); + recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + recyclerView.setLayoutManager(new GridLayoutManager(context, 4)); + giftAdapter = new MultiTypeAdapter(BR.item, true); + recyclerView.setAdapter(giftAdapter); + cacheItemView.put(pagePos, recyclerView); + } else { + recyclerView = cacheItemView.get(pagePos); + giftAdapter = (MultiTypeAdapter) recyclerView.getAdapter(); + } + giftAdapter.clearAllItem(); + giftAdapter.addData(pagerList.get(pagePos)); + giftAdapter.setOnItemClickListener(item -> { + if (item instanceof GiftInfoVm) { + GiftInfoVm giftInfoVm = (GiftInfoVm) item; + if (giftInfoVm.data.isSendMsg()) { + etSendMessage.setVisibility(View.VISIBLE); + } else { + etSendMessage.setVisibility(View.GONE); + } + if (LastSelectedItem != null) { + if (LastSelectedItem instanceof GiftInfoVm) { + ((GiftInfoVm) LastSelectedItem).isSelect.set(false); + } + } + giftInfoVm.isSelect.set(true); + LastSelectedItem = item; + current = giftInfoVm.data; + } else if (item instanceof MagicInfoVm) { + MagicInfoVm magicInfoVm = (MagicInfoVm) item; + if (LastSelectedItem != null) { + if (LastSelectedItem instanceof MagicInfoVm) { + ((MagicInfoVm) LastSelectedItem).isSelect.set(false); + } + } + magicInfoVm.isSelect.set(true); + LastSelectedItem = item; + currentMagicInfo = magicInfoVm.data; + } + setGoldOrRadishText(LastSelectedItem); + }); + container.addView(recyclerView); + return recyclerView; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + RecyclerView recyclerView = cacheItemView.get(position); + MultiTypeAdapter adapter = (MultiTypeAdapter) recyclerView.getAdapter(); + adapter.getAllItems().clear(); + container.removeView(recyclerView); + } + }); + gridView.addOnPageChangeListener(new OnPageSelectedListener() { + @Override + public void onPageSelected(int position) { + if (pagerList.size() > 1) { + indicatorView.setSelectedPage(position); + } + } + }); + } + + private List loadGiftInfoList() { + List giftInfos; + String roomUid = null; + if (isInRoom) { + if (AvRoomDataManager.get().getRoomUid() > 0) { + // 如果在房间内,就用房间的 UID + roomUid = String.valueOf(AvRoomDataManager.get().getRoomUid()); + } else { + // 如果是在公聊大厅,那就用公聊大厅的 UID + roomUid = InitialModel.get().getPublicChatHallUid(); + } + giftInfos = GiftModel.get().getGiftInfosByType(roomUid, GiftType.GAME); + } else { + // 不在房间内,直接在普通的列表里选出房间礼物进行显示 + giftInfos = GiftModel.get().getGiftInfoList(GiftType.GAME); + } + if (ListUtils.isListEmpty(giftInfos)) return new ArrayList<>(); + return giftInfos; + } + + private List getNormalGiftInfos() { + List giftInfos = loadGiftInfoList(); + List infos = new ArrayList<>(); + for (int i = 0; i < giftInfos.size(); i++) { + GiftInfo giftInfo = giftInfos.get(i); + if (!giftInfo.isNobleGift() || giftInfo.getLevel() == 0) { + infos.add(giftInfo); + } + } + return infos; + } + + private List getNobleGiftInfos() { + List giftInfos = loadGiftInfoList(); + List infos = new ArrayList<>(); + for (int i = 0; i < giftInfos.size(); i++) { + GiftInfo giftInfo = giftInfos.get(i); + if (giftInfo.isNobleGift() || giftInfo.getLevel() > 0) { + infos.add(giftInfo); + } + } + return infos; + } + + private void initEasyPop() { + + easyPopup = new EasyPopup(getContext()) + .setContentView(R.layout.dialog_gift_number) + .setFocusAndOutsideEnable(true) + .createPopup(); + + easyPopup.getView(R.id.number_1).setOnClickListener(this); + easyPopup.getView(R.id.number_10).setOnClickListener(this); + easyPopup.getView(R.id.number_66).setOnClickListener(this); + easyPopup.getView(R.id.number_99).setOnClickListener(this); + easyPopup.getView(R.id.number_188).setOnClickListener(this); + easyPopup.getView(R.id.number_520).setOnClickListener(this); + easyPopup.getView(R.id.number_1314).setOnClickListener(this); + easyPopup.getView(R.id.number_manual).setOnClickListener(this); + + easyPopup.setOnDismissListener(() -> giftNumberOptions.animate().rotationBy(180).start()); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_recharge: + + if (itemType == ITEM_TYPE_GOLD) { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_GIFT_PANEL_TO_RECHARGE, "礼物面板_去充值:" + GIFT_DIALOG_FROM); + + ChargeActivity.start(getContext()); + } else if (itemType == ITEM_TYPE_RADISH) { + TaskCenterActivity.start(context, TaskCenterActivity.FromPage.GIFT); + } + + dismiss(); + break; + //送魔法 + case R.id.btn_sendMagic: + btnSendMagic.setEnabled(false); + btnSendMagic.setText("施法中..."); + if (!AuthModel.get().isImLogin()) { + SingleToastUtil.showToast("网络异常,请重试!"); + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + return; + } + if (currentMagicInfo == null) { + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + return; + } + if (!isInRoom) { + if (giftDialogBtnClickListener != null) { + giftDialogBtnClickListener.onSendMagicBtnClick(currentMagicInfo, uid, + new SenGiftCallback() { + @Override + public void onSuccess() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + + @Override + public void onFail() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + }); + } + return; + } + if (!userOnMic && uid > 0) { + //用户不在麦上 + sendSingleMagic(currentMagicInfo, uid, new SenGiftCallback() { + @Override + public void onSuccess() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + + @Override + public void onFail() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + }); + return; + } + //以下是房间内的操作 + if (avatarListAdapter == null || micMemberInfos.size() == 0) { +// Toast.makeText(context, "暂无成员在麦上", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("暂无成员在麦上"); + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + dismiss(); + return; + } + List selectedMember = avatarListAdapter.getSelectedMember(); + if (selectedMember == null || ListUtils.isListEmpty(selectedMember)) { +// Toast.makeText(context, "请选择要送魔法的人", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请选择要送魔法的人"); + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + return; + } + + sendBatchMagic(currentMagicInfo, 1, selectedMember, + avatarListAdapter.getSelectType() == GiftAvatarAdapter.SELECT_TYPE_WHOLE_MIC, + new SenGiftCallback() { + @Override + public void onSuccess() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + + @Override + public void onFail() { + if (btnSendMagic == null) return; + btnSendMagic.setText("施法"); + btnSendMagic.setEnabled(true); + } + }); + break; + //送礼物 + case R.id.btn_send: + sendGiftButton.setEnabled(false); + sendGiftButton.setText("赠送中..."); + Log.e(TAG, "onClick: indicator type: " + giftIndicator.getCurrrentType()); + if (!AuthModel.get().isImLogin()) { + SingleToastUtil.showToast("网络异常,请重试!"); + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + return; + } + if (current == null || giftDialogBtnClickListener == null) { + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + return; + } + String giftMessage = getGiftMessage(); + if (Objects.equals(giftMessage, "")) { +// Toast.makeText(context, "请输入喊话内容", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入喊话内容"); + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } else { + if (!isInRoom) {//不在房间的情况 + List targetUids = new ArrayList<>(); + MicMemberInfo micMemberInfo = new MicMemberInfo(); + micMemberInfo.setUid(uid); + targetUids.add(micMemberInfo); + Log.e(TAG, "onClick: indicator type: " + giftIndicator.getCurrrentType()); + giftDialogBtnClickListener.onSendGiftBtnClick(current, targetUids, giftNumber, giftMessage, + giftIndicator.getCurrrentType() == GiftIndicator.TYPE_KNAP, false, + new SenGiftCallback() { + @Override + public void onSuccess() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + + @Override + public void onFail() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + }); + etSendMessage.setText(""); + return; + } + if (!userOnMic && uid > 0) { + List targetUids = new ArrayList<>(); + MicMemberInfo micMemberInfo = new MicMemberInfo(); + micMemberInfo.setUid(uid); + targetUids.add(micMemberInfo); + Log.e(TAG, "onClick: indicator type: " + giftIndicator.getCurrrentType()); + giftDialogBtnClickListener.onSendGiftBtnClick(current, targetUids, + giftNumber, giftMessage, + giftIndicator.getCurrrentType() == GiftIndicator.TYPE_KNAP, + false, + new SenGiftCallback() { + @Override + public void onSuccess() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + + @Override + public void onFail() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + }); + etSendMessage.setText(""); + } else if (avatarListAdapter != null && avatarListAdapter.getSelectedMember().size() > 0) { + List selectedMembers = avatarListAdapter.getSelectedMember(); + + if (giftIndicator.getCurrrentType() == GiftIndicator.TYPE_KNAP + && giftNumber * selectedMembers.size() > current.getCount()) { +// Toast.makeText(context, "礼物数量不足", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("礼物数量不足"); + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + return; + } + giftDialogBtnClickListener.onSendGiftBtnClick(current, selectedMembers, giftNumber, giftMessage, + giftIndicator.getCurrrentType() == GiftIndicator.TYPE_KNAP, + avatarListAdapter.getSelectType() == GiftAvatarAdapter.SELECT_TYPE_WHOLE_MIC, + new SenGiftCallback() { + @Override + public void onSuccess() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + + @Override + public void onFail() { + if (sendGiftButton == null) return; + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + }); + + etSendMessage.setText(""); + } else if (micMemberInfos.size() == 0) { +// Toast.makeText(context, "暂无成员在麦上", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("暂无成员在麦上"); + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + dismiss(); + } else { +// Toast.makeText(context, "请选择送礼物的人", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请选择送礼物的人"); + sendGiftButton.setText("赠送"); + sendGiftButton.setEnabled(true); + } + } + + break; + case R.id.number_1: + updateNumber(1); + break; + case R.id.number_10: + updateNumber(10); + break; + case R.id.number_66: + updateNumber(66); + break; + case R.id.number_99: + updateNumber(99); + break; + case R.id.number_188: + updateNumber(188); + break; + case R.id.number_520: + updateNumber(520); + break; + case R.id.number_1314: + updateNumber(1314); + break; + case R.id.number_manual: + GiftManualQuantityDialog giftManualQuantityDialog = new GiftManualQuantityDialog(context); + giftManualQuantityDialog.setOnConfirmClick(new GiftManualQuantityDialog.OnConfirmClick() { + @Override + public void onConfirm(int quantity) { + updateNumber(quantity); + giftManualQuantityDialog.dismiss(); + } + }); + giftManualQuantityDialog.show(); + easyPopup.dismiss(); + break; + case R.id.gift_number_layout: + showEasyPopup(); + break; + case R.id.iv_open_noble: + String query = (current == null || current.getLevel() <= 0) ? "" : "?nobleId=" + current.getLevel(); + CommonWebViewActivity.start(context, UriProvider.getNobleIntro() + query); + break; + + case R.id.tv_reload: + reloadData(); + break; + default: + } + } + + private void reloadData() { + showLoadingView(); + int currentType = giftIndicator.getCurrrentType(); + switch (currentType) { + case GiftIndicator.TYPE_NORMAL: + case GiftIndicator.TYPE_NOBLE: + String roomUid = null; + if (isInRoom) { + if (AvRoomDataManager.get().getRoomUid() > 0) { + // 如果在房间内,就用房间的 UID + roomUid = String.valueOf(AvRoomDataManager.get().getRoomUid()); + } else { + // 如果是在公聊大厅,那就用公聊大厅的 UID + roomUid = InitialModel.get().getPublicChatHallUid(); + } + } + compositeDisposable.add(GiftModel.get().refreshGiftList(roomUid) + .subscribe((giftListInfoServiceResult, throwable) -> { + if (throwable == null) { + // 返回结果时,当前选中选项与请求时的选项一样时才显示 + if (currentType == giftIndicator.getCurrrentType()) { + updateGiftView(giftIndicator.getCurrrentType()); + } + } else { + showLoadFailedView(); + } + }) + ); + break; + + case GiftIndicator.TYPE_KNAP: + compositeDisposable.add(GiftModel.get() + .requestKnapGiftInfos() + .subscribe((listServiceResult, throwable) -> { + if (throwable == null) { + if (currentType == giftIndicator.getCurrrentType()) { + updateGiftView(giftIndicator.getCurrrentType()); + } + } else { + showLoadFailedView(); + } + }) + ); + break; + + case GiftIndicator.TYPE_MAGIC: + compositeDisposable.add(getMagicData()); + break; + } + } + + @SuppressLint("CheckResult") + private void sendBatchMagic(MagicInfo magicInfo, int magicNum, List micMemberInfos, boolean isWholeMic, SenGiftCallback callback) { + List targetUids = new ArrayList<>(); + for (MicMemberInfo memberInfo : micMemberInfos) { + targetUids.add(memberInfo.getUid()); + } + MagicModel.get().sendBatchMagic(magicInfo.getMagicId(), magicNum, targetUids, isWholeMic) + .subscribe((multiMagicReceivedInfo, throwable) -> { + if (multiMagicReceivedInfo != null) { + if (callback != null) { + callback.onSuccess(); + } + System.out.println("发送成功"); + } else { + if (throwable instanceof BalanceNotEnoughExeption) { + needCharge(); + } else if (throwable instanceof MagicOutOfDateException) { + SingleToastUtil.showToast(throwable.getMessage()); + } else if (throwable instanceof FreezeException) { + SingleToastUtil.showToast(throwable.getMessage()); + } else { + throwable.printStackTrace(); + } + if (callback != null) { + callback.onFail(); + } + } + }); + } + + @SuppressLint("CheckResult") + private void sendSingleMagic(MagicInfo magicInfo, long account, SenGiftCallback callback) { + MagicModel.get().sendMagic(magicInfo.getMagicId(), account) + .subscribe((magicReceivedInfo, throwable) -> { + if (magicReceivedInfo != null) { + if (callback != null) { + callback.onSuccess(); + } + System.out.println("发送成功"); + } else { + if (throwable instanceof BalanceNotEnoughExeption) { + needCharge(); + } else if (throwable instanceof MagicOutOfDateException) { + //魔法过期 + SingleToastUtil.showToast(throwable.getMessage()); + } else { + throwable.printStackTrace(); + } + if (callback != null) { + callback.onFail(); + } + } + }); + } + + private void needCharge() { + new DialogManager(context).showOkCancelDialog("余额不足,是否充值", + true, new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_NOT_ENOUGH_TO_RECHARGE, + "余额不足_去充值:送礼物"); + ChargeActivity.start(context); + } + }); + } + + + private String getGiftMessage() { + if (current.isSendMsg()) { + if (etSendMessage.getText().toString().length() == 0) { + return getContext().getString(R.string.tips_input_gift_message); + } else { + if (Objects.equals(etSendMessage.getText().toString().trim(), "")) { + return ""; + } else { + return etSendMessage.getText().toString().trim(); + } + } + } else { + return null; + } + } + + private void updateNumber(int number) { + giftNumber = number; + giftNumberText.setText(giftNumber + ""); + easyPopup.dismiss(); + } + + private void showEasyPopup() { + giftNumberOptions.animate().rotationBy(180).start(); + easyPopup.showAtAnchorView(giftNumLayout, VerticalGravity.ABOVE, HorizontalGravity.ALIGN_LEFT, + 0, -UIUtil.dip2px(context, 11)); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + if (mSubscribe != null) { + mSubscribe.dispose(); + mSubscribe = null; + } + if (compositeDisposable != null) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + if (radishObserver != null) { + RadishWalletManager.get().getLdRadishNumber().removeObserver(radishObserver); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onWalletInfoUpdate(UpdateWalletInfoEvent event) { + goldWalletInfo = PayModel.get().getCurrentWalletInfo(); + setGoldOrRadishText(LastSelectedItem); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRecieveGiftKnapMsg(UpdateKnapEvent event) { + //刷新背包礼物 + compositeDisposable.add(GiftModel.get().requestKnapGiftInfos() + .compose(RxHelper.handleSchedulers()) + .subscribe()); + if (giftIndicator.getCurrrentType() != GiftIndicator.TYPE_KNAP) { + return; + } + int giftId = event.getGiftId(); + int sendNum = event.getSendNumber(); + if (ListUtils.isListEmpty(pagerList)) { + return; + } + for (List page : pagerList) { + for (IItem item : page) { + if (!(item instanceof GiftInfoVm)) { + return; + } + GiftInfoVm giftInfoVm = (GiftInfoVm) item; + if (giftInfoVm.data.getGiftId() == giftId) { + int count = giftInfoVm.data.getCount() - sendNum; + giftInfoVm.data.setCount(count < 0 ? 0 : count); + giftInfoVm.updateCount(); + break; + } + } + } + } + + private void onGiftOutOfDate(String message) { + ((BaseActivity) getContext()).toast(message); + } + + @Override + public void onItemSelected(int position) { + avatarList.smoothScrollToPosition(position); + } + + private static List> beanTransformVm(Context context, List data, boolean isKnap, int pageSize) { + List> result = new ArrayList<>(); + if (ListUtils.isListEmpty(data)) { + return result; + } + for (int i = 0; i < data.size(); i++) { + IItem item = null; + List page = null; + if (i % pageSize == 0) { + page = new ArrayList<>(); + result.add(page); + } else { + if (result.size() > 0) { + page = result.get(result.size() - 1); + } + } + if (data.get(i) instanceof GiftInfo) { + item = createGiftItem(context, (GiftInfo) data.get(i), i == 0, isKnap); + } else if (data.get(i) instanceof MagicInfo) { + item = createMagicItem(context, (MagicInfo) data.get(i), i == 0); + } + if (item != null && page != null) { + page.add(item); + } + } + return result; + } + + private static GiftInfoVm createGiftItem(Context context, GiftInfo giftInfo, boolean select, boolean isKnap) { + return new GiftInfoVm(context, giftInfo, select, isKnap); + } + + private static MagicInfoVm createMagicItem(Context context, MagicInfo magicInfo, boolean select) { + return new MagicInfoVm(context, magicInfo, select); + } + + public interface OnGiftDialogBtnClickListener { + + /** + * 新版全麦发礼物事件接口,带喊话功能 + * + * @param giftInfo + * @param micMemberInfos + * @param number + * @param msg + * @param isKnap + * @param isWholeMic + * @param callback + */ + void onSendGiftBtnClick(GiftInfo giftInfo, List micMemberInfos, + int number, String msg, boolean isKnap, + boolean isWholeMic, SenGiftCallback callback); + + /** + * 送魔法 + * + * @param targetUid 被赠送人id + */ + void onSendMagicBtnClick(MagicInfo magicInfo, long targetUid, SenGiftCallback callback); + } + + public interface SenGiftCallback { + void onSuccess(); + + void onFail(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/GiftRecyclerView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftRecyclerView.java new file mode 100644 index 000000000..eee62c589 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/GiftRecyclerView.java @@ -0,0 +1,76 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.ViewConfiguration; + +import com.netease.nim.uikit.common.util.log.LogUtil; + +/** + * @author xiaoyu + * @date 2017/12/12 + */ + +public class GiftRecyclerView extends RecyclerView { + private static final String TAG = "gift"; + + public GiftRecyclerView(Context context) { + super(context); + } + + public GiftRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public GiftRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + private float mLastY; + private float mStartY; + private boolean allowIntercept = true; + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + int pos = ((GridLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // down事件首先阻断父控件的拦截 + getParent().requestDisallowInterceptTouchEvent(true); + // 但是允许父控件后续的拦截 + allowIntercept = true; + mLastY = ev.getY(); + mStartY = ev.getY(); + break; + case MotionEvent.ACTION_MOVE: + LogUtil.e(TAG, "ACTION_MOVE"); + float dy = ev.getY() - mLastY; + float totalY = ev.getY() - mStartY; + if (pos == 0 && getChildAt(0).getTop() == 0) { + if (getChildAt(0).getTop() + dy < 0) { + // 只要内部滑动一次,则往后都不允许父控件拦截 + getParent().requestDisallowInterceptTouchEvent(true); + allowIntercept = false; + } + if (allowIntercept && ViewConfiguration.get(getContext()).getScaledTouchSlop() < totalY) { + getParent().requestDisallowInterceptTouchEvent(false); + } + } else { + // 如果当前第一个完整显示的位置不是0,则允许内部滑动 + allowIntercept = false; + getParent().requestDisallowInterceptTouchEvent(true); + } + mLastY = ev.getY(); + break; + case MotionEvent.ACTION_UP: + LogUtil.e(TAG, "ACTION_UP"); + break; + default: + } + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/GridViewWithoutScroll.java b/app/src/main/java/com/yizhuan/erban/ui/widget/GridViewWithoutScroll.java new file mode 100644 index 000000000..85b1a32fd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/GridViewWithoutScroll.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.GridView; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class GridViewWithoutScroll extends GridView { + + public GridViewWithoutScroll(Context context) { + super(context); + } + + public GridViewWithoutScroll(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public GridViewWithoutScroll(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.O) + public GridViewWithoutScroll(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandHeightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, + MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandHeightSpec); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/InterceptTouchLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/InterceptTouchLayout.java new file mode 100644 index 000000000..7c65dff11 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/InterceptTouchLayout.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +/** + * @author jack + * @Description + * @Date 2019/2/28 + */ +public class InterceptTouchLayout extends FrameLayout { + public InterceptTouchLayout(@NonNull Context context) { + super(context); + } + + public InterceptTouchLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public InterceptTouchLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public InterceptTouchLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return true; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LeftNotiDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LeftNotiDialog.java new file mode 100644 index 000000000..7ff2c395b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LeftNotiDialog.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.ui.widget; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by zhouxiangfeng on 2017/5/13. + */ + +public class LeftNotiDialog extends Dialog implements View.OnClickListener { + + /** + * 上下文 + */ + private Context context; + private WindowManager windowManager; + private int width; + private TextView tvTitle; + private TextView tvOne; + private TextView tvTwo; + private TextView tvCancel; + private TextView tvNoti; + + public LeftNotiDialog(Context context, boolean cancelable, + OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + // TODO Auto-generated constructor stub + this.context = context; + } + + + public LeftNotiDialog(Context context) { + super(context, R.style.BottomSelectDialog); + // TODO Auto-generated constructor stub + this.context = context; + + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + // TODO Auto-generated method stub + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.layout_left_noti_dialog); + findViewById(R.id.ll_content).setOnClickListener(this); + tvNoti = (TextView) findViewById(R.id.tv_noti); + setDialogShowAttributes(context, this);// 设置Dialog显示参数,出入动画 + } + + public static void setDialogShowAttributes(Context context, Dialog dialog) { + + WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//获取窗口管理�? + int mScreenWidth = winManager.getDefaultDisplay().getWidth();//获取屏幕宽度,将此宽度设为要显示的Dialog窗口的宽�? + int mScreenHeight = winManager.getDefaultDisplay().getHeight();//获取屏幕宽度,将此宽度设为要显示的Dialog窗口的宽�? + Window mWindow = dialog.getWindow();//获取Dialog窗口 + mWindow.getDecorView().setPadding(0, 0, 0, 0); + WindowManager.LayoutParams Params = mWindow.getAttributes(); + Params.windowAnimations = R.style.left_dialog_anim_style;//设置窗口出入动画 +// Params.width = mScreenWidth/3; + Params.height = WindowManager.LayoutParams.MATCH_PARENT; +// Params.height = mScreenHeight; + mWindow.setAttributes(Params); + mWindow.setBackgroundDrawableResource(R.color.transparent_black); + mWindow.setGravity(Gravity.LEFT); + } + + public void setNoti(String noti) { + tvNoti.setText(noti); + } + + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + switch (v.getId()) { + case R.id.ll_content: + dismiss(); + break; + + default: + break; + } + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LevelHeadView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LevelHeadView.java new file mode 100644 index 000000000..cf83ab0a2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LevelHeadView.java @@ -0,0 +1,90 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.CircleImageView; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + * Created by zhouxiangfeng on 2017/6/3. + */ + +public class LevelHeadView extends RelativeLayout { + + private final Context context; + private View mView; + private CircleImageView civ_head; + private UserInfo userInfo; + private ImageView iv_trophy_level; + private TextView tv_pay_count; + + public LevelHeadView(Context context) { + super(context); + this.context = context; + init(); + } + + public LevelHeadView(Context context, AttributeSet attrs) { + super(context, attrs); + this.context = context; + init(); + } + + public LevelHeadView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + init(); + } + + public LevelHeadView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + this.context = context; + init(); + } + + private void init() { + mView = LayoutInflater.from(context).inflate(R.layout.layout_level_head, this, true); + civ_head = (CircleImageView) mView.findViewById(R.id.civ_head); + iv_trophy_level = (ImageView) mView.findViewById(R.id.iv_trophy_level); + tv_pay_count = (TextView) mView.findViewById(R.id.tv_pay_count); + } + + public void setCivAvatar(String url) { + GlideApp.with(context).load(url).error(R.drawable.icon_plus_big).into(civ_head); + } + + public void setTrophyLevel(int level) { + switch (level) { + case 1: + GlideApp.with(context).load(R.drawable.icon_first).error(R.drawable.icon_plus_big).into(iv_trophy_level); + break; + + case 2: + GlideApp.with(context).load(R.drawable.icon_second).error(R.drawable.icon_plus_big).into(iv_trophy_level); + break; + + case 3: + GlideApp.with(context).load(R.drawable.icon_third).error(R.drawable.icon_plus_big).into(iv_trophy_level); + break; + } + } + + public void setPayCount(int payCount) { + tv_pay_count.setText(String.valueOf(payCount)); + } + + public void initiate(String avatar, int level, int payCount) { + setCivAvatar(avatar); + setTrophyLevel(level); + setPayCount(payCount); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LevelUpDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LevelUpDialog.java new file mode 100644 index 000000000..263885ff3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LevelUpDialog.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseBindingActivity; +import com.yizhuan.erban.databinding.DialogLevelUpBinding; +import com.yizhuan.xchat_android_library.annatation.ActLayoutRes; + +/** + * Created by huangmeng1 on 2018/6/21. + */ +@ActLayoutRes(R.layout.dialog_level_up) +public class LevelUpDialog extends BaseBindingActivity { + public static void start(Context context, String name, boolean b) { + Intent intent = new Intent(context, LevelUpDialog.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("name", name); + intent.putExtra("isExper", b); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + super.onCreate(savedInstanceState); + } + + @Override + protected void init() { + mBinding.tvIKnow.setOnClickListener(v -> finish()); + boolean isExper = getIntent().getBooleanExtra("isExper", true); + mBinding.setIsExper(isExper); + mBinding.tvLevel.setText(getIntent().getStringExtra("name")); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LinearLayoutManagerWrapper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LinearLayoutManagerWrapper.java new file mode 100644 index 000000000..8148e2d67 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LinearLayoutManagerWrapper.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * Created by huangmeng1 on 2018/4/2. + */ + +public class LinearLayoutManagerWrapper extends LinearLayoutManager { + public LinearLayoutManagerWrapper(Context context) { + super(context); + } + + public LinearLayoutManagerWrapper(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public LinearLayoutManagerWrapper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + } catch (IndexOutOfBoundsException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ListViewWithoutScroll.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ListViewWithoutScroll.java new file mode 100644 index 000000000..9ea4b61f8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ListViewWithoutScroll.java @@ -0,0 +1,40 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.ListView; + +/** + * @author jack + * @Description + * @Date 2018/4/16 + */ + +public class ListViewWithoutScroll extends ListView { + public ListViewWithoutScroll(Context context) { + super(context); + } + + public ListViewWithoutScroll(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ListViewWithoutScroll(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.O) + public ListViewWithoutScroll(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandHeightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, + MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandHeightSpec); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LivingIconView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LivingIconView.java new file mode 100644 index 000000000..b6753b4dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LivingIconView.java @@ -0,0 +1,92 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatImageView; +import android.util.AttributeSet; +import android.view.ViewGroup; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * @author jack + * @Description + * @Date 2018/4/19 + */ + +public class LivingIconView extends AppCompatImageView { + private int color = Color.RED; + + private volatile boolean isPlaying = false; + private volatile boolean isAttched = false; + + private AnimationDrawable drawable; + private int drawableId; + + public LivingIconView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LivingIconView); + drawableId = a.getResourceId(R.styleable.LivingIconView_cus_drawable, R.drawable.living_icon_animation); + a.recycle(); + init(context); + } + + private void init(Context context){ + drawable = (AnimationDrawable) context.getResources().getDrawable(drawableId); + drawable.setOneShot(false); + setScaleType(ScaleType.FIT_CENTER); + setImageDrawable(drawable); + int dp_9 = UIUtil.dip2px(context, 9); + setLayoutParams(new ViewGroup.LayoutParams(dp_9, dp_9)); + } + + public void setColor(int color) { + this.color = color; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + isAttched = true; + if (!isPlaying && drawable != null) {//开启子线程 + isPlaying = true; + drawable.start(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + isAttched = false; + if (drawable != null) { + drawable.stop(); + } + isPlaying = false; + } + + /** + * 开始播放 + */ + public void start() { + if (!isPlaying) { + if (isAttched && drawable != null) { + isPlaying = true; + drawable.start(); + } + } + } + + /** + * 停止子线程,并刷新画布 + */ + public void stop() { + isPlaying = false; + if (drawable != null) { + drawable.stop(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingAdapter.java new file mode 100644 index 000000000..abac9fc71 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingAdapter.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.ui.widget; + +import android.support.annotation.IntDef; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.yizhuan.erban.R; + +import java.util.List; + +/** + *

具有加载更多的adapter

+ * Created by Administrator on 2017/11/13. + */ +public abstract class LoadingAdapter extends RecyclerView.Adapter { + + private static final int FOOTER = 10000; + private static final int NORMAL = 10001; + + public static final int STATUS_LOADING = 10; + public static final int STATUS_LOADED = 11; +// public static final int STATUS_LOADED = 11; + + @IntDef({STATUS_LOADING, STATUS_LOADED}) + public @interface Status { + } + + private int mStatus = STATUS_LOADED; + + private List mDataList; + + + public void setDataList(List dataList) { + mDataList = dataList; + notifyDataSetChanged(); + } + + public void setStatus(@Status int status) { + mStatus = status; + notifyDataSetChanged(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == FOOTER) { + return new LoadingViewHolder(LayoutInflater.from( + parent.getContext()).inflate(R.layout.loading_more_layout, parent, false)); + } else + return onCreateHolder(parent, viewType); + } + + protected abstract RecyclerView.ViewHolder onCreateHolder(ViewGroup parent, int viewType); + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof LoadingViewHolder) return; + onBindHolder(holder, position); + } + + protected abstract void onBindHolder(RecyclerView.ViewHolder holder, int position); + + @Override + public int getItemViewType(int position) { + if (position == getItemCount() - 2 && mStatus == STATUS_LOADING) { + return FOOTER; + } + return NORMAL; + } + + @Override + public int getItemCount() { + return mDataList == null ? 0 : mDataList.size() + (mStatus == STATUS_LOADING ? 1 : 0); + } + + //解决GridLayoutManager 占用问题 + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); + if (manager instanceof GridLayoutManager) { + final GridLayoutManager gridManager = ((GridLayoutManager) manager); + gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return isFooter(position) ? gridManager.getSpanCount() : 1; + } + }); + } + } + + private boolean isFooter(int position) { + return mStatus == STATUS_LOADING && position == getItemCount(); + } + + //处理StaggeredGridLayoutManager 占用问题 + @Override + public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { + super.onViewAttachedToWindow(holder); + if (isStaggeredGridLayout(holder)) { + handleLayoutIfStaggeredGridLayout(holder, holder.getLayoutPosition()); + } + } + + private boolean isStaggeredGridLayout(RecyclerView.ViewHolder holder) { + ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); + return layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams; + } + + private void handleLayoutIfStaggeredGridLayout(RecyclerView.ViewHolder holder, int position) { + if (/*isHeader(position) ||*/ isFooter(position)) { + StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); + p.setFullSpan(true); + } + } + + public static class LoadingViewHolder extends RecyclerView.ViewHolder { + + public LoadingViewHolder(View itemView) { + super(itemView); + } + } + + public static class NormalViewHolder extends RecyclerView.ViewHolder { + + public NormalViewHolder(View itemView) { + super(itemView); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingDialog.java new file mode 100644 index 000000000..0b790a8ec --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/LoadingDialog.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; + +import com.yizhuan.erban.R; + +/** + * @author xiaoyu + * @date 2017/12/13 + */ + +public class LoadingDialog extends AppCompatDialog { + private Context context; + private ImageView ivLoading; + + public LoadingDialog(Context context) { + super(context, R.style.ErbanUserInfoDialog); + this.context = context; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_loading); + setCancelable(false); + setCanceledOnTouchOutside(false); + ivLoading = (ImageView) findViewById(R.id.iv_loading); + Animation animation = AnimationUtils.loadAnimation(context, R.anim.comm_loading); + ivLoading.setAnimation(animation); + animation.start(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MagicAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MagicAdapter.java new file mode 100644 index 000000000..c344c9599 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MagicAdapter.java @@ -0,0 +1,153 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_core.magic.bean.MagicInfo; + +import java.util.List; +import java.util.Locale; + +/** + * @author xiaoyu + */ + +public class MagicAdapter extends RecyclerView.Adapter { + + private List magicInfos; + private Context context; + private int index; + + public MagicInfo getCurrentMagicInfo() { + if (ListUtils.isListEmpty(magicInfos) || + index >= magicInfos.size()) + return null; + else + return magicInfos.get(index); + } + + public List getData() { + return magicInfos; + } + + public void setIndex(int index) { + this.index = index; + } + + public MagicAdapter(Context context, List magicInfos) { + this.magicInfos = magicInfos; + this.context = context; + } + + @Override + public int getItemViewType(int position) { + return magicInfos.get(position).getMagicType(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + int layoutResId; + switch (viewType) { + case MagicInfo.MONSTER_MAGIC: + layoutResId = R.layout.list_item_monster_magic; + break; + + default: + case MagicInfo.ROOM_MAGIC: + layoutResId = R.layout.list_item_magic; + break; + } + View root = LayoutInflater.from(context).inflate(layoutResId, parent, false); + return new MagicViewHolder(root, viewType); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { + if (viewHolder instanceof MagicViewHolder) { + ((MagicViewHolder) viewHolder).bind(position); + } + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public int getItemCount() { + return magicInfos == null ? 0 : magicInfos.size(); + } + + class MagicViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + private ImageView ivMagicIcon; + private TextView tvMagicName; + private TextView tvMagicGold; + private MagicInfo mMagicInfo; + private TextView damageValue; + private View viewSelect; + + MagicViewHolder(View itemView, int viewType) { + super(itemView); + ivMagicIcon = itemView.findViewById(R.id.iv_magic_icon); + tvMagicName = itemView.findViewById(R.id.tv_magic_name); + tvMagicGold = itemView.findViewById(R.id.tv_magic_gold); + if (viewType == MagicInfo.MONSTER_MAGIC) { + damageValue = itemView.findViewById(R.id.tv_magic_damage); + } + itemView.setOnClickListener(this); + viewSelect = itemView.findViewById(R.id.view_room_gift_select); + } + + @Override + public void onClick(View v) { + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(v, position); + } + index = position; + notifyDataSetChanged(); + } + + int position; + + public void bind(int position) { + this.position = position; + mMagicInfo = magicInfos.get(position); + // 魔法icon + GlideApp.with(ivMagicIcon.getContext().getApplicationContext()) + .load(mMagicInfo.getIcon()) + .into(ivMagicIcon); + // 魔法名字 + tvMagicName.setText(mMagicInfo.getName()); + // 魔法金币 + String gold = mMagicInfo.getPrice() + "金币"; + if (mMagicInfo.getMagicType() == MagicInfo.MONSTER_MAGIC) { + gold = String.format(Locale.getDefault(), + context.getString(R.string.format_monster_hunting_magic_value), + String.valueOf(mMagicInfo.getPrice())); + damageValue.setText(String.format(Locale.getDefault(), + context.getString(R.string.format_monster_hunting_impact), + mMagicInfo.getImpactValue())); + } + tvMagicGold.setText(gold); + viewSelect.setSelected(position == index); + } + } + + private OnItemClickListener mOnItemClickListener; + + public void setOnItemClickListener(OnItemClickListener listener) { + mOnItemClickListener = listener; + } + + public interface OnItemClickListener { + void onItemClick(View view, int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MagicRecyclerView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MagicRecyclerView.java new file mode 100644 index 000000000..b916b4812 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MagicRecyclerView.java @@ -0,0 +1,75 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import com.netease.nim.uikit.common.util.log.LogUtil; + +/** + * @author xiaoyu + * @date 2017/12/12 + */ + +public class MagicRecyclerView extends RecyclerView { + private static final String TAG = "gift"; + + public MagicRecyclerView(Context context) { + super(context); + } + + public MagicRecyclerView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public MagicRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + private float mLastY; + private float mStartY; + private boolean allowIntercept = true; + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { +// int pos = ((GridLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); +// switch (ev.getActionMasked()) { +// case MotionEvent.ACTION_DOWN: +// // down事件首先阻断父控件的拦截 +// getParent().requestDisallowInterceptTouchEvent(true); +// // 但是允许父控件后续的拦截 +// allowIntercept = true; +// mLastY = ev.getY(); +// mStartY = ev.getY(); +// break; +// case MotionEvent.ACTION_MOVE: +// LogUtil.e(TAG, "ACTION_MOVE"); +// float dy = ev.getY() - mLastY; +// float totalY = ev.getY() - mStartY; +// if (pos == 0 && getChildAt(0).getTop() == 0) { +// if (getChildAt(0).getTop() + dy < 0) { +// // 只要内部滑动一次,则往后都不允许父控件拦截 +// getParent().requestDisallowInterceptTouchEvent(true); +// allowIntercept = false; +// } +// if (allowIntercept && ViewConfiguration.get(getContext()).getScaledTouchSlop() < totalY) { +// getParent().requestDisallowInterceptTouchEvent(false); +// } +// } else { +// // 如果当前第一个完整显示的位置不是0,则允许内部滑动 +// allowIntercept = false; +// getParent().requestDisallowInterceptTouchEvent(true); +// } +// mLastY = ev.getY(); +// break; +// case MotionEvent.ACTION_UP: +// LogUtil.e(TAG, "ACTION_UP"); +// break; +// default: +// } + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MainRedPointTab.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MainRedPointTab.java new file mode 100644 index 000000000..5d80fef0d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MainRedPointTab.java @@ -0,0 +1,99 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleMessageTouchListener; +import com.netease.nim.uikit.common.ui.draggablebubbles.BubbleView; +import com.netease.nim.uikit.common.ui.draggablebubbles.MessageBubbleView; +import com.yizhuan.erban.R; + +/** + *

main tab 有消息个数 控件 (todo:还可以优化,将字体写在字体上面) + *

+ * Created by Administrator on 2017/11/14. + */ +public class MainRedPointTab extends RelativeLayout { + private int mTabIcon, mTabIconSelect; + private MainTab mMainTab; + private TextView mTvNum; + + private RedPointDismissListener mListener; + + public MainRedPointTab(@NonNull Context context) { + this(context, null); + } + + public MainRedPointTab(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MainRedPointTab(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + inflate(context, R.layout.maint_tab_red_poin_layout, this); + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MainTab); + mTabIcon = typedArray.getResourceId(R.styleable.MainTab_tab_icon, R.mipmap.ic_main_tab_game_home); + mTabIconSelect = typedArray.getResourceId(R.styleable.MainTab_tab_icon_select, R.mipmap.ic_main_tab_game_pressed); + + boolean draggable = typedArray.getBoolean(R.styleable.MainTab_tab_draggable, false); + mMainTab = findViewById(R.id.main_tab_msg); + mMainTab.setmTabIcon(mTabIcon); + mMainTab.setmTabIconSelect(mTabIconSelect); + mTvNum = findViewById(R.id.msg_number); + + if (draggable) { + MessageBubbleView.attach(mTvNum,false, new BubbleMessageTouchListener.BubbleDisappearListener() { + @Override + public void dragStart(View view) { + + } + + @Override + public void dismiss(View view) { + if (mListener != null) { + mListener.dismiss(); + } + } + + @Override + public void dragFinish(View view) { + + } + }); + } + } + + public void select(boolean select) { + mMainTab.select(select); + } + + @SuppressLint("SetTextI18n") + public void setNumber(int number) { + if(mTvNum instanceof BubbleView){ + ((BubbleView) mTvNum).setNumText(number); + return; + } + mTvNum.setVisibility(number <= 0 ? GONE : VISIBLE); + if (number > 99) { + mTvNum.setText("99+"); + } else + mTvNum.setText(String.valueOf(number)); + } + + public void setmListener(RedPointDismissListener mListener) { + this.mListener = mListener; + } + + public interface RedPointDismissListener { + void dismiss(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MainTab.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MainTab.java new file mode 100644 index 000000000..6ff5b75d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MainTab.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.util.AttributeSet; +import android.view.Gravity; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.R; + +/** + *

main tab 控件

+ * Created by Administrator on 2017/11/14. + */ +public class MainTab extends android.support.v7.widget.AppCompatTextView { + private static final int DEFAULT_COLOR = Color.parseColor("#333333"); + private int mTabIcon, mTabIconSelect; + private int mTabtextColor, mTabTextSelectColor; + private String mTabText; + private Context mContext; + + public MainTab(Context context) { + this(context, null); + } + + public MainTab(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MainTab(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + mContext = context; + setGravity(Gravity.CENTER); + setCompoundDrawablePadding(ScreenUtil.dip2px(4)); + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MainTab); + mTabIcon = typedArray.getResourceId(R.styleable.MainTab_tab_icon, R.mipmap.ic_main_tab_game_home); + mTabIconSelect = typedArray.getResourceId(R.styleable.MainTab_tab_icon_select, R.mipmap.ic_main_tab_game_pressed); + + mTabtextColor = typedArray.getColor(R.styleable.MainTab_tab_text_color, DEFAULT_COLOR); + mTabTextSelectColor = typedArray.getColor(R.styleable.MainTab_tab_text_color_select, DEFAULT_COLOR); + mTabText = typedArray.getString(R.styleable.MainTab_tab_text); + typedArray.recycle(); + + select(false); + setText(mTabText); + } + + public void setIcon(int iconResId) { + Drawable mainTabHome = ContextCompat.getDrawable(mContext, iconResId); + + //必须加上这句,否则不显示 + mainTabHome.setBounds(0, 0, mainTabHome.getMinimumWidth(), mainTabHome.getIntrinsicHeight()); + setCompoundDrawables(null, mainTabHome, null, null); + } + + public void setmTabIcon(int tabIcon) { + mTabIcon = tabIcon; + } + + public void setmTabIconSelect(int tabIconSelect) { + mTabIconSelect = tabIconSelect; + } + + public void select(boolean select) { + setTextColor(select ? mTabTextSelectColor : mTabtextColor); + stopAnim(); + if (!select) { + setIcon(mTabIcon); + } else { + setIcon(mTabIconSelect); + } + } + + public void setAnimIcon(int anmiResId) { +// setCompoundDrawablesWithIntrinsicBounds(0, anmiResId, 0, 0); +// setCompoundDrawablesWithIntrinsicBounds(null, animationDrawable, null, null); +// if (animationDrawable != null) { +// animationDrawable.start(); +// } + } + + public void stopAnim() { +// if (animationDrawable != null) { +// animationDrawable.stop(); +// } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MainTabLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MainTabLayout.java new file mode 100644 index 000000000..291d1fe1a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MainTabLayout.java @@ -0,0 +1,167 @@ +package com.yizhuan.erban.ui.widget; + + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.msg.MsgService; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.customer_server.event.CustomerServerMsgEvent; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; + +import org.greenrobot.eventbus.EventBus; + +/** + *

底部tab导航

+ * Created by Administrator on 2017/11/14. + */ +public class MainTabLayout extends LinearLayout implements View.OnClickListener { + + public static final int MAIN_TAB_POS_HOME = 0; + public static final int MAIN_TAB_POS_MSG = 1; + public static final int MAIN_TAB_POS_ATTENTION = 2; + public static final int MAIN_TAB_POS_ME = 3; + public static final int MAIN_TAB_POS_GAME = 4; + + private MainTab mMeTab, gameTab; + private MainRedPointTab mMsgTab; + private MainRedPointTab mAttentionTab; + private int mLastPosition = -1; + + // 切换账号需要重置;接收未读互动消息自定义消息、互动消息未读接口调用需要设置; + private int mUnReadDynamicCount = 0; + + private MainRedPointTab.RedPointDismissListener msgListener = new MainRedPointTab.RedPointDismissListener() { + @Override + public void dismiss() { + EventBus.getDefault().post(new CustomerServerMsgEvent(0)); + NIMClient.getService(MsgService.class).clearAllUnreadCount(); + } + }; + + private MainRedPointTab.RedPointDismissListener attentionListener = new MainRedPointTab.RedPointDismissListener() { + @Override + public void dismiss() { + // TODO 互动消息清空未读 + } + }; + + public MainTabLayout(Context context) { + this(context, null); + } + + public MainTabLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MainTabLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + setOrientation(HORIZONTAL); + inflate(context, R.layout.main_tab_layout, this); + + mAttentionTab = findViewById(R.id.main_attention_tab); + mMsgTab = findViewById(R.id.main_msg_tab); + mMeTab = findViewById(R.id.main_me_tab); + gameTab = findViewById(R.id.main_game_tab); + + gameTab.setOnClickListener(this); + mAttentionTab.setOnClickListener(this); + mMsgTab.setOnClickListener(this); + mMeTab.setOnClickListener(this); + + mAttentionTab.setmListener(attentionListener); + mMsgTab.setmListener(msgListener); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.main_game_tab: + select(MAIN_TAB_POS_GAME); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_FIRST_TAB, + "首页tab"); + break; + case R.id.main_home_tab: + select(MAIN_TAB_POS_HOME); + break; + case R.id.main_attention_tab: + select(MAIN_TAB_POS_ATTENTION); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_FIND_TAB, + "发现tab"); + break; + case R.id.main_msg_tab: + select(MAIN_TAB_POS_MSG); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_MESSAGE_TAB, + "消息tab"); + break; + case R.id.main_me_tab: + select(MAIN_TAB_POS_ME); + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.EVENT_HOME_MINE_TAB, + "我的tab"); + break; + + } + } + + public void setMsgNum(int number) { + mMsgTab.setNumber(number); + } + + public void select(int position) { + if (mLastPosition == position) return; + //mHomeTab.select(position == MAIN_TAB_POS_HOME); + mAttentionTab.select(position == MAIN_TAB_POS_ATTENTION); + mMsgTab.select(position == MAIN_TAB_POS_MSG); + mMeTab.select(position == MAIN_TAB_POS_ME); + gameTab.select(position == MAIN_TAB_POS_GAME); + if (mOnTabClickListener != null) { + mOnTabClickListener.onTabClick(position); + } + mLastPosition = position; + } + + private OnTabClickListener mOnTabClickListener; + + public void setOnTabClickListener(OnTabClickListener onTabClickListener) { + mOnTabClickListener = onTabClickListener; + } + + public void setmUnReadDynamicCount(int mUnReadDynamicCount) { + this.mUnReadDynamicCount = mUnReadDynamicCount; + mAttentionTab.setNumber(mUnReadDynamicCount); + } + + public interface OnTabClickListener { + void onTabClick(int position); + } + + /** + * 隐藏或显示某些tab + */ + public void showOrHideTab(int position,int visible){ + switch (position) { + case MAIN_TAB_POS_HOME: + //mHomeTab.setVisibility(visible); + break; + case MAIN_TAB_POS_ATTENTION: + mAttentionTab.setVisibility(visible); + break; + case MAIN_TAB_POS_MSG: + mMsgTab.setVisibility(visible); + break; + case MAIN_TAB_POS_ME: + mMeTab.setVisibility(visible); + break; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeLayout.java new file mode 100644 index 000000000..b4adeeeef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeLayout.java @@ -0,0 +1,118 @@ +package com.yizhuan.erban.ui.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.view.animation.LinearInterpolator; +import android.widget.HorizontalScrollView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.ScreenUtils; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_library.utils.log.MLog; + +/** + * @author xxf-kaede + * @date 2015/1/7 + */ +public class MarqueeLayout extends HorizontalScrollView { + + private TextView mGlobalNoticeContent; + private AnimatorSet animatorSet; + + private int mScreenWidth; + private Context mContext; + + public MarqueeLayout(@NonNull Context context) { + this(context, null); + } + + public MarqueeLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MarqueeLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + inflate(context, R.layout.global_broadcast_notice_layout, this); + setHorizontalScrollBarEnabled(false); + mGlobalNoticeContent = findViewById(R.id.tv_global_notice_content); + + mScreenWidth = ScreenUtils.getScreenWidth(context); + } + + + public void setText(CharSequence content) { + mGlobalNoticeContent.setText(content); + } + + /** + * 使用MarqueeLayout后,一定要在界面销毁的时候调用reserverAnimation() + * 不然可能导致内存泄露 + */ + public void startMarquee() { + MLog.debug(this, "[liao] startMarquee"); + reserverAnimation(); + + if (mGlobalNoticeContent != null) { + TextPaint paint = mGlobalNoticeContent.getPaint(); + float len = paint.measureText(mGlobalNoticeContent.getText().toString()); + + + MLog.debug(this, "[liao] 内容字体长度=" + len); + + animatorSet = new AnimatorSet(); + ObjectAnimator inAnimator = ObjectAnimator.ofFloat(mGlobalNoticeContent, + "translationX", mScreenWidth, -mScreenWidth - len); + inAnimator.setDuration((long) (len * 0.1) * 100); + inAnimator.setInterpolator(new LinearInterpolator()); + + + animatorSet.playSequentially(inAnimator); + + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (mOnAnimatorListener != null) + mOnAnimatorListener.onAnimationEnd(animation); + } + }); + animatorSet.start(); + } + } + + //清除属性动画 + public void reserverAnimation() { + MLog.debug(this, "[liao] reserverAnimation"); + if (animatorSet != null) { + if (animatorSet.isRunning()) { + animatorSet.cancel(); + } + animatorSet = null; + } + } + + @Override + protected void onDetachedFromWindow() { + reserverAnimation(); + super.onDetachedFromWindow(); + } + + private OnAnimatorListener mOnAnimatorListener; + + public void setOnAnimatorListener(OnAnimatorListener onAnimatorListener) { + mOnAnimatorListener = onAnimatorListener; + } + + public interface OnAnimatorListener { + void onAnimationEnd(Animator animation); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeTextView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeTextView.java new file mode 100644 index 000000000..4c98fe90b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MarqueeTextView.java @@ -0,0 +1,46 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.widget.TextView; + +/** + * Created by Administrator on 2014/7/22. + */ +public class MarqueeTextView extends TextView{ + + private boolean isMarquee=true; + + public MarqueeTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFocusChanged(boolean focused, int direction,Rect previouslyFocusedRect) { + if(focused) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + } + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + if(hasWindowFocus){ + super.onWindowFocusChanged(hasWindowFocus); + } + } + @Override + public boolean isFocused() { + if (isMarquee){ + return true; + }else { + return false; + } + } + public void setMarquee(boolean isMarquee){ + this.isMarquee=isMarquee; + this.setFocusable(isMarquee); + this.setFocusableInTouchMode(isMarquee); + this.setHorizontallyScrolling(isMarquee); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/MyItemAnimator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/MyItemAnimator.java new file mode 100644 index 000000000..33e7b0e57 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/MyItemAnimator.java @@ -0,0 +1,683 @@ +package com.yizhuan.erban.ui.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.support.annotation.NonNull; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.SimpleItemAnimator; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.View; +import android.view.ViewPropertyAnimator; + +import java.util.ArrayList; +import java.util.List; + +/** + * 重写DefualtItemAnimator, 防止 recyclerview 列表闪烁 + */ +public class MyItemAnimator extends SimpleItemAnimator { + private static final boolean DEBUG = false; + + private static TimeInterpolator sDefaultInterpolator; + + private ArrayList mPendingRemovals = new ArrayList<>(); + private ArrayList mPendingAdditions = new ArrayList<>(); + private ArrayList mPendingMoves = new ArrayList<>(); + private ArrayList mPendingChanges = new ArrayList<>(); + + ArrayList> mAdditionsList = new ArrayList<>(); + ArrayList> mMovesList = new ArrayList<>(); + ArrayList> mChangesList = new ArrayList<>(); + + ArrayList mAddAnimations = new ArrayList<>(); + ArrayList mMoveAnimations = new ArrayList<>(); + ArrayList mRemoveAnimations = new ArrayList<>(); + ArrayList mChangeAnimations = new ArrayList<>(); + + private static class MoveInfo { + public ViewHolder holder; + public int fromX, fromY, toX, toY; + + MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { + this.holder = holder; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + } + + private static class ChangeInfo { + public ViewHolder oldHolder, newHolder; + public int fromX, fromY, toX, toY; + private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { + this.oldHolder = oldHolder; + this.newHolder = newHolder; + } + + ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + this(oldHolder, newHolder); + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + + @Override + public String toString() { + return "ChangeInfo{" + + "oldHolder=" + oldHolder + + ", newHolder=" + newHolder + + ", fromX=" + fromX + + ", fromY=" + fromY + + ", toX=" + toX + + ", toY=" + toY + + '}'; + } + } + + @Override + public void runPendingAnimations() { + boolean removalsPending = !mPendingRemovals.isEmpty(); + boolean movesPending = !mPendingMoves.isEmpty(); + boolean changesPending = !mPendingChanges.isEmpty(); + boolean additionsPending = !mPendingAdditions.isEmpty(); + if (!removalsPending && !movesPending && !additionsPending && !changesPending) { + // nothing to animate + return; + } + // First, remove stuff + for (ViewHolder holder : mPendingRemovals) { + animateRemoveImpl(holder); + } + mPendingRemovals.clear(); + // Next, move stuff + if (movesPending) { + final ArrayList moves = new ArrayList<>(); + moves.addAll(mPendingMoves); + mMovesList.add(moves); + mPendingMoves.clear(); + Runnable mover = new Runnable() { + @Override + public void run() { + for (MoveInfo moveInfo : moves) { + animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, + moveInfo.toX, moveInfo.toY); + } + moves.clear(); + mMovesList.remove(moves); + } + }; + if (removalsPending) { + View view = moves.get(0).holder.itemView; + ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); + } else { + mover.run(); + } + } + // Next, change stuff, to run in parallel with move animations + if (changesPending) { + final ArrayList changes = new ArrayList<>(); + changes.addAll(mPendingChanges); + mChangesList.add(changes); + mPendingChanges.clear(); + Runnable changer = new Runnable() { + @Override + public void run() { + for (ChangeInfo change : changes) { + animateChangeImpl(change); + } + changes.clear(); + mChangesList.remove(changes); + } + }; + if (removalsPending) { + ViewHolder holder = changes.get(0).oldHolder; + ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); + } else { + changer.run(); + } + } + // Next, add stuff + if (additionsPending) { + final ArrayList additions = new ArrayList<>(); + additions.addAll(mPendingAdditions); + mAdditionsList.add(additions); + mPendingAdditions.clear(); + Runnable adder = new Runnable() { + @Override + public void run() { + for (ViewHolder holder : additions) { + animateAddImpl(holder); + } + additions.clear(); + mAdditionsList.remove(additions); + } + }; + if (removalsPending || movesPending || changesPending) { + long removeDuration = removalsPending ? getRemoveDuration() : 0; + long moveDuration = movesPending ? getMoveDuration() : 0; + long changeDuration = changesPending ? getChangeDuration() : 0; + long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); + View view = additions.get(0).itemView; + ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); + } else { + adder.run(); + } + } + } + + @Override + public boolean animateRemove(final ViewHolder holder) { + resetAnimation(holder); + mPendingRemovals.add(holder); + return true; + } + + private void animateRemoveImpl(final ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mRemoveAnimations.add(holder); + animation.setDuration(getRemoveDuration()).alpha(0).setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchRemoveStarting(holder); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + view.setAlpha(1); + dispatchRemoveFinished(holder); + mRemoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateAdd(final ViewHolder holder) { + resetAnimation(holder); + holder.itemView.setAlpha(0); + mPendingAdditions.add(holder); + return true; + } + + void animateAddImpl(final ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mAddAnimations.add(holder); + animation.alpha(1).setDuration(getAddDuration()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchAddStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + view.setAlpha(1); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchAddFinished(holder); + mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateMove(final ViewHolder holder, int fromX, int fromY, + int toX, int toY) { + final View view = holder.itemView; + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + return true; + } + + void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + final int deltaX = toX - fromX; + final int deltaY = toY - fromY; + if (deltaX != 0) { + view.animate().translationX(0); + } + if (deltaY != 0) { + view.animate().translationY(0); + } + // TODO: make EndActions end listeners instead, since end actions aren't called when + // vpas are canceled (and can't end them. why?) + // need listener functionality in VPACompat for this. Ick. + final ViewPropertyAnimator animation = view.animate(); + mMoveAnimations.add(holder); + animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchMoveStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + if (deltaX != 0) { + view.setTranslationX(0); + } + if (deltaY != 0) { + view.setTranslationY(0); + } + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchMoveFinished(holder); + mMoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + if (oldHolder == newHolder) { + // Don't know how to run change animations when the same view holder is re-used. + // run a move animation to handle position changes. + return animateMove(oldHolder, fromX, fromY, toX, toY); + } + final float prevTranslationX = oldHolder.itemView.getTranslationX(); + final float prevTranslationY = oldHolder.itemView.getTranslationY(); + final float prevAlpha = oldHolder.itemView.getAlpha(); + resetAnimation(oldHolder); + int deltaX = (int) (toX - fromX - prevTranslationX); + int deltaY = (int) (toY - fromY - prevTranslationY); + // recover prev translation state after ending animation + oldHolder.itemView.setTranslationX(prevTranslationX); + oldHolder.itemView.setTranslationY(prevTranslationY); + oldHolder.itemView.setAlpha(prevAlpha); + if (newHolder != null) { + // carry over translation values + resetAnimation(newHolder); + newHolder.itemView.setTranslationX(-deltaX); + newHolder.itemView.setTranslationY(-deltaY); + newHolder.itemView.setAlpha(0); + } + mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + return true; + } + + void animateChangeImpl(final ChangeInfo changeInfo) { + final ViewHolder holder = changeInfo.oldHolder; + final View view = holder == null ? null : holder.itemView; + final ViewHolder newHolder = changeInfo.newHolder; + final View newView = newHolder != null ? newHolder.itemView : null; + if (view != null) { + final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( + getChangeDuration()); + mChangeAnimations.add(changeInfo.oldHolder); + oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); + oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); +// oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() { +// @Override +// public void onAnimationStart(Animator animator) { +// dispatchChangeStarting(changeInfo.oldHolder, true); +// } +// +// @Override +// public void onAnimationEnd(Animator animator) { +// oldViewAnim.setListener(null); +// view.setAlpha(1); +// view.setTranslationX(0); +// view.setTranslationY(0); +// dispatchChangeFinished(changeInfo.oldHolder, true); +// mChangeAnimations.remove(changeInfo.oldHolder); +// dispatchFinishedWhenDone(); +// } +// }).start(); + oldViewAnim.setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.oldHolder, true); + } + + @Override + public void onAnimationEnd(Animator animator) { + oldViewAnim.setListener(null); + view.setAlpha(1); + view.setTranslationX(0); + view.setTranslationY(0); + dispatchChangeFinished(changeInfo.oldHolder, true); + mChangeAnimations.remove(changeInfo.oldHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + if (newView != null) { + final ViewPropertyAnimator newViewAnimation = newView.animate(); + mChangeAnimations.add(changeInfo.newHolder); +// newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) +// .alpha(1).setListener(new AnimatorListenerAdapter() { +// @Override +// public void onAnimationStart(Animator animator) { +// dispatchChangeStarting(changeInfo.newHolder, false); +// } +// @Override +// public void onAnimationEnd(Animator animator) { +// newViewAnimation.setListener(null); +// newView.setAlpha(1); +// newView.setTranslationX(0); +// newView.setTranslationY(0); +// dispatchChangeFinished(changeInfo.newHolder, false); +// mChangeAnimations.remove(changeInfo.newHolder); +// dispatchFinishedWhenDone(); +// } +// }).start(); + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.newHolder, false); + } + @Override + public void onAnimationEnd(Animator animator) { + newViewAnimation.setListener(null); + newView.setAlpha(1); + newView.setTranslationX(0); + newView.setTranslationY(0); + dispatchChangeFinished(changeInfo.newHolder, false); + mChangeAnimations.remove(changeInfo.newHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + } + + private void endChangeAnimation(List infoList, ViewHolder item) { + for (int i = infoList.size() - 1; i >= 0; i--) { + ChangeInfo changeInfo = infoList.get(i); + if (endChangeAnimationIfNecessary(changeInfo, item)) { + if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { + infoList.remove(changeInfo); + } + } + } + } + + private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { + if (changeInfo.oldHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); + } + if (changeInfo.newHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); + } + } + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { + boolean oldItem = false; + if (changeInfo.newHolder == item) { + changeInfo.newHolder = null; + } else if (changeInfo.oldHolder == item) { + changeInfo.oldHolder = null; + oldItem = true; + } else { + return false; + } + item.itemView.setAlpha(1); + item.itemView.setTranslationX(0); + item.itemView.setTranslationY(0); + dispatchChangeFinished(item, oldItem); + return true; + } + + @Override + public void endAnimation(ViewHolder item) { + final View view = item.itemView; + // this will trigger end callback which should set properties to their target values. + view.animate().cancel(); + // TODO if some other animations are chained to end, how do we cancel them as well? + for (int i = mPendingMoves.size() - 1; i >= 0; i--) { + MoveInfo moveInfo = mPendingMoves.get(i); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + mPendingMoves.remove(i); + } + } + endChangeAnimation(mPendingChanges, item); + if (mPendingRemovals.remove(item)) { + view.setAlpha(1); + dispatchRemoveFinished(item); + } + if (mPendingAdditions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + } + + for (int i = mChangesList.size() - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + endChangeAnimation(changes, item); + if (changes.isEmpty()) { + mChangesList.remove(i); + } + } + for (int i = mMovesList.size() - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + for (int j = moves.size() - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(i); + } + break; + } + } + } + for (int i = mAdditionsList.size() - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + if (additions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + if (additions.isEmpty()) { + mAdditionsList.remove(i); + } + } + } + + // animations should be ended by the cancel above. + //noinspection PointlessBooleanExpression,ConstantConditions + if (mRemoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mRemoveAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mAddAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mAddAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mChangeAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mChangeAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mMoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mMoveAnimations list"); + } + dispatchFinishedWhenDone(); + } + + private void resetAnimation(ViewHolder holder) { + if (sDefaultInterpolator == null) { + sDefaultInterpolator = new ValueAnimator().getInterpolator(); + } + holder.itemView.animate().setInterpolator(sDefaultInterpolator); + endAnimation(holder); + } + + @Override + public boolean isRunning() { + return (!mPendingAdditions.isEmpty() + || !mPendingChanges.isEmpty() + || !mPendingMoves.isEmpty() + || !mPendingRemovals.isEmpty() + || !mMoveAnimations.isEmpty() + || !mRemoveAnimations.isEmpty() + || !mAddAnimations.isEmpty() + || !mChangeAnimations.isEmpty() + || !mMovesList.isEmpty() + || !mAdditionsList.isEmpty() + || !mChangesList.isEmpty()); + } + + /** + * Check the state of currently pending and running animations. If there are none + * pending/running, call {@link #dispatchAnimationsFinished()} to notify any + * listeners. + */ + void dispatchFinishedWhenDone() { + if (!isRunning()) { + dispatchAnimationsFinished(); + } + } + + @Override + public void endAnimations() { + int count = mPendingMoves.size(); + for (int i = count - 1; i >= 0; i--) { + MoveInfo item = mPendingMoves.get(i); + View view = item.holder.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item.holder); + mPendingMoves.remove(i); + } + count = mPendingRemovals.size(); + for (int i = count - 1; i >= 0; i--) { + ViewHolder item = mPendingRemovals.get(i); + dispatchRemoveFinished(item); + mPendingRemovals.remove(i); + } + count = mPendingAdditions.size(); + for (int i = count - 1; i >= 0; i--) { + ViewHolder item = mPendingAdditions.get(i); + item.itemView.setAlpha(1); + dispatchAddFinished(item); + mPendingAdditions.remove(i); + } + count = mPendingChanges.size(); + for (int i = count - 1; i >= 0; i--) { + endChangeAnimationIfNecessary(mPendingChanges.get(i)); + } + mPendingChanges.clear(); + if (!isRunning()) { + return; + } + + int listCount = mMovesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + count = moves.size(); + for (int j = count - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + ViewHolder item = moveInfo.holder; + View view = item.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(moveInfo.holder); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(moves); + } + } + } + listCount = mAdditionsList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + count = additions.size(); + for (int j = count - 1; j >= 0; j--) { + ViewHolder item = additions.get(j); + View view = item.itemView; + view.setAlpha(1); + dispatchAddFinished(item); + additions.remove(j); + if (additions.isEmpty()) { + mAdditionsList.remove(additions); + } + } + } + listCount = mChangesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + count = changes.size(); + for (int j = count - 1; j >= 0; j--) { + endChangeAnimationIfNecessary(changes.get(j)); + if (changes.isEmpty()) { + mChangesList.remove(changes); + } + } + } + + cancelAll(mRemoveAnimations); + cancelAll(mMoveAnimations); + cancelAll(mAddAnimations); + cancelAll(mChangeAnimations); + + dispatchAnimationsFinished(); + } + + void cancelAll(List viewHolders) { + for (int i = viewHolders.size() - 1; i >= 0; i--) { + viewHolders.get(i).itemView.animate().cancel(); + } + } + + /** + * {@inheritDoc} + *

+ * If the payload list is not empty, DefaultItemAnimator returns true. + * When this is the case: + *

    + *
  • If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both + * ViewHolder arguments will be the same instance. + *
  • + *
  • + * If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, + * then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and + * run a move animation instead. + *
  • + *
+ */ + @Override + public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, + @NonNull List payloads) { + return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/NobleAvatarView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/NobleAvatarView.java new file mode 100644 index 000000000..e5232cc99 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/NobleAvatarView.java @@ -0,0 +1,125 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.room.bean.OnlineChatMember; +import com.yizhuan.xchat_android_core.user.bean.FansInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + *

贵族头像

+ * + * @author jiahui + * @date 2018/1/16 + */ +public class NobleAvatarView extends RelativeLayout { + + private ImageView mIvAvatar; + private ImageView mIvAvatarHeadWear; + private ImageView mIvUserLevel; + private Context mContext; + + public NobleAvatarView(Context context) { + this(context, null); + } + + public NobleAvatarView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public NobleAvatarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + inflate(context, R.layout.noble_avatar_layout, this); + mIvAvatar = findViewById(R.id.iv_avatar); + mIvAvatarHeadWear = findViewById(R.id.iv_avatar_head_wear); + mIvUserLevel = findViewById(R.id.iv_user_noble_level); + } + + /** + * 设置自定义大小,单位dp + * + * @param avatarSize 头像大小 + * @param avatarHeadWearSize 头饰大小 + * @param userLevelSize 贵族级别图标大小 + */ + public void setSize(float avatarSize, float avatarHeadWearSize, float userLevelSize) { + int avatarSizeDp = SizeUtils.dp2px(mContext, avatarSize); + LayoutParams avatarParams = (LayoutParams) mIvAvatar.getLayoutParams(); + avatarParams.width = avatarSizeDp; + avatarParams.height = avatarSizeDp; + avatarParams.leftMargin = SizeUtils.dp2px(mContext, (avatarHeadWearSize - avatarSize) / 2); + avatarParams.topMargin = SizeUtils.dp2px(mContext, (avatarHeadWearSize - avatarSize) / 2); + + int avatarHeadWearSizeDp = SizeUtils.dp2px(mContext, avatarHeadWearSize); + LayoutParams avatarHeadWearParam = (LayoutParams) mIvAvatarHeadWear.getLayoutParams(); + avatarHeadWearParam.width = avatarHeadWearSizeDp; + avatarHeadWearParam.height = avatarHeadWearSizeDp; + + int userLevelSizeDp = SizeUtils.dp2px(mContext, userLevelSize); + LayoutParams userLevelParam = (LayoutParams) mIvUserLevel.getLayoutParams(); + userLevelParam.width = userLevelSizeDp; + userLevelParam.height = userLevelSizeDp; + } + + public void setData(UserInfo userInfo) { + if (userInfo == null) return; + ImageLoadUtils.loadAvatar(mContext, userInfo.getAvatar(), mIvAvatar, true); + setNobleData(userInfo.getNobleInfo()); + } + + public void setData(String avatar, NobleInfo nobleInfo) { + ImageLoadUtils.loadAvatar(mContext, avatar, mIvAvatar, true); + setNobleData(nobleInfo); + } + + + public void setData(OnlineChatMember onlineChatMember) { + if (onlineChatMember == null) return; + if (TextUtils.isEmpty(onlineChatMember.avatar)) + mIvAvatar.setImageResource(R.drawable.icon_room_up_micro); + else + ImageLoadUtils.loadAvatar(mContext, onlineChatMember.avatar, mIvAvatar, true); + setNobleData(onlineChatMember.nobleUsers); + } + + public void setData(ChatRoomMember chatRoomMember) { + if (chatRoomMember == null) return; + ImageLoadUtils.loadAvatar(mContext, chatRoomMember.getAvatar(), mIvAvatar, true); + NobleInfo nobleInfo = new NobleInfo(); + String resourceHeadWear = (String) NobleUtil.getResource(NobleResourceType.KEY_HEAD_WEAR, chatRoomMember); + nobleInfo.setHeadWear(resourceHeadWear); + setNobleData(nobleInfo); + } + + private void setNobleData(NobleInfo nobleInfo) { + if (nobleInfo != null) { + mIvAvatarHeadWear.setVisibility(VISIBLE); + mIvUserLevel.setVisibility(VISIBLE); + String headWear = nobleInfo.getHeadWear(); + if (TextUtils.isEmpty(headWear)) { + mIvAvatarHeadWear.setVisibility(INVISIBLE); + mIvUserLevel.setVisibility(nobleInfo.getLevel() > 0 ? VISIBLE : GONE); + NobleUtil.loadResource(NobleUtil.getBadgeByLevel(nobleInfo.getLevel()), mIvUserLevel); + } else { + mIvUserLevel.setVisibility(INVISIBLE); + NobleUtil.loadResource(headWear, mIvAvatarHeadWear); + } + } else { + mIvAvatarHeadWear.setVisibility(INVISIBLE); + mIvUserLevel.setVisibility(INVISIBLE); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/NobleOpenNoticeView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/NobleOpenNoticeView.java new file mode 100644 index 000000000..b7c0b427d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/NobleOpenNoticeView.java @@ -0,0 +1,173 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.Color; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.opensource.svgaplayer.SVGACallback; +import com.opensource.svgaplayer.SVGADrawable; +import com.opensource.svgaplayer.SVGAImageView; +import com.opensource.svgaplayer.SVGAParser; +import com.opensource.svgaplayer.SVGAVideoEntity; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + *

房间里面开通贵族展示横幅

+ * + * @author jiahui + * @date 2018/1/19 + */ +public class NobleOpenNoticeView extends RelativeLayout implements View.OnClickListener { + private Context mContext; + + private TextView mNobleOpenContent; + private SVGAImageView mSVGAImageView; + private SVGAParser mSVGAParser; + + public NobleOpenNoticeView(Context context) { + this(context, null); + } + + public NobleOpenNoticeView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public NobleOpenNoticeView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + inflate(context, R.layout.noble_open_notice_layout, this); + LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutParams(params); + setBackgroundColor(ContextCompat.getColor(context, R.color.color_99000000)); + + mNobleOpenContent = findViewById(R.id.tv_noble_open_content); + mSVGAImageView = findViewById(R.id.noble_savg_view); + findViewById(R.id.iv_noble_open_close).setOnClickListener(this); + mSVGAParser = new SVGAParser(context); + } + + /** + * 设置数据 + * + * @param nobleInfo 贵族信息 + * @param nick 昵称 + * @param type 1:开通,2:续费 + */ + public void setData(NobleInfo nobleInfo, String nick, int type) { + if (nobleInfo == null || TextUtils.isEmpty(nick)) { + setVisibility(GONE); + return; + } + + String source = NobleUtil.getOpenEffectByLevel(nobleInfo.getLevel()); + if (TextUtils.isEmpty(source)) return; + if (source.toLowerCase().endsWith(".svga")) { + try { + mSVGAParser.parse(new URL(source), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(SVGAVideoEntity svgaVideoEntity) { + setVisibility(VISIBLE); + SVGADrawable drawable = new SVGADrawable(svgaVideoEntity); + mSVGAImageView.setLoops(1); + mSVGAImageView.setImageDrawable(drawable); + mSVGAImageView.startAnimation(); + mSVGAImageView.setClearsAfterStop(true); + mSVGAImageView.setCallback(new SVGACallback() { + @Override + public void onPause() { + + } + + @Override + public void onFinished() { + NobleOpenNoticeView.this.setVisibility(GONE); + } + + @Override + public void onRepeat() { + + } + + @Override + public void onStep(int i, double v) { + + } + }); + } + + @Override + public void onError() { + setVisibility(GONE); + } + }); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + setVisibility(VISIBLE); + + String content = null; + if (type == 1) { + //恭喜 xxxx 开通“国王”贵族,速来膜拜 + content = mContext.getString(R.string.noble_open_notice, nick, nobleInfo.getName()); + } else if (type == 2) { + //恭喜 xxxx 续费“国王”贵族 + content = mContext.getString(R.string.noble_reopen_notice, nick, nobleInfo.getName()); + } + if (!TextUtils.isEmpty(content)) { + Spannable spannable = new SpannableString(content); + int start = content.lastIndexOf(nick); + int end = start + nick.length() + 1; + spannable.setSpan(new ForegroundColorSpan(Color.parseColor("#f3cf77")), + start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + start = content.lastIndexOf(nobleInfo.getName()); + end = start + nobleInfo.getName().length() + 1; + spannable.setSpan(new ForegroundColorSpan(Color.parseColor("#f3cf77")), + start - 1, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mNobleOpenContent.setText(spannable); + } + } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (visibility == GONE || visibility == INVISIBLE) { + if (mSVGAImageView.isAnimating()) { + mSVGAImageView.clearAnimation(); + mSVGAImageView.setVisibility(GONE); + } + } + } + + @Override + public void onClick(View v) { + setVisibility(GONE); + if (mSVGAImageView.isAnimating()) { + mSVGAImageView.clearAnimation(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mSVGAImageView.isAnimating()) { + mSVGAImageView.clearAnimation(); + } + super.onDetachedFromWindow(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/NumView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/NumView.java new file mode 100644 index 000000000..de5496b59 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/NumView.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +public class NumView extends LinearLayout { + + private int[] nums = {R.drawable.ic_num0, R.drawable.ic_num1, R.drawable.ic_num2 + , R.drawable.ic_num3, R.drawable.ic_num4, R.drawable.ic_num5 + , R.drawable.ic_num6, R.drawable.ic_num7, R.drawable.ic_num8 + , R.drawable.ic_num9}; + + public NumView(Context context) { + this(context, null); + } + + public NumView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public void setNum(int num) { + char[] bytes = String.valueOf(num).toCharArray(); + for (char aByte : bytes) { + ImageView imageView = new ImageView(getContext()); + imageView.setImageResource(nums[JavaUtil.str2int(aByte + "")]); + addView(imageView); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ObservableScrollView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ObservableScrollView.java new file mode 100644 index 000000000..36e5f637d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ObservableScrollView.java @@ -0,0 +1,47 @@ +package com.yizhuan.erban.ui.widget; + +/** + * Created by chenran on 2017/10/17. + */ + +import android.content.Context; +import android.support.v4.widget.NestedScrollView; +import android.util.AttributeSet; + +import com.netease.nim.uikit.common.util.log.LogUtil; + +public class ObservableScrollView extends NestedScrollView { + + private ScrollViewListener scrollViewListener = null; + + public ObservableScrollView(Context context) { + super(context); + } + + public ObservableScrollView(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + } + + public ObservableScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setScrollViewListener(ScrollViewListener scrollViewListener) { + this.scrollViewListener = scrollViewListener; + } + + @Override + protected void onScrollChanged(int x, int y, int oldx, int oldy) { + super.onScrollChanged(x, y, oldx, oldy); + LogUtil.i("ObservableScrollView", "x->"+x + " y->" + y + " oldx->" + oldx + " oldy" + oldy); + if (scrollViewListener != null) { + scrollViewListener.onScrollChanged(this, x, y, oldx, oldy); + } + } + + public interface ScrollViewListener { + void onScrollChanged(NestedScrollView view, int x, int y, int oldx, int oldy); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/OnPageSelectedListener.java b/app/src/main/java/com/yizhuan/erban/ui/widget/OnPageSelectedListener.java new file mode 100644 index 000000000..748c72a0f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/OnPageSelectedListener.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.ui.widget; + +import android.support.v4.view.ViewPager; + +/** + * + * Created by lvzebiao on 2018/11/8. + */ + +public abstract class OnPageSelectedListener implements ViewPager.OnPageChangeListener{ + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/PinEntryEditText.java b/app/src/main/java/com/yizhuan/erban/ui/widget/PinEntryEditText.java new file mode 100644 index 000000000..1309dc011 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/PinEntryEditText.java @@ -0,0 +1,629 @@ +/** + * Copyright 2016 Ali Muzaffar + *

+ * 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.yizhuan.erban.ui.widget; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; +import android.support.v4.view.ViewCompat; +import android.support.v7.widget.AppCompatEditText; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.ActionMode; +import android.view.View; +import android.view.animation.OvershootInterpolator; +import android.view.inputmethod.InputMethodManager; + +import com.yizhuan.erban.R; + + +public class PinEntryEditText extends AppCompatEditText { + private static final String XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android"; + + public static final String DEFAULT_MASK = "\u25CF"; + + protected String mMask = null; + protected StringBuilder mMaskChars = null; + protected String mSingleCharHint = null; + protected int mAnimatedType = 0; + protected float mSpace = 24; //24 dp by default, space between the lines + protected float mCharSize; + protected float mNumChars = 4; + protected float mTextBottomPadding = 8; //8dp by default, height of the text from our lines + protected int mMaxLength = 4; + protected RectF[] mLineCoords; + protected float[] mCharBottom; + protected Paint mCharPaint; + protected Paint mLastCharPaint; + protected Paint mSingleCharPaint; + protected Drawable mPinBackground; + protected Rect mTextHeight = new Rect(); + protected boolean mIsDigitSquare = false; + + protected OnClickListener mClickListener; + protected OnPinEnteredListener mOnPinEnteredListener = null; + + protected float mLineStroke = 1; //1dp by default + protected float mLineStrokeSelected = 2; //2dp by default + protected Paint mLinesPaint; + protected boolean mAnimate = false; + protected boolean mHasError = false; + protected ColorStateList mOriginalTextColors; + protected int[][] mStates = new int[][]{ + new int[]{android.R.attr.state_selected}, // selected + new int[]{android.R.attr.state_active}, // error + new int[]{android.R.attr.state_focused}, // focused + new int[]{-android.R.attr.state_focused}, // unfocused + }; + + protected int[] mColors = new int[]{ + Color.GREEN, + Color.RED, + Color.BLACK, + Color.GRAY + }; + + protected ColorStateList mColorStates = new ColorStateList(mStates, mColors); + + public PinEntryEditText(Context context) { + super(context); + } + + public PinEntryEditText(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public PinEntryEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + public void setMaxLength(final int maxLength) { + mMaxLength = maxLength; + mNumChars = maxLength; + + setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + + setText(null); + invalidate(); + } + + public void setMask(String mask) { + mMask = mask; + mMaskChars = null; + invalidate(); + } + + public void setSingleCharHint(String hint) { + mSingleCharHint = hint; + invalidate(); + } + + private void init(Context context, AttributeSet attrs) { + float multi = context.getResources().getDisplayMetrics().density; + mLineStroke = multi * mLineStroke; + mLineStrokeSelected = multi * mLineStrokeSelected; + mSpace = multi * mSpace; //convert to pixels for our density + mTextBottomPadding = multi * mTextBottomPadding; //convert to pixels for our density + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PinEntryEditText, 0, 0); + try { + TypedValue outValue = new TypedValue(); + ta.getValue(R.styleable.PinEntryEditText_pinAnimationType, outValue); + mAnimatedType = outValue.data; + mMask = ta.getString(R.styleable.PinEntryEditText_pinCharacterMask); + mSingleCharHint = ta.getString(R.styleable.PinEntryEditText_pinRepeatedHint); + mLineStroke = ta.getDimension(R.styleable.PinEntryEditText_pinLineStroke, mLineStroke); + mLineStrokeSelected = ta.getDimension(R.styleable.PinEntryEditText_pinLineStrokeSelected, mLineStrokeSelected); + mSpace = ta.getDimension(R.styleable.PinEntryEditText_pinCharacterSpacing, mSpace); + mTextBottomPadding = ta.getDimension(R.styleable.PinEntryEditText_pinTextBottomPadding, mTextBottomPadding); + mIsDigitSquare = ta.getBoolean(R.styleable.PinEntryEditText_pinBackgroundIsSquare, mIsDigitSquare); + mPinBackground = ta.getDrawable(R.styleable.PinEntryEditText_pinBackgroundDrawable); + ColorStateList colors = ta.getColorStateList(R.styleable.PinEntryEditText_pinLineColors); + if (colors != null) { + mColorStates = colors; + } + } finally { + ta.recycle(); + } + + mCharPaint = new Paint(getPaint()); + mLastCharPaint = new Paint(getPaint()); + mSingleCharPaint = new Paint(getPaint()); + mLinesPaint = new Paint(getPaint()); + mLinesPaint.setStrokeWidth(mLineStroke); + + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(R.attr.colorControlActivated, + outValue, true); + int colorSelected = outValue.data; + mColors[0] = colorSelected; + + int colorFocused = isInEditMode() ? Color.GRAY : ContextCompat.getColor(context, R.color.color_999999); + mColors[1] = colorFocused; + + int colorUnfocused = isInEditMode() ? Color.GRAY : ContextCompat.getColor(context, R.color.color_999999); + mColors[2] = colorUnfocused; + + setBackgroundResource(0); + + mMaxLength = attrs.getAttributeIntValue(XML_NAMESPACE_ANDROID, "maxLength", 4); + mNumChars = mMaxLength; + + //Disable copy paste +// super.setCustomSelectionActionModeCallback(new ActionMode.Callback() { +// public boolean onPrepareActionMode(ActionMode mode, Menu menu) { +// return false; +// } +// +// public void onDestroyActionMode(ActionMode mode) { +// } +// +// public boolean onCreateActionMode(ActionMode mode, Menu menu) { +// return false; +// } +// +// public boolean onActionItemClicked(ActionMode mode, MenuItem item) { +// return false; +// } +// }); + // When tapped, move cursor to end of text. + super.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + setSelection(getText().length()); + if (mClickListener != null) { + mClickListener.onClick(v); + } + } + }); + +// super.setOnLongClickListener(new OnLongClickListener() { +// @Override +// public boolean onLongClick(View v) { +// setSelection(getText().length()); +// return true; +// } +// }); + + //If input type is password and no mask is set, use a default mask + if ((getInputType() & InputType.TYPE_TEXT_VARIATION_PASSWORD) == InputType.TYPE_TEXT_VARIATION_PASSWORD && TextUtils.isEmpty(mMask)) { + mMask = DEFAULT_MASK; + } else if ((getInputType() & InputType.TYPE_NUMBER_VARIATION_PASSWORD) == InputType.TYPE_NUMBER_VARIATION_PASSWORD && TextUtils.isEmpty(mMask)) { + mMask = DEFAULT_MASK; + } + + if (!TextUtils.isEmpty(mMask)) { + mMaskChars = getMaskChars(); + } + + //Height of the characters, used if there is a background drawable + getPaint().getTextBounds("|", 0, 1, mTextHeight); + + mAnimate = mAnimatedType > -1; + } + + @Override + public void setInputType(int type) { + super.setInputType(type); + + if ((type & InputType.TYPE_TEXT_VARIATION_PASSWORD) == InputType.TYPE_TEXT_VARIATION_PASSWORD + || (type & InputType.TYPE_NUMBER_VARIATION_PASSWORD) == InputType.TYPE_NUMBER_VARIATION_PASSWORD) { + // If input type is password and no mask is set, use a default mask + if (TextUtils.isEmpty(mMask)) { + setMask(DEFAULT_MASK); + } + } else { + // If input type is not password, remove mask + setMask(null); + } + + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mOriginalTextColors = getTextColors(); + if (mOriginalTextColors != null) { + mLastCharPaint.setColor(mOriginalTextColors.getDefaultColor()); + mCharPaint.setColor(mOriginalTextColors.getDefaultColor()); + mSingleCharPaint.setColor(getCurrentHintTextColor()); + } + int availableWidth = getWidth() - ViewCompat.getPaddingEnd(this) - ViewCompat.getPaddingStart(this); + if (mSpace < 0) { + mCharSize = (availableWidth / (mNumChars * 2 - 1)); + } else { + mCharSize = (availableWidth - (mSpace * (mNumChars - 1))) / mNumChars; + } + mLineCoords = new RectF[(int) mNumChars]; + mCharBottom = new float[(int) mNumChars]; + int startX; + int bottom = getHeight() - getPaddingBottom(); + int rtlFlag; + final boolean isLayoutRtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL; + if (isLayoutRtl) { + rtlFlag = -1; + startX = (int) (getWidth() - ViewCompat.getPaddingStart(this) - mCharSize); + } else { + rtlFlag = 1; + startX = ViewCompat.getPaddingStart(this); + } + for (int i = 0; i < mNumChars; i++) { + mLineCoords[i] = new RectF(startX, bottom, startX + mCharSize, bottom); + if (mPinBackground != null) { + if (mIsDigitSquare) { + mLineCoords[i].top = getPaddingTop(); + mLineCoords[i].right = startX + mLineCoords[i].width(); + } else { + mLineCoords[i].top -= mTextHeight.height() + mTextBottomPadding * 2; + } + } + + if (mSpace < 0) { + startX += rtlFlag * mCharSize * 2; + } else { + startX += rtlFlag * (mCharSize + mSpace); + } + mCharBottom[i] = mLineCoords[i].bottom - mTextBottomPadding; + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mIsDigitSquare) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int measuredWidth = 0; + int measuredHeight = 0; + // If we want a square or circle pin box, we might be able + // to figure out the dimensions outselves + // if width and height are set to wrap_content or match_parent + if (widthMode == MeasureSpec.EXACTLY) { + measuredWidth = MeasureSpec.getSize(widthMeasureSpec); + measuredHeight = (int) ((measuredWidth - (mNumChars - 1 * mSpace)) / mNumChars); + } else if (heightMode == MeasureSpec.EXACTLY) { + measuredHeight = MeasureSpec.getSize(heightMeasureSpec); + measuredWidth = (int) ((measuredHeight * mNumChars) + (mSpace * mNumChars - 1)); + } else if (widthMode == MeasureSpec.AT_MOST) { + measuredWidth = MeasureSpec.getSize(widthMeasureSpec); + measuredHeight = (int) ((measuredWidth - (mNumChars - 1 * mSpace)) / mNumChars); + } else if (heightMode == MeasureSpec.AT_MOST) { + measuredHeight = MeasureSpec.getSize(heightMeasureSpec); + measuredWidth = (int) ((measuredHeight * mNumChars) + (mSpace * mNumChars - 1)); + } else { + // Both unspecific + // Try for a width based on our minimum + measuredWidth = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth(); + + // Whatever the width ends up being, ask for a height that would let the pie + // get as big as it can + measuredHeight = (int) ((measuredWidth - (mNumChars - 1 * mSpace)) / mNumChars); + } + + setMeasuredDimension( + resolveSizeAndState(measuredWidth, widthMeasureSpec, 1), resolveSizeAndState(measuredHeight, heightMeasureSpec, 0)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + @Override + public void setOnClickListener(OnClickListener l) { + mClickListener = l; + } + + @Override + public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) { + throw new RuntimeException("setCustomSelectionActionModeCallback() not supported."); + } + + @Override + protected void onDraw(Canvas canvas) { + //super.onDraw(canvas); + CharSequence text = getFullText(); + int textLength = text.length(); + float[] textWidths = new float[textLength]; + getPaint().getTextWidths(text, 0, textLength, textWidths); + + float hintWidth = 0; + if (mSingleCharHint != null) { + float[] hintWidths = new float[mSingleCharHint.length()]; + getPaint().getTextWidths(mSingleCharHint, hintWidths); + for (float i : hintWidths) { + hintWidth += i; + } + } + for (int i = 0; i < mNumChars; i++) { + //If a background for the pin characters is specified, it should be behind the characters. + if (mPinBackground != null) { + updateDrawableState(i < textLength, i == textLength); + mPinBackground.setBounds((int) mLineCoords[i].left, (int) mLineCoords[i].top, (int) mLineCoords[i].right, (int) mLineCoords[i].bottom); + mPinBackground.draw(canvas); + } + float middle = mLineCoords[i].left + mCharSize / 2; + if (textLength > i) { + if (!mAnimate || i != textLength - 1) { + canvas.drawText(text, i, i + 1, middle - textWidths[i] / 2, mCharBottom[i], mCharPaint); + } else { + canvas.drawText(text, i, i + 1, middle - textWidths[i] / 2, mCharBottom[i], mLastCharPaint); + } + } else if (mSingleCharHint != null) { + canvas.drawText(mSingleCharHint, middle - hintWidth / 2, mCharBottom[i], mSingleCharPaint); + } + //The lines should be in front of the text (because that's how I want it). + if (mPinBackground == null) { + updateColorForLines(i <= textLength); + canvas.drawLine(mLineCoords[i].left, mLineCoords[i].top, mLineCoords[i].right, mLineCoords[i].bottom, mLinesPaint); + } + } + } + + private CharSequence getFullText() { + if (TextUtils.isEmpty(mMask)) { + return getText(); + } else { + return getMaskChars(); + } + } + + private StringBuilder getMaskChars() { + if (mMaskChars == null) { + mMaskChars = new StringBuilder(); + } + int textLength = getText().length(); + while (mMaskChars.length() != textLength) { + if (mMaskChars.length() < textLength) { + mMaskChars.append(mMask); + } else { + mMaskChars.deleteCharAt(mMaskChars.length() - 1); + } + } + return mMaskChars; + } + + + private int getColorForState(int... states) { + return mColorStates.getColorForState(states, Color.GRAY); + } + + /** + * @param hasTextOrIsNext Is the color for a character that has been typed or is + * the next character to be typed? + */ + protected void updateColorForLines(boolean hasTextOrIsNext) { + if (mHasError) { + mLinesPaint.setColor(getColorForState(android.R.attr.state_active)); + } else if (isFocused()) { + mLinesPaint.setStrokeWidth(mLineStrokeSelected); + mLinesPaint.setColor(getColorForState(android.R.attr.state_focused)); + if (hasTextOrIsNext) { + mLinesPaint.setColor(getColorForState(android.R.attr.state_selected)); + } + } else { + mLinesPaint.setStrokeWidth(mLineStroke); + mLinesPaint.setColor(getColorForState(-android.R.attr.state_focused)); + } + } + + protected void updateDrawableState(boolean hasText, boolean isNext) { + if (mHasError) { + mPinBackground.setState(new int[]{android.R.attr.state_active}); + } else if (isFocused()) { + mPinBackground.setState(new int[]{android.R.attr.state_focused}); + if (isNext) { + mPinBackground.setState(new int[]{android.R.attr.state_focused, android.R.attr.state_selected}); + } else if (hasText) { + mPinBackground.setState(new int[]{android.R.attr.state_focused, android.R.attr.state_checked}); + } + } else { + if (hasText) { + mPinBackground.setState(new int[]{-android.R.attr.state_focused, android.R.attr.state_checked}); + } else { + mPinBackground.setState(new int[]{-android.R.attr.state_focused}); + } + } + } + + public void setError(boolean hasError) { + mHasError = hasError; + invalidate(); + } + + public boolean isError() { + return mHasError; + } + + /** + * Request focus on this PinEntryEditText + */ + public void focus() { + requestFocus(); + + // Show keyboard + InputMethodManager inputMethodManager = (InputMethodManager) getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.showSoftInput(this, 0); + } + + @Override + public void setTypeface(@Nullable Typeface tf) { + super.setTypeface(tf); + setCustomTypeface(tf); + } + + @Override + public void setTypeface(@Nullable Typeface tf, int style) { + super.setTypeface(tf, style); + setCustomTypeface(tf); + } + + private void setCustomTypeface(@Nullable Typeface tf) { + if (mCharPaint != null) { + mCharPaint.setTypeface(tf); + mLastCharPaint.setTypeface(tf); + mSingleCharPaint.setTypeface(tf); + mLinesPaint.setTypeface(tf); + } + } + + public void setPinLineColors(ColorStateList colors) { + mColorStates = colors; + invalidate(); + } + + public void setPinBackground(Drawable pinBackground) { + mPinBackground = pinBackground; + invalidate(); + } + + @Override + protected void onTextChanged(CharSequence text, final int start, int lengthBefore, final int lengthAfter) { + setError(false); + if (mLineCoords == null || !mAnimate) { + if (mOnPinEnteredListener != null && text.length() == mMaxLength) { + mOnPinEnteredListener.onPinEntered(text); + } + return; + } + + if (mAnimatedType == -1) { + invalidate(); + return; + } + + if (lengthAfter > lengthBefore) { + if (mAnimatedType == 0) { + animatePopIn(); + } else { + animateBottomUp(text, start); + } + } + } + + private void animatePopIn() { + ValueAnimator va = ValueAnimator.ofFloat(1, getPaint().getTextSize()); + va.setDuration(200); + va.setInterpolator(new OvershootInterpolator()); + va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mLastCharPaint.setTextSize((Float) animation.getAnimatedValue()); + PinEntryEditText.this.invalidate(); + } + }); + if (getText().length() == mMaxLength && mOnPinEnteredListener != null) { + va.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + mOnPinEnteredListener.onPinEntered(getText()); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + }); + } + va.start(); + } + + private void animateBottomUp(CharSequence text, final int start) { + mCharBottom[start] = mLineCoords[start].bottom - mTextBottomPadding; + ValueAnimator animUp = ValueAnimator.ofFloat(mCharBottom[start] + getPaint().getTextSize(), mCharBottom[start]); + animUp.setDuration(300); + animUp.setInterpolator(new OvershootInterpolator()); + animUp.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + Float value = (Float) animation.getAnimatedValue(); + mCharBottom[start] = value; + PinEntryEditText.this.invalidate(); + } + }); + + mLastCharPaint.setAlpha(255); + ValueAnimator animAlpha = ValueAnimator.ofInt(0, 255); + animAlpha.setDuration(300); + animAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + Integer value = (Integer) animation.getAnimatedValue(); + mLastCharPaint.setAlpha(value); + } + }); + + AnimatorSet set = new AnimatorSet(); + if (text.length() == mMaxLength && mOnPinEnteredListener != null) { + set.addListener(new Animator.AnimatorListener() { + + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + mOnPinEnteredListener.onPinEntered(getText()); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + set.playTogether(animUp, animAlpha); + set.start(); + } + + public void setAnimateText(boolean animate) { + mAnimate = animate; + } + + public void setOnPinEnteredListener(OnPinEnteredListener l) { + mOnPinEnteredListener = l; + } + + public interface OnPinEnteredListener { + void onPinEntered(CharSequence str); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RecallDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RecallDialog.java new file mode 100644 index 000000000..4e22af354 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RecallDialog.java @@ -0,0 +1,118 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.string.StringUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.recall.RecallModel; +import com.yizhuan.xchat_android_core.recall.bean.GoBackInfo; +import com.yizhuan.xchat_android_core.recall.event.GoBackEvent; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import io.reactivex.functions.Consumer; +import retrofit2.http.HEAD; + +public class RecallDialog extends BaseActivity implements View.OnClickListener { + /** 一个设备只能领取一次老用户回归礼物 */ + public static final String GO_BACK_ONCE = "go_back_once"; + + private EditText etRecallInput; + + public static void start(Context context) { + Intent intent = new Intent(context, RecallDialog.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.recall_dialog); + initView(); + + EventBus.getDefault().register(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onGobackEvent(GoBackEvent event){ + if (event.isFailed()) { + SingleToastUtil.showToast(event.getError()); + } else { + GoBackInfo goBackInfo = (GoBackInfo) event.getData(); + + SingleToastUtil.showToast(goBackInfo.getMessage()); + SharedPreferenceUtils.put(GO_BACK_ONCE, "true"); + finish(); + } + } + + private void initView() { + etRecallInput = findViewById(R.id.et_recall_input); + + TextView tvRecallName = findViewById(R.id.tv_recall_name); + UserModel.get().getCurrentUserInfo().subscribe(new Consumer() { + @Override + public void accept(UserInfo info) throws Exception { + tvRecallName.setText("亲爱的" + info.getNick() + ":"); + } + }); + findViewById(R.id.tv_get_recall_gift).setOnClickListener(this); + findViewById(R.id.iv_recall_close).setOnClickListener(this); + } + + private void goBack(String uid, String inviteCode) { + RecallModel.get().goBack(uid, StringUtil.isEmpty(inviteCode) ? "" : inviteCode); + } + + /** + * 只有框内按钮可以关闭弹框 + */ + @Override + public void onBackPressed() { +// super.onBackPressed(); + } + + @Override + public void onClick(View v) { + + switch (v.getId()) { + + case R.id.tv_get_recall_gift: // 收下回归礼 + goBack(String.valueOf(AuthModel.get().getCurrentUid()), etRecallInput.getText().toString().trim()); + break; + + case R.id.iv_recall_close: + finish(); + break; + + default: + break; + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RectLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RectLayout.java new file mode 100644 index 000000000..27ba938bb --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RectLayout.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; + +/** + * Created by jack + */ +public class RectLayout extends RelativeLayout { + + private float hwRatio = -1.0f; + public RectLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RectLayout, defStyle, 0); + hwRatio = a.getFloat(R.styleable.RectLayout_hw_ratio, -1.0f); + + a.recycle(); + } + + public RectLayout(Context context, AttributeSet attrs) { + this(context, attrs,0); + } + + public RectLayout(Context context) { + super(context); + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); + + if (hwRatio > 0){ + int childWidthSize = getMeasuredWidth(); + heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (childWidthSize * hwRatio), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerRefreshLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerRefreshLayout.java new file mode 100644 index 000000000..90c4708b6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerRefreshLayout.java @@ -0,0 +1,227 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +import com.yizhuan.erban.R; + + +/** + * 下拉刷新上拉加载控件,目前适用于RecyclerView + * Created by huanghaibin on 16-5-3. + */ +public class RecyclerRefreshLayout extends SwipeRefreshLayout implements SwipeRefreshLayout.OnRefreshListener { + private RecyclerView mRecycleView; + + private int mTouchSlop; + + private SuperRefreshLayoutListener listener; + + private boolean mIsOnLoading = false; + + private boolean mCanLoadMore = true; + + private boolean mHasMore = true; + + private int mYDown; + + private int mLastY; + + public RecyclerRefreshLayout(Context context) { + this(context, null); + } + + public RecyclerRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + setOnRefreshListener(this); + } + + + @Override + public void onRefresh() { + if (listener != null && !mIsOnLoading) { + listener.onRefreshing(); + } else + setRefreshing(false); + } + + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + // 初始化ListView对象 + if (mRecycleView == null) { + getRecycleView(); + } + } + + /** + * 获取RecyclerView,后续支持AbsListView + */ + private void getRecycleView() { + if (getChildCount() > 0) { + View childView = getChildAt(0); + if (!(childView instanceof RecyclerView)) { + childView = findViewById(R.id.recyclerView); + } + if (childView != null && childView instanceof RecyclerView) { + mRecycleView = (RecyclerView) childView; + mRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + if (canLoad() && mCanLoadMore) { + loadData(); + } + } + }); + } + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + final int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + mYDown = (int) event.getRawY(); + break; + case MotionEvent.ACTION_MOVE: + mLastY = (int) event.getRawY(); + break; + default: + break; + } + return super.dispatchTouchEvent(event); + } + + /** + * 是否可以加载更多, 条件是到了最底部 + * + * @return isCanLoad + */ + private boolean canLoad() { + return isScrollBottom() && !mIsOnLoading && isPullUp() && mHasMore; + } + + /** + * 如果到了最底部,而且是上拉操作.那么执行onLoad方法 + */ + private void loadData() { + if (listener != null) { + setOnLoading(true); + listener.onLoadMore(); + } + } + + /** + * 是否是上拉操作 + * + * @return isPullUp + */ + private boolean isPullUp() { + return (mYDown - mLastY) >= mTouchSlop; + } + + /** + * 设置正在加载 + * + * @param loading 设置正在加载 + */ + public void setOnLoading(boolean loading) { + mIsOnLoading = loading; + if (!mIsOnLoading) { + mYDown = 0; + mLastY = 0; + } + } + + /** + * 判断是否到了最底部 + */ + private boolean isScrollBottom() { + return (mRecycleView != null && mRecycleView.getAdapter() != null) + && getLastVisiblePosition() == (mRecycleView.getAdapter().getItemCount() - 1); + } + + /** + * 加载结束记得调用 + */ + public void onComplete() { + setOnLoading(false); + setRefreshing(false); + mHasMore = true; + } + + /** + * 是否可加载更多 + * + * @param mCanLoadMore 是否可加载更多 + */ + public void setCanLoadMore(boolean mCanLoadMore) { + this.mCanLoadMore = mCanLoadMore; + } + + /** + * 获取RecyclerView可见的最后一项 + * + * @return 可见的最后一项position + */ + public int getLastVisiblePosition() { + int position; + if (mRecycleView.getLayoutManager() instanceof LinearLayoutManager) { + position = ((LinearLayoutManager) mRecycleView.getLayoutManager()).findLastVisibleItemPosition(); + } else if (mRecycleView.getLayoutManager() instanceof GridLayoutManager) { + position = ((GridLayoutManager) mRecycleView.getLayoutManager()).findLastVisibleItemPosition(); + } else if (mRecycleView.getLayoutManager() instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) mRecycleView.getLayoutManager(); + int[] lastPositions = layoutManager.findLastVisibleItemPositions(new int[layoutManager.getSpanCount()]); + position = getMaxPosition(lastPositions); + } else { + position = mRecycleView.getLayoutManager().getItemCount() - 1; + } + return position; + } + + /** + * 获得最大的位置 + * + * @param positions 获得最大的位置 + * @return 获得最大的位置 + */ + private int getMaxPosition(int[] positions) { + int maxPosition = Integer.MIN_VALUE; + for (int position : positions) { + maxPosition = Math.max(maxPosition, position); + } + return maxPosition; + } + + /** + * 添加加载和刷新 + * + * @param listener add the listener for SuperRefreshLayout + */ + public void setSuperRefreshLayoutListener(SuperRefreshLayoutListener listener) { + this.listener = listener; + } + + public interface SuperRefreshLayoutListener { + void onRefreshing(); + + void onLoadMore(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoBugLinearLayoutManager.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoBugLinearLayoutManager.java new file mode 100644 index 000000000..644f5bbab --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoBugLinearLayoutManager.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; + +/** + * Created by ${Seven} on 2017/10/18. + */ + +public class RecyclerViewNoBugLinearLayoutManager extends LinearLayoutManager { + public RecyclerViewNoBugLinearLayoutManager(Context context) { + super( context ); + } + + public RecyclerViewNoBugLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { + super( context, orientation, reverseLayout ); + } + + public RecyclerViewNoBugLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super( context, attrs, defStyleAttr, defStyleRes ); + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + //try catch一下 + super.onLayoutChildren( recycler, state ); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @Override + public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + return super.scrollVerticallyBy(dy, recycler, state); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoViewpagerScroll.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoViewpagerScroll.java new file mode 100644 index 000000000..cda2c3e01 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RecyclerViewNoViewpagerScroll.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * 横向RecyclerView与Viewpager结合使用, RecyclerView区域禁止Viewpager滑动 + */ +public class RecyclerViewNoViewpagerScroll extends RecyclerView { + public RecyclerViewNoViewpagerScroll(Context context) { + super(context); + } + + public RecyclerViewNoViewpagerScroll(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public RecyclerViewNoViewpagerScroll(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + getParent().requestDisallowInterceptTouchEvent(true); + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RedPacketDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RedPacketDialog.java new file mode 100644 index 000000000..bb4546580 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RedPacketDialog.java @@ -0,0 +1,122 @@ +package com.yizhuan.erban.ui.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.AccelerateInterpolator; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.wallet.RedBagActivity; +import com.yizhuan.erban.ui.wallet.WalletActivity; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfoV2; + +/** + * @author chenran + * @date 2017/10/4 + */ + +public class RedPacketDialog extends BaseActivity implements View.OnClickListener{ + + private ImageView openRed; + private ImageView imgClose; + private ImageView checkDetail; + private TextView redMoney; + private TextView source; + private RelativeLayout openRedPacket; + private LinearLayout checkRedPacket; + private RedPacketInfoV2 redPacketInfo; + + private ObjectAnimator mObjectAnimator; + + public static void start(Context context, RedPacketInfoV2 redPacketInfoV2) { + Intent intent = new Intent(context, RedPacketDialog.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("redPacketInfo", redPacketInfoV2); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.red_packet_dialog); + redPacketInfo = (RedPacketInfoV2) getIntent().getSerializableExtra("redPacketInfo"); + initView(); + setListener(); + } + + private void setListener() { + imgClose.setOnClickListener(this); + openRed.setOnClickListener(this); + checkDetail.setOnClickListener(this); + } + + private void initView() { + openRedPacket = (RelativeLayout) findViewById(R.id.open_red_packet); + checkRedPacket = findViewById(R.id.check_red_packet); + openRed = (ImageView) findViewById(R.id.img_open); + imgClose = (ImageView) findViewById(R.id.img_close); + redMoney = (TextView) findViewById(R.id.tv_red_money); + checkDetail = (ImageView) findViewById(R.id.tv_look); + source = (TextView) findViewById(R.id.source); + + source.setText("收到" + redPacketInfo.getPacketName() + "红包"); + redMoney.setText(String.valueOf(redPacketInfo.getPacketNum())); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.img_open: + startRedPacketAnim(v); + break; + case R.id.img_close: + finish(); + break; + case R.id.tv_look: + startActivity(new Intent(context, RedBagActivity.class)); + finish(); + break; + default: + } + } + + private void startRedPacketAnim(View v) { + v.setOnClickListener(null); + mObjectAnimator = ObjectAnimator.ofFloat(v, "rotationX", 0, 360, 720, 1080, 1540, 1900); + mObjectAnimator.setDuration(1000); + mObjectAnimator.setInterpolator(new AccelerateInterpolator()); + mObjectAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + openRedPacket.setVisibility(View.INVISIBLE); + checkRedPacket.setVisibility(View.VISIBLE); + } + }); + mObjectAnimator.start(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mObjectAnimator != null) { + if (mObjectAnimator.isRunning()) { + mObjectAnimator.cancel(); + } + mObjectAnimator = null; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RedPointView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RedPointView.java new file mode 100644 index 000000000..b46fd7792 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RedPointView.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatTextView; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +/** + * 本来是继承View,但是发现new出来的paint和textview不一样,(暂时没找到原因) + * 所以继承textview ,获取textview的paint + * create by lvzebiao @2019/5/7 + */ +public class RedPointView extends AppCompatTextView { + + private String text; + + private TextPaint textPaint; + + private float textYOffset; + + private Rect rect; + + private int padding; + + public RedPointView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.RedPointView, 0, 0); + padding = a.getDimensionPixelOffset(R.styleable.RedPointView_rpv_padding, UIUtil.dip2px(context, 5)); + a.recycle(); + + rect = new Rect(); + textPaint = getPaint(); + //textPaint.setColor(textColor); + textPaint.setTextAlign(Paint.Align.CENTER); + //textPaint.setTextSize(textSize); + Paint.FontMetrics textFontMetrics = textPaint.getFontMetrics(); + /* + * drawText从baseline开始,baseline的值为0,baseline的上面为负值,baseline的下面为正值, + * 即这里ascent为负值,descent为正值。 + * 比如ascent为-20,descent为5,那需要移动的距离就是20 - (20 + 5)/ 2 + */ + textYOffset = -textFontMetrics.ascent - (-textFontMetrics.ascent + textFontMetrics.descent) / 2; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int height = MeasureSpec.getSize(heightMeasureSpec); + int textWidth = 0; + if (!TextUtils.isEmpty(text) && text.length() >= 2) { + //测量文本的长度 + rect.setEmpty(); + textPaint.getTextBounds(text, 0, text.length(), rect); + textWidth = rect.width(); + } + int width = Math.max(textWidth + padding * 2, height); + //noinspection SuspiciousNameCombination + setMeasuredDimension(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (!TextUtils.isEmpty(text)) { + canvas.drawText(text, (float) getWidth() / 2, (float) getHeight() / 2 + textYOffset, + textPaint); + } + } + + public void setNumber(String text) { + this.text = text; + invalidate(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RoomItemView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RoomItemView.java new file mode 100644 index 000000000..022e13075 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RoomItemView.java @@ -0,0 +1,211 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.text.StaticLayout; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.home.bean.HomeRoom; + +/** + *

首页item view

+ * + * @author Administrator + * @date 2017/11/29 + */ +public class RoomItemView extends LinearLayout implements View.OnClickListener { + public final static String TAG = RoomItemView.class.getSimpleName(); + private ImageView mIvCover; + private LivingIconView livingIconView; + private ImageView mIvTabCategory; + private ImageView mIvLockBg; + private TextView mTvTitle; + private ImageView mIvTabLabel; + private ImageView mIvEmperorRecommend; + private TextView mTvOnlineNumber; + private Context mContext; + private LinearLayout llNameContainer; + + private int mRound; + private int mTagHeight, mBadgeHeight; + private HomeRoom mHomeRoom; + private boolean showLiving; + + public RoomItemView(Context context) { + this(context, null); + } + + public RoomItemView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RoomItemView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + inflate(context, R.layout.list_room_item_view, this); + + livingIconView = findViewById(R.id.liv_living_icon); + mIvCover = findViewById(R.id.iv_cover); + mIvTabCategory = (ImageView) findViewById(R.id.iv_tab_category); + mIvLockBg = (ImageView) findViewById(R.id.lock_bg); + mTvTitle = (TextView) findViewById(R.id.title); + mIvTabLabel = (ImageView) findViewById(R.id.iv_tab_label); + mIvEmperorRecommend = (ImageView) findViewById(R.id.iv_emperor_recommend); + mTvOnlineNumber = (TextView) findViewById(R.id.tv_online_number); + llNameContainer = findViewById(R.id.ll_name_container); + mRound = context.getResources().getDimensionPixelOffset(R.dimen.common_cover_round_size); + mTagHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + mBadgeHeight = (int) context.getResources().getDimension(R.dimen.tag_height); + + setOnClickListener(this); + + showLiving = true; + } + + public void bindData(HomeRoom homeRoom) { + mHomeRoom = homeRoom; + if (homeRoom == null) { + setVisibility(INVISIBLE); + return; + } + setVisibility(VISIBLE); + if (showLiving) { + livingIconView.setColor(getResources().getColor(R.color.color_333333)); + livingIconView.start(); + } else { + livingIconView.setVisibility(INVISIBLE); + } + + livingIconView.setColor(Color.WHITE); + livingIconView.start(); + mTvOnlineNumber.setText(getResources().getString(R.string.online_number_text, homeRoom.getOnlineNum())); +// LogUtil.d(TAG," width:" + Utils.getWindowWidth(mContext) * 0.6f); +// mTvTitle.setMaxWidth((int) (Utils.getWindowWidth(mContext) * 0.6f)); + mTvTitle.setText(homeRoom.getTitle()); +// llNameContainer.getViewTreeObserver().addOnGlobalLayoutListener(new MyOnGlobalLayoutListener(mTvTitle) { +// +// @Override +// public void onGlobalLayout() { +// llNameContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this); +// int viewWidth = llNameContainer.getWidth(); +//// LogUtil.d(TAG,"parent width:" + viewWidth + " child width:" + mTvTitle.getMeasuredWidth()); +// int textWidth = (int) StaticLayout.getDesiredWidth(((TextView)markView).getText().toString(), ((TextView)markView).getPaint()); +// if (textWidth > (viewWidth - Utils.dip2px(mContext, 30))) { +// LayoutParams lp = (LayoutParams) markView.getLayoutParams(); +// lp.width = viewWidth - Utils.dip2px(mContext, 30); +//// LogUtil.d(TAG," mod width:" + lp.width); +// markView.setLayoutParams(lp); +// } +// } +// }); + mIvLockBg.setVisibility(!TextUtils.isEmpty(homeRoom.getRoomPwd()) ? VISIBLE : GONE); + + GlideApp.with(mContext) + .load(TextUtils.isEmpty(homeRoom.tagPict) ? R.mipmap.ic_tag_default : homeRoom.tagPict) + .placeholder(R.mipmap.ic_tag_default) + .error(R.mipmap.ic_tag_default) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { + float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); + int width = Math.round(mTagHeight / ratio); + int height = mTagHeight; + ViewGroup.LayoutParams params = mIvTabCategory.getLayoutParams(); + params.width = width; + params.height = height; + mIvTabCategory.setLayoutParams(params); + mIvTabCategory.setImageDrawable(drawable); + return true; + } + }) + .into(mIvTabCategory); + + + mIvTabLabel.setVisibility(TextUtils.isEmpty(homeRoom.badge) ? View.GONE : View.VISIBLE); + GlideApp.with(mContext) + .load(homeRoom.badge) + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object o, Target target, boolean b) { + return false; + } + + @Override + public boolean onResourceReady(Drawable drawable, Object o, Target target, DataSource dataSource, boolean b) { + float ratio = (drawable.getIntrinsicHeight() + 0.F) / drawable.getIntrinsicWidth(); + int width = Math.round(mBadgeHeight / ratio); + int height = mBadgeHeight; + ViewGroup.LayoutParams params = mIvTabLabel.getLayoutParams(); + params.width = width; + params.height = height; + mIvTabLabel.setLayoutParams(params); + mIvTabLabel.setImageDrawable(drawable); + return true; + } + }) + .into(mIvTabLabel); + // 皇帝推荐 + mIvEmperorRecommend.setVisibility(homeRoom.getIsRecom() > 0 ? View.VISIBLE : View.GONE); + GlideApp.with(mContext) + .load(mContext.getResources().getDrawable(R.drawable.ic_king_recommend)) +// .load(homeRoom.getIsRecom() > 0 ? NobleUtil.getEmperorRecommendTag(7) : 0) + .fitCenter() + .into(mIvEmperorRecommend); + + if (!TextUtils.isEmpty(homeRoom.getAvatar())) { + ImageLoadUtils.loadAvatar(homeRoom.getAvatar(), mIvCover, R.drawable.default_cover); + } else { + GlideApp.with(mContext) + .load(R.drawable.default_cover) + .placeholder(R.drawable.default_cover) + .transforms(new CenterCrop(), new RoundedCorners(mRound)) + .into(mIvCover); + } + } + + + @Override + public void onClick(View v) { + if (mHomeRoom != null) { + AVRoomActivity.start(mContext, mHomeRoom.getUid()); + } + } + + public void setShowLiving(boolean showLiving) { + this.showLiving = showLiving; + } + + private static abstract class MyOnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { + protected View markView; + public MyOnGlobalLayoutListener(View view) { + this.markView = view; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/RoomTypeSelectDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/RoomTypeSelectDialog.java new file mode 100644 index 000000000..7f69e559b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/RoomTypeSelectDialog.java @@ -0,0 +1,254 @@ +package com.yizhuan.erban.ui.widget; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.activity.OpenRoomActivity; +import com.yizhuan.erban.base.BaseMvpActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; + +import io.reactivex.disposables.CompositeDisposable; + +import static com.yizhuan.xchat_android_core.user.bean.UserInfo.USER_TYPE_OFFICIAL; + +/** + * 打开房间类型dialog + * + * @author chenran + * @date 2017/8/3 + */ +@Deprecated +public class RoomTypeSelectDialog extends Dialog implements View.OnClickListener { + private Context context; + private int roomType; + private CompositeDisposable disposable; + + public RoomTypeSelectDialog(Context context, boolean cancelable, + OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + // TODO Auto-generated constructor stub + this.context = context; + } + + public RoomTypeSelectDialog(Context context) { + super(context, R.style.BottomSelectDialogNotTransparent); + this.context = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.dialog_bottom_type_select); + findViewById(R.id.open_chat_light_layout).setOnClickListener(this); + findViewById(R.id.open_auction_layout).setOnClickListener(this); + findViewById(R.id.open_home_party_layout).setOnClickListener(this); + findViewById(R.id.close_image).setOnClickListener(this); + + setDialogShowAttributes(getContext(), this); + } + + public static void setDialogShowAttributes(Context context, Dialog dialog) { + + WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + int mScreenWidth = winManager.getDefaultDisplay().getWidth(); + Window mWindow = dialog.getWindow(); + mWindow.getDecorView().setPadding(0, 0, 0, 0); + WindowManager.LayoutParams Params = mWindow.getAttributes(); + Params.windowAnimations = R.style.bottom_dialog_anim_style; + Params.width = WindowManager.LayoutParams.MATCH_PARENT; + Params.height = WindowManager.LayoutParams.WRAP_CONTENT; + mWindow.setAttributes(Params); + mWindow.setGravity(Gravity.BOTTOM); + } + + @Override + public void onClick(View v) { + String waitingText = context.getString(R.string.waiting_text); + switch (v.getId()) { + case R.id.open_auction_layout: + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + if (userInfo.getDefUser() == USER_TYPE_OFFICIAL) { + ((BaseMvpActivity) context).getDialogManager().showProgressDialog(context, waitingText); + roomType = RoomInfo.ROOMTYPE_AUCTION; + requestRoomInfo(); + } else { + ((BaseMvpActivity) context).toast("您暂无权限开竞拍房"); + } + } + break; + case R.id.open_home_party_layout: + ((BaseMvpActivity) context).getDialogManager().showProgressDialog(context, waitingText); + roomType = RoomInfo.ROOMTYPE_HOME_PARTY; + requestRoomInfo(); + break; + case R.id.open_chat_light_layout: + roomType = RoomInfo.ROOMTYPE_LIGHT_CHAT; + ((BaseMvpActivity) context).getDialogManager().showProgressDialog(context, waitingText); + requestRoomInfo(); + break; + case R.id.close_image: + dismiss(); + break; + default: + } + } + + private void requestRoomInfo() { + AvRoomModel.get() + .requestRoomInfoFromService(String.valueOf(AuthModel.get().getCurrentUid()), + new CallBack() { + @Override + public void onSuccess(RoomInfo data) { + onGetRoomInfo(data); + } + + @Override + public void onFail(int code, String error) { + onGetRoomInfoFail(error); + } + }); + } + + private void openRoom() { + if (roomType == RoomInfo.ROOMTYPE_HOME_PARTY) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + disposable.add(AvRoomModel.get().openRoom( + userInfo.getUid(), roomType, null, null, null, null) + .subscribe((roomResult, throwable) -> { + if (throwable != null) { + onOpenRoomFail(throwable.getMessage()); + } else if (roomResult != null && roomResult.isSuccess()) { + onOpenRoom(roomResult.getData()); + } else if (roomResult != null && !roomResult.isSuccess()) { + if (roomResult.getCode() == 1500) { + onAlreadyOpenedRoom(); + } else { + onOpenRoomFail(roomResult.getError()); + } + } else { + onOpenRoomFail("未知错误"); + } + }) + ); + } else if (roomType == RoomInfo.ROOMTYPE_AUCTION) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + OpenRoomActivity.startAuction(context); + dismiss(); + } else { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + OpenRoomActivity.startHomeParty(context); + dismiss(); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + context = null; + if (disposable != null && !disposable.isDisposed()) { + disposable.dispose(); + } + } + + private void onGetRoomInfo(RoomInfo roomInfo) { + if (roomInfo != null) { + if (roomInfo.isValid()) { + if (roomInfo.getType() != roomType) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + String roomName = ""; + if (roomInfo.getType() == RoomInfo.ROOMTYPE_AUCTION) { + roomName = "竞拍房"; + } else if (roomInfo.getType() == RoomInfo.ROOMTYPE_HOME_PARTY) { + roomName = "轰趴房"; + } else { + roomName = "轻聊房"; + } + ((BaseMvpActivity) context).getDialogManager().showOkCancelDialog( + "当前正在" + roomName + "中,是否关闭当前房间?", true, + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + + } + + @Override + public void onOk() { + ((BaseMvpActivity) context).getDialogManager().showProgressDialog(context, "请稍后..."); + quitRoomForOurService(); + } + }); + } else { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + AVRoomActivity.start(context, roomInfo.getUid()); + dismiss(); + } + } else { + openRoom(); + } + + } else { + openRoom(); + } + } + + private void quitRoomForOurService() { + AvRoomModel.get() + .quitRoomForOurService(new CallBack() { + @Override + public void onSuccess(String data) { + onCloseRoomInfo(); + } + + @Override + public void onFail(int code, String error) { + onCloseRoomInfoFail(error); + } + }); + } + + private void onGetRoomInfoFail(String error) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + ((BaseMvpActivity) context).toast(error); + } + + private void onCloseRoomInfo() { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + openRoom(); + } + + private void onCloseRoomInfoFail(String error) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + ((BaseMvpActivity) context).toast(error); + } + + private void onOpenRoom(RoomInfo roomInfo) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + AVRoomActivity.start(context, roomInfo.getUid()); + dismiss(); + } + + private void onOpenRoomFail(String error) { + ((BaseMvpActivity) context).getDialogManager().dismissDialog(); + ((BaseMvpActivity) context).toast(error); + } + + private void onAlreadyOpenedRoom() { + ((BaseMvpActivity) context).getDialogManager().showProgressDialog(context, "请稍后..."); + quitRoomForOurService(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ShareDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ShareDialog.java new file mode 100644 index 000000000..269db075b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ShareDialog.java @@ -0,0 +1,168 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.os.Bundle; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.view.View; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.StringUtils; + +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.tencent.qq.QQ; +import cn.sharesdk.tencent.qzone.QZone; +import cn.sharesdk.wechat.friends.Wechat; +import cn.sharesdk.wechat.moments.WechatMoments; + +/** + * @author xiaoyu + * @date 2017/12/13 + */ + +public class ShareDialog extends BottomSheetDialog implements View.OnClickListener { + + public static final int TYPE_SHARE_NORMAL = 0; + public static final int TYPE_SHARE_ROOM = 1; + public static final int TYPE_SHARE_FAMILY = 2; + public static final int TYPE_SHARE_TEAM = 3; + public static final int TYPE_SHARE_H5 = 4; + + private Context context; + private WindowManager windowManager; + private int width; + private TextView tvName; + private TextView tvErban; + private TextView tvWeixin; + private TextView tvWeixinpy; + private TextView tvQq; + private TextView tvQqZone; + private TextView tvCancel; + private static final String TAG = "ShareDialog"; + private OnShareDialogItemClick onShareDialogItemClick; + private int type = TYPE_SHARE_NORMAL; + + + public ShareDialog(Context context) { + super(context, R.style.ErbanBottomSheetDialog); + this.context = context; + } + + public void setOnShareDialogItemClick(OnShareDialogItemClick onShareDialogItemClick) { + this.onShareDialogItemClick = onShareDialogItemClick; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_share); + setCanceledOnTouchOutside(true); + tvName = (TextView) findViewById(R.id.tv_title); + tvErban = findViewById(R.id.tv_erban); + tvWeixin = (TextView) findViewById(R.id.tv_weixin); + tvWeixinpy = (TextView) findViewById(R.id.tv_weixinpy); + tvQq = (TextView) findViewById(R.id.tv_qq); + tvQqZone = (TextView) findViewById(R.id.tv_qq_zone); + tvCancel = (TextView) findViewById(R.id.tv_cancel); + + tvErban.setOnClickListener(this); + tvWeixin.setOnClickListener(this); + tvWeixinpy.setOnClickListener(this); + tvQq.setOnClickListener(this); + tvQqZone.setOnClickListener(this); + tvCancel.setOnClickListener(this); + findViewById(R.id.tv_qq_game).setOnClickListener(this); + FrameLayout bottomSheet = (FrameLayout) findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + } + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = context.getResources().getDisplayMetrics().heightPixels - (Utils.hasSoftKeys(context) ? Utils.getNavigationBarHeight(context) : 0); + getWindow().setAttributes(params); + + if (type == TYPE_SHARE_H5){ + tvErban.setVisibility(View.GONE); + tvQq.setVisibility(View.GONE); + } + } + + public void setName(String name) { + if (!StringUtils.isEmpty(name)) { + tvName.setText(name); + } + } + + public void setType(int type) { + this.type = type; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_erban: + if (onShareDialogItemClick != null) { + if (type != TYPE_SHARE_H5) { + onShareDialogItemClick.onInAppSharingItemClick(); + } else { +// Toast.makeText(context, "该内容不能分享给轻寻好友", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("该内容不能分享给轻寻好友"); + } + } + dismiss(); + break; + + case R.id.tv_weixin: + if (onShareDialogItemClick != null) { + onShareDialogItemClick.onSharePlatformClick(ShareSDK.getPlatform(Wechat.NAME)); + } + dismiss(); + break; + case R.id.tv_weixinpy: + if (onShareDialogItemClick != null) { + onShareDialogItemClick.onSharePlatformClick(ShareSDK.getPlatform(WechatMoments.NAME)); + } + dismiss(); + break; + case R.id.tv_qq: + case R.id.tv_qq_game: + if (onShareDialogItemClick != null) { + onShareDialogItemClick.onSharePlatformClick(ShareSDK.getPlatform(QQ.NAME)); + } + dismiss(); + break; + case R.id.tv_qq_zone: + if (onShareDialogItemClick != null) { + onShareDialogItemClick.onSharePlatformClick(ShareSDK.getPlatform(QZone.NAME)); + } + dismiss(); + break; + case R.id.tv_cancel: + dismiss(); + break; + default: + break; + } + } + + public interface OnShareDialogItemClick { + + /** + * 应用内分享 + */ + void onInAppSharingItemClick(); + + /** + * 应用外分享包括微信 qq 等平台 + * @param platform + */ + void onSharePlatformClick(Platform platform); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/ShareRedBagDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/ShareRedBagDialog.java new file mode 100644 index 000000000..a649a2798 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/ShareRedBagDialog.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.ui.widget; + +import android.app.Dialog; +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StyleRes; + +/** + * Created by Seven on 2017/9/24. + */ + +public class ShareRedBagDialog extends Dialog { + public ShareRedBagDialog(@NonNull Context context) { + super(context); + } + + public ShareRedBagDialog(@NonNull Context context, @StyleRes int themeResId) { + super(context, themeResId); + } + + protected ShareRedBagDialog(@NonNull Context context, boolean cancelable, @Nullable + OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/SquareImageView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/SquareImageView.java new file mode 100644 index 000000000..1b85e3b3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/SquareImageView.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; + +/** + * Created by chenran on 2017/7/24. + */ +public class SquareImageView extends android.support.v7.widget.AppCompatImageView { + + + public SquareImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public SquareImageView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SquareImageView(Context context) { + super(context); + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); + + int childWidthSize = getMeasuredWidth(); +// int childHeightSize = getMeasuredHeight(); + + heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/SquareLayout.java b/app/src/main/java/com/yizhuan/erban/ui/widget/SquareLayout.java new file mode 100644 index 000000000..b5cc93cba --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/SquareLayout.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +/** + * Created by chenran on 2017/7/24. + */ +public class SquareLayout extends RelativeLayout { + + + public SquareLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public SquareLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public SquareLayout(Context context) { + super(context); + } + + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); + + int childWidthSize = getMeasuredWidth(); + int childHeightSize = getMeasuredHeight(); + + heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/SuperEditText.java b/app/src/main/java/com/yizhuan/erban/ui/widget/SuperEditText.java new file mode 100644 index 000000000..5c7cdc92d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/SuperEditText.java @@ -0,0 +1,109 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.InputType; +import android.util.AttributeSet; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * Created by huangmeng1 on 2018/6/27. + */ + +public class SuperEditText extends FrameLayout { + private String hint=""; + private String titleHint = ""; + private TextView tvTitle; + private EditText editText; + private ImageView imageView; + private boolean close; + private boolean isPay; + + private int hintColor; + private int textColor; + + public void setPay(boolean pay) { + isPay = pay; + } + + public SuperEditText(@NonNull Context context) { + this(context,null); + } + + public SuperEditText(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.SuperEditText, 0, 0); + hint = a.getString(R.styleable.SuperEditText_hint); + titleHint = a.getString(R.styleable.SuperEditText_title_hint); + hintColor = a.getColor(R.styleable.SuperEditText_hint_color, Color.GRAY); + textColor = a.getColor(R.styleable.SuperEditText_text_color, Color.BLACK); + a.recycle(); + init(); + } + public void setIntegerType(){ + editText.setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_PASSWORD); + } + + public EditText getEditText() { + return editText; + } + + private void init(){ + inflate(getContext(), R.layout.layout_edit_eyes, this); + + tvTitle = findViewById(R.id.tv_title_hint); + tvTitle.setText(titleHint); + + editText = findViewById(R.id.edit); + editText.setHintTextColor(hintColor); + editText.setTextColor(textColor); + imageView = findViewById(R.id.iv_eyes); + editText.setHint(hint); + imageView.setOnClickListener(v -> { + if (isPay){ + if(!close){ + editText.setInputType(InputType.TYPE_CLASS_NUMBER); + imageView.setImageResource(R.drawable.ic_eyes_open); + }else { + setIntegerType(); + imageView.setImageResource(R.drawable.ic_eyes_close); + } + close=!close; + }else { + if (editText.getInputType() == 129) { + editText.setInputType(145); + imageView.setImageResource(R.drawable.ic_eyes_open); + } else { + editText.setInputType(129); + imageView.setImageResource(R.drawable.ic_eyes_close); + } + } + + editText.setSelection(editText.getText().length()); + }); + } + + public String getText(){ + return editText.getText().toString(); + } + + public void setTitleHint(String title) { + titleHint = title; + tvTitle.setText(titleHint); + } + + public void setEditHint(String hint) { + this.hint = hint; + editText.setHint(this.hint); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/TextWatcherSimple.java b/app/src/main/java/com/yizhuan/erban/ui/widget/TextWatcherSimple.java new file mode 100644 index 000000000..50758665a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/TextWatcherSimple.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.ui.widget; + +import android.text.TextWatcher; + +/** + * create by lvzebiao @2019/12/1 + */ +public abstract class TextWatcherSimple implements TextWatcher { + + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoDialog.java new file mode 100644 index 000000000..bf7281583 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoDialog.java @@ -0,0 +1,1274 @@ +package com.yizhuan.erban.ui.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.support.v7.widget.AppCompatImageView; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.flexbox.FlexboxLayout; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.yizhuan.erban.R; +import com.yizhuan.erban.UIHelper; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.avroom.adapter.UpMicAdapter; +import com.yizhuan.erban.avroom.giftvalue.GiftValueDialogUiHelper; +import com.yizhuan.erban.avroom.ktv.KtvMusicManager; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.user.UserInfoActivity; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_constants.XChatConstants; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.decoration.headwear.bean.HeadWearInfo; +import com.yizhuan.xchat_android_core.family.bean.FamilyInfo; +import com.yizhuan.xchat_android_core.family.model.FamilyModel; +import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; +import com.yizhuan.xchat_android_core.kick.KickModel; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.manager.RoomEvent; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleResourceType; +import com.yizhuan.xchat_android_core.noble.NobleUtil; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomResult; +import com.yizhuan.xchat_android_core.room.dragonball.DragonBallModel; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.GiftValueModel; +import com.yizhuan.xchat_android_core.room.giftvalue.bean.RoomGiftValue; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.HomePartyModel; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.BaseInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; + +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_DRAGON_BAR; +import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_DRAGON_BAR_CANCEL; +import static com.yizhuan.xchat_android_core.manager.RoomEvent.DRAGON_BAR_CANCEL; + +/** + * 替代原来的框架,用来替代UserInfoDialog的 + * 现在简单来说在view层使用model,,,,,以后可以改过来 + * + * @author xiaoyu + * @date 2017/12/13 + */ + +public class UserInfoDialog extends AppCompatDialog implements View.OnClickListener { + private Context context; + private long uid; + private boolean isAttention; + private UserInfo userInfo; + private ImageView closeImage; + //private ImageView ivTopBg; + private FrameLayout avatarLayout; + private ImageView ivAvatarHeadWear; + private ImageView avatar; + /** + * 头像高斯模糊背景 + */ + private ImageView ivAvatarBg; + private ImageView ivBadge; + private TextView nick; + private ImageView ivGender; + private TextView erbanId; + + private TextView fansNumber; + private AppCompatImageView ivOfficialView; + private AppCompatImageView ivNewUser; + private AppCompatImageView mIvGoodNumber; + private AppCompatImageView mIvUserLevel; + private AppCompatImageView mIvUserCharm; + private LinearLayout llFamily; + private TextView tvFamilyNameLabel; + private TextView tvFamilyName; + private FlexboxLayout flexbox; + private ImageView iv101; + private ImageView ivTag; + + private long myUid; + private Disposable subscribe; + private String topBg = ""; + + private CompositeDisposable mCompositeDisposable; + private List buttons; + private boolean isMySelf; + + private HomePartyModel homePartyModel; + private boolean isInRoom; // true:房间内打开 false:房间外打开 + + private SuperAdminModel mSuperAdminModel; + + private ViewItem findHimView; + + public UserInfoDialog(Context context, long uid, List buttons, boolean isInRoom) { + super(context, R.style.ErbanUserInfoDialog); + this.context = context; + this.uid = uid; + this.buttons = buttons; + isMySelf = (this.uid == AuthModel.get().getCurrentUid()); + homePartyModel = new HomePartyModel(); + mSuperAdminModel = new SuperAdminModel(); + this.isInRoom = isInRoom; + } + + public UserInfoDialog(Context context, long uid) { + this(context, uid, null, false); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCompositeDisposable = new CompositeDisposable(); + setContentView(R.layout.dialog_user_info); + setCanceledOnTouchOutside(true); + //设置全屏 + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + + setMicViewVisiable(false); + closeImage = findViewById(R.id.close_image); + avatarLayout = findViewById(R.id.fl_avatar_layout); + avatar = findViewById(R.id.avatar); + ivAvatarBg = findViewById(R.id.iv_avatar_bg); + nick = findViewById(R.id.nick); + erbanId = findViewById(R.id.tv_erban_id); + ivGender = findViewById(R.id.iv_gender); + + fansNumber = findViewById(R.id.fans_number); + //ivTopBg = findViewById(R.id.iv_top_bg); + flexbox = findViewById(R.id.flexbox); + + ivAvatarHeadWear = findViewById(R.id.iv_avatar_head_wear); + ivBadge = findViewById(R.id.iv_badge); + ivBadge.setVisibility(View.GONE); + ivOfficialView = findViewById(R.id.iv_user_official); + ivNewUser = (AppCompatImageView) findViewById(R.id.iv_new_user); + mIvGoodNumber = findViewById(R.id.iv_good_number); + mIvUserLevel = findViewById(R.id.iv_user_level); + mIvUserCharm = findViewById(R.id.iv_user_charm); + + llFamily = (LinearLayout) findViewById(R.id.ll_family); + tvFamilyNameLabel = (TextView) findViewById(R.id.tv_family_name_label); + tvFamilyName = (TextView) findViewById(R.id.tv_family_name); + iv101 = findViewById(R.id.iv_101); + ivTag = findViewById(R.id.iv_tag); + + avatarLayout.setOnClickListener(this); + closeImage.setOnClickListener(this); + TextView tvReport = findViewById(R.id.tv_report); + if (tvReport != null) { + if (isMySelf) { + tvReport.setVisibility(View.GONE); + } else { + tvReport.setVisibility(View.VISIBLE); + tvReport.setOnClickListener(this); + } + } + + myUid = AuthModel.get().getCurrentUid(); + + addViewItems(); + addMainAndMicBottons(); + subscribe = IMNetEaseManager.get().getChatRoomEventObservable().subscribe(this::onReceiveRoomEvent); + initAttentData(); + + UserModel.get().getUserInfo(uid) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(UserInfo userInfo) { + UserInfoDialog.this.userInfo = userInfo; + updateView(); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + private void initAttentData() { + if (isMySelf) { + tvFamilyNameLabel.setText(tvFamilyNameLabel.getText().toString().replace("TA", "我")); + } else { + Disposable disposable = PraiseModel.get().isPraised(myUid, uid).subscribe(aBoolean -> { + isAttention = aBoolean; + if (attentView == null) return; + updateAttentView(); + attentView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toAttent(); + } + }); + }); + mCompositeDisposable.add(disposable); + } + } + + /** + * @param isVisiable ture则表示上麦的网格布局可见 + */ + @SuppressWarnings("ConstantConditions") + private void setMicViewVisiable(boolean isVisiable) { + findViewById(R.id.recycler_view_mic).setVisibility(isVisiable ? View.VISIBLE : View.GONE); + findViewById(R.id.layout_grid_button).setVisibility(isVisiable ? View.GONE : View.VISIBLE); + findViewById(R.id.ll_bottom_buttons).setVisibility(isVisiable ? View.GONE : View.VISIBLE); + } + + private View attentView; + + private void updateAttentView() { + TextView textView = attentView.findViewById(R.id.text); + textView.setText(isAttention ? "已关注Ta" : "关注Ta"); + ImageView imageView = attentView.findViewById(R.id.image); + imageView.setImageResource( + isAttention ? R.drawable.icon_dialog_cancel_attent : R.drawable.icon_dialog_attent); + } + + private void addViewItems() { + if (ListUtils.isListEmpty(buttons)) { + findViewById(R.id.layout_grid_button).setVisibility(View.GONE); + return; + } + int dialogWidth = context.getResources().getDimensionPixelOffset( + R.dimen.dp_room_user_dialog_width); + int itemWidth = dialogWidth / 4; + flexbox.removeAllViews(); + //底部item,不添加到网格 + List bottomList = new ArrayList<>(); + for (int i = 0; i < buttons.size(); i++) { + ViewItem buttonItem = buttons.get(i); + if (buttonItem.mButtonType == ViewItem.BUTTON_TYPE_NORMAL) { + View item = LayoutInflater.from(getContext()).inflate(buttonItem.resourceID, flexbox, false); + item.getLayoutParams().width = itemWidth; + TextView textView = item.findViewById(R.id.text); + textView.setText(buttonItem.mText); + ImageView imageView = item.findViewById(R.id.image); + imageView.setImageResource(buttonItem.imgRes); + //关注按钮的处理 + if (buttonItem.isAttent) { + if (!isMySelf) { + flexbox.addView(item); + attentView = item; + } + } else if (buttonItem.isFindTa) { + //找到他处理 + if (!isMySelf) { + findHimView = buttonItem; + } + + } else { + item.setOnClickListener(v -> { + buttonItem.mClickListener.onClick(); + if (!buttonItem.noDissmis) { + dismiss(); + } + }); + flexbox.addView(item); + } + } else if (buttonItem.mButtonType == ViewItem.BUTTON_TYPE_USER_CAR_BOTTOM) { + bottomList.add(buttonItem); + } + } + if (flexbox.getChildCount() == 0) { + findViewById(R.id.layout_grid_button).setVisibility(View.GONE); + } + } + + /** + * 添加主页麦位操作的button + */ + private void addMainAndMicBottons() { + LinearLayout llBottomButtons = findViewById(R.id.ll_bottom_buttons); + if (llBottomButtons == null) return; + llBottomButtons.removeAllViews(); + if (!isInRoom) { + hideBottom(); + return; + } + List bottomList = getMicRelativeButtons(String.valueOf(uid)); + //如果用户在麦上,而且登录用户是管理员,则显示此按钮 + if (AvRoomDataManager.get().isShowGiftValue() + && AvRoomDataManager.get().isManager()) { + + boolean onMic = AvRoomDataManager.get().isOnMic(uid); + boolean leaveMode = AvRoomDataManager.get().isLeaveMode() && AvRoomDataManager.get().isRoomOwner(uid); + + if (onMic || leaveMode) { + if (!SuperAdminUtil.isSuperAdmin()) { + bottomList.add(createClearGiftValueItem()); + } + } + } + if (ListUtils.isListEmpty(bottomList)) { + hideBottom(); + return; + } + for (int i = 0; i < bottomList.size(); i++) { + TextView textView = bottomList.get(i); + textView.setVisibility(View.INVISIBLE); + llBottomButtons.addView(textView); + } + llBottomButtons.post(() -> { + int parentWidth = llBottomButtons.getMeasuredWidth(); + int childCount = bottomList.size(); + if (bottomList.size() == 1) { + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(parentWidth, + ViewGroup.LayoutParams.MATCH_PARENT); + TextView textView = bottomList.get(0); + textView.setVisibility(View.VISIBLE); + textView.setLayoutParams(params); + return; + } + int[] wrapWidth = new int[childCount]; + int childWidths = 0; + for (int i = 0; i < bottomList.size(); i++) { + TextView textView = bottomList.get(i); + int width = textView.getMeasuredWidth(); + wrapWidth[i] = width; + childWidths += width; + } + //空白是多少 + int paddingSpace = (parentWidth - childWidths) / (childCount * 2); + //剩余是多少px + int leftPx = (parentWidth - childWidths) - paddingSpace * (childCount * 2); + leftPx = leftPx / childCount; + //重新计算item的宽度 + for (int i = 0; i < childCount; i++) { + wrapWidth[i] = wrapWidth[i] + 2 * paddingSpace; + } + for (int i = 0; i < llBottomButtons.getChildCount(); i++) { + View textView = llBottomButtons.getChildAt(i); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(wrapWidth[i] + leftPx, + ViewGroup.LayoutParams.MATCH_PARENT); + textView.setLayoutParams(params); + textView.setVisibility(View.VISIBLE); + } + }); + + } + + private void hideBottom() { + LinearLayout llBottomButtons = findViewById(R.id.ll_bottom_buttons); + if (llBottomButtons != null) { + llBottomButtons.setVisibility(View.GONE); + } + View lineBottom = findViewById(R.id.line_bottom); + if (lineBottom != null) { + lineBottom.setVisibility(View.GONE); + } + } + + private void onReceiveRoomEvent(RoomEvent roomEvent) { + if (roomEvent == null || roomEvent.getEvent() == RoomEvent.NONE) return; + int event = roomEvent.getEvent(); + if (event == RoomEvent.FOLLOW) { + onFollow(roomEvent.isSuccess()); + } else if (event == RoomEvent.UNFOLLOW) { + onUnFollow(roomEvent.isSuccess()); + } else if (RoomEvent.KICK_OUT_ROOM == event) { + onKickMember(roomEvent.getReason()); + } + } + + private void onKickMember(ChatRoomKickOutEvent reason) { + if (reason == null) return; + ChatRoomKickOutEvent.ChatRoomKickOutReason reasonReason = reason.getReason(); + if (reasonReason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + dismiss(); + } + } + + private void updateView() { + if (userInfo != null) { + ivOfficialView.setVisibility(userInfo.isOfficial() ? View.VISIBLE : View.GONE); + ivNewUser.setVisibility(userInfo.isNewUser() ? View.VISIBLE : View.GONE); + mIvGoodNumber.setVisibility(userInfo.isHasPrettyErbanNo() ? View.VISIBLE : View.GONE); + + // 这个方法能让图片不失真 + ImageLoadUtils.laodUsrInfoAvatar(context, userInfo.getAvatar(), avatar); + nick.setText(RegexUtil.getPrintableString(userInfo.getNick())); + erbanId.setText("ID" + userInfo.getErbanNo()); + ivGender.setImageResource( + userInfo.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + + // 设置粉丝数量 + fansNumber.setText(userInfo.getFansNum() + "粉丝"); + + //设置家族 + if (FamilyInfo.NO_FAMILY_ID.equals(userInfo.getFamilyId()) + || TextUtils.isEmpty(userInfo.getFamilyId()) + || MarketVerifyModel.get().isMarketChecking()) { + tvFamilyName.setText(context.getResources().getString(R.string.empty_family_text)); + } else { + loadSimpleFamilyInfo(userInfo.getFamilyId()); + } + + UserLevelVo userLevelVo = userInfo.getUserLevelVo(); + mIvUserLevel.setVisibility(userLevelVo == null ? View.GONE : View.VISIBLE); + mIvUserCharm.setVisibility(View.GONE); + if (userLevelVo != null) { + mIvUserLevel.setVisibility(TextUtils.isEmpty(userLevelVo.getExperUrl()) ? View.GONE : View.VISIBLE); + if (!TextUtils.isEmpty(userLevelVo.getExperUrl())) { + ImageLoadUtils.loadImage(context, userLevelVo.getExperUrl(), mIvUserLevel); + } + if (!TextUtils.isEmpty(userLevelVo.getCharmUrl())) { + mIvUserCharm.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(context, userLevelVo.getCharmUrl(), mIvUserCharm); + } + } + if (userInfo.getUserInfoSkillVo() != null) { + iv101.setVisibility(userInfo.getUserInfoSkillVo().isLiveTag() ? View.VISIBLE : View.GONE); + if (!TextUtils.isEmpty(userInfo.getUserInfoSkillVo().getSkillTag())) { + ImageLoadUtils.loadImage(context, userInfo.getUserInfoSkillVo().getSkillTag(), ivTag); + ivTag.setVisibility(View.VISIBLE); + } + } + // 改变贵族 + updateNobleView(); + + if (null != findHimView) { + //获取用户房间信息 + AvRoomModel.get().getUserRoom(userInfo.getUid()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(RoomResult roomResult) { + if (!roomResult.isSuccess()) { +// Toast.makeText(context, roomResult.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(roomResult.getMessage()); + return; + } + if (roomResult.getData() != null && roomResult.getData().getUid() != 0) { + int dialogWidth = context.getResources().getDimensionPixelOffset( + R.dimen.dp_room_user_dialog_width); + int itemWidth = dialogWidth / 4; + View item = LayoutInflater.from(getContext()).inflate(findHimView.resourceID, flexbox, false); + item.getLayoutParams().width = itemWidth; + TextView textView = item.findViewById(R.id.text); + textView.setText(findHimView.mText); + ImageView imageView = item.findViewById(R.id.image); + imageView.setImageResource(findHimView.imgRes); + item.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AVRoomActivity.start(context, roomResult.getData().getUid()); + } + }); + flexbox.addView(item); + + } + + } + + @Override + public void onError(Throwable e) { +// Toast.makeText(context, "获取用户房间信息异常。", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("获取用户房间信息异常。"); + } + }); + } + } + } + + private void loadSimpleFamilyInfo(String familyId) { + FamilyModel.Instance().loadFamilySimpleInfo( + familyId + ) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + mCompositeDisposable.add(d); + } + + @Override + public void onSuccess(FamilyInfo familyInfo) { + tvFamilyName.setText(familyInfo.getFamilyName()); + } + + @Override + public void onError(Throwable e) { +// Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(e.getMessage()); + } + }); + } + + private String avatarBg; + + private void updateNobleView() { + // 防止访问数据库和网络同时刷新出现图标跳动 + NobleInfo nobleInfo = userInfo.getNobleInfo(); + HeadWearInfo userHeadwear = userInfo.getUserHeadwear(); + boolean havaHead = false; + // 设置普通人 + if (userHeadwear != null && !TextUtils.isEmpty(userHeadwear.getPic())) { + havaHead = true; + NobleUtil.loadHeadWear(userHeadwear.getPic(), ivAvatarHeadWear); + } + + if (nobleInfo == null || TextUtils.isEmpty(nobleInfo.getCardBg())) { + //如果没贵族信息,就加载头像作为背景 + if (avatarBg == null || !avatarBg.equals(userInfo.getAvatar())) { + avatarBg = userInfo.getAvatar(); + ImageLoadUtils.loadImageWithBlurTransformation( + context, userInfo.getAvatar(), ivAvatarBg); + } + return; + } + // 卡片背景 + if (!TextUtils.isEmpty(nobleInfo.getCardBg()) && !topBg.equals(nobleInfo.getCardBg())) { + topBg = nobleInfo.getCardBg(); + NobleUtil.loadResource(nobleInfo.getCardBg(), ivAvatarBg, R.drawable.bg_user_info_dialog_top); + } + if (!TextUtils.isEmpty(nobleInfo.getHeadWear())) { + // 头饰 + if (!havaHead) { + NobleUtil.loadResource(nobleInfo.getHeadWear(), ivAvatarHeadWear); + } + } + if (!TextUtils.isEmpty(nobleInfo.getBadge())) { + // 勋章 + ivBadge.setVisibility(View.VISIBLE); + NobleUtil.loadResource(nobleInfo.getBadge(), ivBadge); + } + } + + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (subscribe != null) { + subscribe.dispose(); + subscribe = null; + } + if (mCompositeDisposable != null) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + } + + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.close_image: + dismiss(); + break; + case R.id.tv_report: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_report_click, "资料卡片-举报"); + + UIHelper.showReportPage(context, uid, XChatConstants.REPORT_TYPE_USERCARD); + dismiss(); + break; + case R.id.fl_avatar_layout: + case R.id.user_info_page_btn: + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_homepage_click,"资料卡片-主页"); + UserInfoActivity.Companion.start(context, uid); + dismiss(); + break; + default: + } + } + + /** + * 关注or取消 + */ + private void toAttent() { + if (userInfo == null) return; + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_card_follow_click, "资料卡片-关注TA"); + + //资料卡片不允许取消关注 + if (isAttention) { + return; + } + PraiseModel.get().praise(userInfo.getUid(), !isAttention) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + SingleToastUtil.showToast(error); + } + + @Override + public void onSuccess(String s) { + if (!isAttention) { + onFollow(true); + } else { + onUnFollow(true); + } + } + }); + } + + @SuppressLint("CheckResult") + private void onFollow(boolean success) { + if (success) { + isAttention = true; + updateAttentView(); + SingleToastUtil.showToast( + BasicConfig.INSTANCE.getAppContext().getResources().getString(R.string.fan_success)); + // 更新粉丝数量 + UserModel.get().getUserInfo(uid).subscribe(); + } + } + + private void onUnFollow(boolean success) { + if (success) { + isAttention = false; + updateAttentView(); + UserModel.get().getUserInfo(uid).subscribe(); + } + } + + /** + * 不去判断用户在不在房间 + * 麦位操作相关的一些操作,比如上下麦 + */ + public List getMicRelativeButtons(String account) { + List buttonItems = new ArrayList<>(); + final RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) return buttonItems; + //根据账号查询在哪个坑位 + int micPosition = AvRoomDataManager.get().getMicPosition(account); + // 判断在不在麦上 + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(micPosition); + RoomMicInfo roomMicInfo = null; + if (roomQueueInfo == null) { + + } else { + roomMicInfo = roomQueueInfo.mRoomMicInfo; + } + + String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + boolean isMySelf = Objects.equals(currentUid, account); + boolean isTargetRoomAdmin = AvRoomDataManager.get().isRoomAdmin(account); + boolean isTargetRoomOwner = AvRoomDataManager.get().isRoomOwner(account); + //目标用户是否是管理,(房主或者管理员) + boolean isTargetManager = isTargetRoomOwner || isTargetRoomAdmin; + boolean isTargetOnMic = AvRoomDataManager.get().isOnMic(account); + //超管逻辑 + if (SuperAdminUtil.isSuperAdmin()) { + if (isTargetOnMic) { + if (isMySelf) { + buttonItems.add(createDownMicItem()); + } else { + //如果是cp房,不能抱房主下麦 + if (AvRoomDataManager.get().isCpRoom()) { + if (!isTargetRoomOwner) { + buttonItems.add(createKickMicItem()); + } + } else { + buttonItems.add(createKickMicItem()); + } + + } + } + //锁麦 + if (roomMicInfo != null) { + if (!roomMicInfo.isMicMute()) { + buttonItems.add(createBanMicItem(micPosition)); + } + if (!roomMicInfo.isMicLock()) { + buttonItems.add(createLockMicItem(micPosition)); + } + } + return buttonItems; + } + + if (AvRoomDataManager.get().isRoomOwner()) { + //房主操作 + if (isMySelf) { + //开闭麦麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicMute()) { + buttonItems.add(createOpenMicItem(micPosition)); + } else { + buttonItems.add(createBanMicItem(micPosition)); + } + } + } + if (isTargetOnMic) { + if (!AvRoomDataManager.get().isCpRoom()) { + buttonItems.add(createDownMicItem()); + } + } else { + //支持自己抱自己上麦, 离开模式下不可上麦 + if (!AvRoomDataManager.get().isLeaveMode()) { + handleInviteMicItem(buttonItems); + } + } + //解锁麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicLock()) { + buttonItems.add(createUnLockMicItem(micPosition)); + } else { + buttonItems.add(createLockMicItem(micPosition)); + } + } + } + } else { + //开闭麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicMute()) { + buttonItems.add(createOpenMicItem(micPosition)); + } else { + buttonItems.add(createBanMicItem(micPosition)); + } + } + } + if (isTargetOnMic) { + buttonItems.add(createKickMicItem()); + } else { + handleInviteMicItem(buttonItems); + } + //解锁麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicLock()) { + buttonItems.add(createUnLockMicItem(micPosition)); + } else { + buttonItems.add(createLockMicItem(micPosition)); + } + } + } + } + return buttonItems; + } else if (AvRoomDataManager.get().isRoomAdmin()) { + //管理员操作 + if (isMySelf) { + //开闭麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicMute()) { + buttonItems.add(createOpenMicItem(micPosition)); + } else { + buttonItems.add(createBanMicItem(micPosition)); + } + } + } + if (isTargetOnMic) { + buttonItems.add(createDownMicItem()); + } else { + handleInviteMicItem(buttonItems); + } + //解锁麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicLock()) { + buttonItems.add(createUnLockMicItem(micPosition)); + } else { + buttonItems.add(createLockMicItem(micPosition)); + } + } + } + } else { + //管理员操作不是自己的坑上用户 + //开闭麦 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicMute()) { + buttonItems.add(createOpenMicItem(micPosition)); + } else { + if (!isTargetManager) { + buttonItems.add(createBanMicItem(micPosition)); + } + } + } + } + //管理员能抱所有人上麦 + if (isTargetOnMic) { + //管理员能抱管理员和游客下麦 + if (!isTargetRoomOwner) { + buttonItems.add(createKickMicItem()); + } + } else { + if (AvRoomDataManager.get().isLeaveMode()) { + + if (!isTargetRoomOwner) { + handleInviteMicItem(buttonItems); + } + + } else { + handleInviteMicItem(buttonItems); + } + } + //解锁麦 管理员能操作所有坑位 @陈金林说的 + if (micPosition != AvRoomDataManager.POSITON_NOT_ON_MIC) { + if (roomMicInfo != null) { + if (roomMicInfo.isMicLock()) { + buttonItems.add(createUnLockMicItem(micPosition)); + } else { + buttonItems.add(createLockMicItem(micPosition)); + } + } + } + + } + return buttonItems; + } else { + //游客操作 + if (isMySelf && isTargetOnMic) { + buttonItems.add(createDownMicItem()); + } + return buttonItems; + } + } + + /** + * 如果是超管点开资料卡片,隐藏 + * 抱ta上麦 + */ + private void handleInviteMicItem(List buttonItems) { + if (!SuperAdminUtil.isSuperAdmin()) { + buttonItems.add(createInviteMicItem()); + } + } + + private TextView getTextView(String text) { + TextView textView = new TextView(getContext()); + textView.setText(text); + textView.setTextColor(getContext().getResources().getColor(R.color.color_333333)); + textView.setTextSize(14); + textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); + textView.setGravity(Gravity.CENTER); + return textView; + } + + private TextView createClearGiftValueItem() { + TextView textView = getTextView("清除礼物值"); + + textView.setOnClickListener(v -> { + GiftValueModel.get().clearSingleMicValue(uid).subscribe(new DontWarnObserver() { + @Override + public void accept(RoomGiftValue roomGiftValue, String error) { + super.accept(roomGiftValue, error); + if (roomGiftValue == null) { + return; + } + if (error != null) { + SingleToastUtil.showToast(error); + return; + } + SingleToastUtil.showToast("清除成功"); + GiftValueMrg.get().updateRoomGiftValue(roomGiftValue, true); + //通知房间其他用户更新 + GiftValueMrg.get().sendRoomGiftValueMsg(roomGiftValue); + + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_DATA_CARD_CLEAN_GIFTVALUE, + "资料卡片-清除礼物值"); + } + }); + dismiss(); + }); + return textView; + } + + private TextView createDownMicItem() { + TextView textView = getTextView("下麦旁听"); + textView.setOnClickListener(v -> { + showDownMicDialog(); + dismiss(); + }); + return textView; + } + + /** + * 下麦前需要判断是否是ktv模式或者龙珠 + */ + private void showDownMicDialog() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) { + return; + } + + if (AvRoomDataManager.get().mCurrentRoomInfo.isOpenKTV()) { + new DialogManager(context).showOkCancelDialog("KTV模式下下麦会移除您已点的所有歌曲,确定进行此操作?", false, + () -> + { + handleDownMicro(); + KtvMusicManager.INSTANCE.deleteUserAllChooseMusic() + .subscribe(s -> { + }); + } + ); + } else if (AvRoomDataManager.get().haveStartDragon) { + new DialogManager(context).showOkCancelDialog("你正在交友匹配中,此操作代表你放弃本局匹配展示,确定进行此操作?", false, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + } + + @Override + public void onOk() { + DragonBallModel.get() + .clearDragonBar() + .doOnSuccess(s -> { + AvRoomDataManager.get().haveStartDragon = false; + cancelDragon(); + handleDownMicro(); + }) + .subscribe(); + } + }); + } else { + handleDownMicro(); + } + } + + private void handleDownMicro() { + if (AvRoomDataManager.get().isShowGiftValue() + && GiftValueDialogUiHelper.get().isNeedConfirmDialog(GiftValueDialogUiHelper.TYPE_DOWN_MIC)) { + GiftValueDialogUiHelper.get().showGiftValueDialog(context, null, GiftValueDialogUiHelper.TYPE_DOWN_MIC, + this::downMicCode); + } else { + downMicCode(); + } + } + + /** + * 下麦的代码 + */ + private void downMicCode() { + long currentUid = AuthModel.get().getCurrentUid(); + int micPos = AvRoomDataManager.get().getMicPosition(currentUid); + IMNetEaseManager.get().downMicroPhoneBySdk( + micPos, null); + } + + + public void cancelDragon() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + // 普通表情 + final ChatRoomMessage message = getChatRoomMessage(roomInfo, AvRoomDataManager.get().dragons, CUSTOM_MSG_DRAGON_BAR_CANCEL); + IMNetEaseManager.get().sendChatRoomMessage(message, false) + .subscribe((chatRoomMessage, throwable) -> { + IMNetEaseManager.get().getChatRoomEventObservable(). + onNext(new RoomEvent().setEvent(DRAGON_BAR_CANCEL) + .setChatRoomMessage(chatRoomMessage)); + IMNetEaseManager.get().addMessages(chatRoomMessage); + + }); + } + + private ChatRoomMessage getChatRoomMessage(RoomInfo roomInfo, List integers, int second) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + List faceReceiveInfos = new ArrayList<>(); + FaceReceiveInfo faceReceiveInfo = new FaceReceiveInfo(); + faceReceiveInfo.setNick(userInfo.getNick()); + faceReceiveInfo.setFaceId(Constants.DRAGON_BAR_ID); + faceReceiveInfo.setUid(userInfo.getUid()); + + faceReceiveInfo.setResultIndexes(integers); + faceReceiveInfos.add(faceReceiveInfo); + + // 发送云信信息给所有人 + FaceAttachment faceAttachment = + new FaceAttachment(CUSTOM_MSG_DRAGON_BAR, second); + faceAttachment.setUid(userInfo.getUid()); + faceAttachment.setFaceReceiveInfos(faceReceiveInfos); + + return ChatRoomMessageBuilder.createChatRoomCustomMessage( + // 聊天室id + roomInfo.getRoomId() + "", + // 自定义消息 + faceAttachment + ); + } + + private TextView createBanMicItem(int micPosition) { + TextView textView = getTextView("闭麦"); + textView.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_close_mic_click, "资料卡片-闭麦"); + + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + mSuperAdminModel.roomOperate(SuperAdminModel.CLOSE_MIC).subscribe(); + homePartyModel.closeMicroPhone(micPosition, roomInfo.getUid()).subscribe(); + dismiss(); + + }); + return textView; + } + + private TextView createOpenMicItem(int micPosition) { + TextView textView = getTextView("开麦"); + textView.setOnClickListener(v -> { + + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + homePartyModel.openMicroPhone(micPosition, roomInfo.getUid()).subscribe(); + dismiss(); + + }); + return textView; + } + + private TextView createLockMicItem(int micPosition) { + TextView textView = getTextView("锁麦"); + textView.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_lock_mic_click, "资料卡片-锁麦"); + + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (AvRoomDataManager.get().isQueuingMicro()) { +// Toast.makeText(getContext(), "排麦模式不可以锁麦哦!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("排麦模式不可以锁麦哦!"); + return; + } + mSuperAdminModel.roomOperate(SuperAdminModel.LOCK_MIC).subscribe(); + + homePartyModel.lockMicroPhone(micPosition, roomInfo.getUid() + "", + AuthModel.get().getTicket()).subscribe(); + dismiss(); + }); + return textView; + } + + private TextView createUnLockMicItem(int micPosition) { + TextView textView = getTextView("解锁"); + textView.setOnClickListener(v -> { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (AvRoomDataManager.get().isQueuingMicro()) { +// Toast.makeText(getContext(), "排麦模式不可以解锁哦!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("排麦模式不可以解锁哦!"); + return; + } + if (AvRoomDataManager.get().isOpenPKMode()) { +// Toast.makeText(getContext(), "PK模式不可以解锁哦!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("PK模式不可以解锁哦!"); + return; + } + homePartyModel.unLockMicroPhone(micPosition, roomInfo.getUid() + "", + AuthModel.get().getTicket()).subscribe(); + dismiss(); + }); + return textView; + } + + private TextView createInviteMicItem() { + TextView textView = getTextView("抱Ta上麦"); + textView.setOnClickListener(v -> { + if (AvRoomDataManager.get().getChatRoomMember(String.valueOf(uid)) == null) { + SingleToastUtil.showToast(context.getString(R.string.tips_member_not_in_room)); + dismiss(); + return; + } + setMicViewVisiable(true); + RecyclerView recyclerView = findViewById(R.id.recycler_view_mic); + + UpMicAdapter adapter = new UpMicAdapter(context, + position -> { + if (AvRoomDataManager.get().isLeaveMode() && uid == AvRoomDataManager.get().getRoomUid()) { + SingleToastUtil.showToast(context.getString(R.string.tips_close_leave_mode_first)); + dismiss(); + return; + } + if (isMySelf) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + //自己抱自己上麦 + AvRoomDataManager.get().haveStartDragon = false; + homePartyModel.upMicroPhone( + position - 1, + String.valueOf(uid), + String.valueOf(roomInfo.getRoomId()), + true, + new CallBack() { + @Override + public void onSuccess(String data) { + GiftValueMrg.get().requestUpMic(position - 1, String.valueOf(uid)); + } + + @Override + public void onFail(int code, String error) { + + } + } + ); + dismiss(); + return; + } + + String nick = null; + if (userInfo != null) { + nick = userInfo.getNick(); + + if (userInfo.getDefUser() == UserInfo.USER_TYPE_ROBOT) { + SingleToastUtil.showToast(context.getString(R.string.unable_to_up_mic_by_level)); + return; + } + } + + BaseInfo baseInfo = new BaseInfo(uid, nick); + IMNetEaseManager.get().inviteMicroPhoneBySdk(baseInfo, position - 1).subscribe(); + dismiss(); + }); + recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 4)); + recyclerView.setAdapter(adapter); + + }); + return textView; + } + + private TextView createKickMicItem() { + TextView textView = getTextView("抱Ta下麦"); + textView.setOnClickListener(v -> { + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.data_dard_takeOut_mic_click, "资料卡片-抱他下麦"); + + if (SuperAdminUtil.isSuperAdmin()) { + mSuperAdminModel.roomOperate(SuperAdminModel.TAKE_OUT_MIC, uid).subscribe(); + kickDownMicCode(); + return; + } + + if (AvRoomDataManager.get().isOnMic(uid)) { + //皇帝不能T + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByAccount(String.valueOf(uid)); + if (roomQueueInfo != null) { + String level = (String) NobleUtil.getResource(NobleResourceType.KEY_LEVEL, roomQueueInfo.mChatRoomMember); + String name = NobleUtil.getNobleName(level); + if (!NobleUtil.canKickMicroOrNot(level)) { + // 如果不能被踢下麦,则直接返回 +// Toast.makeText(BasicConfig.INSTANCE.getAppContext(), "不能踢" + name + "陛下哦", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("不能踢" + name + "陛下哦"); + return; + } + } + //ktv模式下麦 + if (AvRoomDataManager.get().isOpenKTV()) { + new DialogManager(context).showOkCancelWithTitleDialog("KTV模式下抱人下麦会删除ta演唱的歌,是否继续?", + (DialogManager.LambdaOkDialogListener) () -> { + int micPosition = AvRoomDataManager.get().getMicPosition(uid); + IMNetEaseManager.get().downMicroPhoneBySdk(micPosition, null); + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null) { + UserModel.get().getUserInfo(uid).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + String nick = userInfo != null ? RegexUtil.getPrintableString(userInfo.getNick()) : ""; + IMNetEaseManager.get().kickMicroPhoneBySdk(uid, nick, + roomInfo.getRoomId()).subscribe(chatRoomMessage -> + KickModel.get().onSendRoomMessageSuccess(chatRoomMessage) + , Throwable::printStackTrace); + } + }); + } + dismiss(); + }); + return; + } + if (GiftValueDialogUiHelper.get().isNeedKickDownMicDialog()) { + dismiss(); + GiftValueDialogUiHelper.get().showGiftValueDialog(context, null, + GiftValueDialogUiHelper.TYPE_KICK_DOWN_MIC, + this::kickDownMicCode); + return; + } + kickDownMicCode(); + + } + }); + return textView; + } + + @SuppressLint("CheckResult") + private void kickDownMicCode() { + int micPosition = AvRoomDataManager.get().getMicPosition(uid); + IMNetEaseManager.get().downMicroPhoneBySdk(micPosition, null); + //noinspection ResultOfMethodCallIgnored + UserModel.get().getUserInfo(uid).subscribe(new Consumer() { + @Override + public void accept(UserInfo userInfo) throws Exception { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo != null && userInfo != null) { + Single single; + if (SuperAdminUtil.isSuperAdmin()) { + single = IMNetEaseManager.get().kickMicroBySdkBySAdmin( + uid, userInfo.getNick(), roomInfo.getRoomId()); + } else { + single = IMNetEaseManager.get().kickMicroPhoneBySdk(uid, userInfo.getNick(), + roomInfo.getRoomId()); + } + single.subscribe( + chatRoomMessage -> { + KickModel.get().onSendRoomMessageSuccess(chatRoomMessage); + dismiss(); + }, + Throwable::printStackTrace); + } + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoView.java new file mode 100644 index 000000000..931adc6fe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/UserInfoView.java @@ -0,0 +1,74 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.erban.utils.RegexUtil; +import com.yizhuan.xchat_android_core.level.UserLevelVo; +import com.yizhuan.xchat_android_core.user.bean.SimpleUserInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import butterknife.BindView; +import butterknife.ButterKnife; +import lombok.Data; + +/** + * 用户信息展示 一个通用的展示,用户昵称,性别,经验等级,魅力等级 + * Created by lvzebiao on 2019/1/3. + */ + +public class UserInfoView extends LinearLayout { + + @BindView(R.id.tv_nick) + TextView tvNick; + @BindView(R.id.iv_gender) + AppCompatImageView ivGender; + @BindView(R.id.iv_user_level) + AppCompatImageView ivUserLevel; + @BindView(R.id.iv_charm_level) + AppCompatImageView ivCharmLevel; + + public UserInfoView(Context context) { + this(context, null); + } + + public UserInfoView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public UserInfoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.CENTER_VERTICAL); + inflate(getContext(), R.layout.view_user_info, this); + ButterKnife.bind(this); + } + + public void setData(SimpleUserInfo info) { + if (info == null) { + return; + } + tvNick.setText(RegexUtil.getPrintableString(info.getNick())); + ivGender.setImageResource(info.getGender() == 1 ? R.drawable.ic_male : R.drawable.ic_female); + ivUserLevel.setVisibility(View.GONE); + if (info.getUserLevelVo() != null && !TextUtils.isEmpty(info.getUserLevelVo().getExperUrl())) { + ivUserLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(getContext(), info.getUserLevelVo().getExperUrl(), ivUserLevel); + } + ivCharmLevel.setVisibility(View.GONE); + if (info.getUserLevelVo() != null && !TextUtils.isEmpty(info.getUserLevelVo().getCharmUrl())) { + ivCharmLevel.setVisibility(View.VISIBLE); + ImageLoadUtils.loadImage(getContext(), info.getUserLevelVo().getCharmUrl(), ivCharmLevel); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/UserMagicIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/UserMagicIndicator.java new file mode 100644 index 000000000..d86a98205 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/UserMagicIndicator.java @@ -0,0 +1,79 @@ +package com.yizhuan.erban.ui.widget; + +import android.content.Context; +import android.support.v4.content.ContextCompat; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.decoration.view.widgets.BadgeScaleTransitionPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; +import com.yizhuan.xchat_android_core.home.bean.TabInfo; + +import java.util.List; + +public class UserMagicIndicator extends CommonNavigatorAdapter { + + private Context mContext; + private List mTitleList; + private int mBottomMargin; + + public UserMagicIndicator(Context context, List titleList, int bottomMargin) { + mContext = context; + mTitleList = titleList; + mBottomMargin = bottomMargin; + } + + @Override + public int getCount() { + return mTitleList == null ? 0 : mTitleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, final int i) { + BadgeScaleTransitionPagerTitleView scaleTransitionPagerTitleView = new BadgeScaleTransitionPagerTitleView(context); + scaleTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(mContext, R.color.color_999999)); + scaleTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(mContext, R.color.color_333333)); + scaleTransitionPagerTitleView.setMinScale(1); + scaleTransitionPagerTitleView.setTextSize(16); + scaleTransitionPagerTitleView.setText(mTitleList.get(i).getName()); + if (mTitleList.get(i).getName().equals("座驾")) { + scaleTransitionPagerTitleView.findViewById(R.id.car_badge).setId(R.id.car_badge_garage); + } + scaleTransitionPagerTitleView.setOnClickListener(view -> { + if (mOnItemSelectListener != null) { + mOnItemSelectListener.onItemSelect(i); + } + }); + return scaleTransitionPagerTitleView; + } + + + @Override + public IPagerIndicator getIndicator(Context context) { + LinePagerIndicator indicator = new LinePagerIndicator(context); + indicator.setMode(LinePagerIndicator.MODE_EXACTLY); + indicator.setLineHeight(UIUtil.dip2px(mContext, 4)); + indicator.setRoundRadius(UIUtil.dip2px(mContext, 22)); + indicator.setLineWidth(UIUtil.dip2px(mContext, 7)); + indicator.setColors(context.getResources().getColor(R.color.color_333333)); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + lp.bottomMargin = mBottomMargin; + indicator.setLayoutParams(lp); + return indicator; + } + + private OnItemSelectListener mOnItemSelectListener; + + public void setOnItemSelectListener(OnItemSelectListener onItemSelectListener) { + mOnItemSelectListener = onItemSelectListener; + } + + public interface OnItemSelectListener { + void onItemSelect(int position); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/XRecyclerView/ScaleTransitionPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/XRecyclerView/ScaleTransitionPagerTitleView.java new file mode 100644 index 000000000..46f07de5c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/XRecyclerView/ScaleTransitionPagerTitleView.java @@ -0,0 +1,95 @@ +package com.yizhuan.erban.ui.widget.XRecyclerView; + +import android.content.Context; +import android.text.TextPaint; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView; + + +/** + * 带颜色渐变和缩放的指示器标题 + * 博客: http://hackware.lucode.net + * + * @author hackware + * @date 2016/6/26 + */ +public class ScaleTransitionPagerTitleView extends ColorTransitionPagerTitleView { + private float mMinScale = 0.75f; + /** + * 选中是否加粗 + */ + private boolean selectedBold; + + /** 往y方向平移,设置每个tab文字底部对齐, 0.0不平移 */ + private float mTranslationY = 0.0f; + + private boolean isAlwaysBold; + + public ScaleTransitionPagerTitleView(Context context, boolean selectedBold, float translationY) { + this(context, selectedBold); + mTranslationY = translationY; + } + + public ScaleTransitionPagerTitleView(Context context, boolean selectedBold) { + super(context); + this.selectedBold = selectedBold; + } + + public ScaleTransitionPagerTitleView(Context context) { + this(context, true); + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + super.onEnter(index, totalCount, enterPercent, leftToRight); + // 实现颜色渐变 + setScaleX(mMinScale + (1.0f - mMinScale) * enterPercent); + setScaleY(mMinScale + (1.0f - mMinScale) * enterPercent); + setTranslationY(1.0f + (1- enterPercent) * mTranslationY); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + super.onLeave(index, totalCount, leavePercent, leftToRight); + // 实现颜色渐变 + setScaleX(1.0f + (mMinScale - 1.0f) * leavePercent); + setScaleY(1.0f + (mMinScale - 1.0f) * leavePercent); + setTranslationY(1.0f + mTranslationY * leavePercent); + } + + @Override + public void onSelected(int index, int totalCount) { + super.onSelected(index, totalCount); + if (!isAlwaysBold) { + TextPaint paint = getPaint(); + paint.setFakeBoldText(selectedBold); + invalidate(); + } + } + + @Override + public void onDeselected(int index, int totalCount) { + super.onDeselected(index, totalCount); + if (!isAlwaysBold) { + TextPaint paint = getPaint(); + paint.setFakeBoldText(false); + invalidate(); + } + } + + public float getMinScale() { + return mMinScale; + } + + public void setMinScale(float minScale) { + mMinScale = minScale; + } + + public void setAlwaysBold() { + isAlwaysBold = true; + TextPaint paint = getPaint(); + paint.setFakeBoldText(true); + invalidate(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextView.java new file mode 100644 index 000000000..0a5b85248 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextView.java @@ -0,0 +1,73 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.TextView; + + +/** + * Created by dupengtao on 15/7/25. + *

+ * + * + * + * + * + * + * + * + * + * + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + */ +public class LeBubbleTextView extends LeBubbleView implements Runnable { + + private TextView tvContent; + + public LeBubbleTextView(Context context) { + super(context); + } + + public LeBubbleTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LeBubbleTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initChildView(float radius, int backgroundColor, int textColor, float textSize, String content) { + super.initChildView(radius, backgroundColor, textColor, textSize, content); + tvContent = new TextView(mContext); + tvContent.setId(View.generateViewId()); + tvContent.setTextColor(textColor); + tvContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + tvContent.setText(content); + int px22 = dip2px(21); + int px16 = dip2px(15); + tvContent.setPaddingRelative(px22, px16, px22, px16); + conRl.addView(tvContent); + } + + public TextView getContentTextView(){ + return tvContent; + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViewHelper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViewHelper.java new file mode 100644 index 000000000..645dd46fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViewHelper.java @@ -0,0 +1,123 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; + + +/** + * Created by dupengtao on 15/10/9. + */ +public class LeBubbleTextViewHelper { + + private LeBubbleView mBubbleView; + private PopupWindow mBubblePopupWindow; + private View mAnchor; + private int mBubbleViewWidth; + private int mBubbleViewHeight; + + public LeBubbleTextViewHelper() { + } + + public LeBubbleTextViewHelper(LeBubbleView bubbleView) { + mBubbleView = bubbleView; + } + + /** + * 初始化 + * @param anchor 目标的view + * @param bubbleViewLayoutRes bubbleTextView资源文件 + */ + public void init(final View anchor, final int bubbleViewLayoutRes) { + + mBubbleView = (LeBubbleView) LayoutInflater.from(anchor.getContext()).inflate( + bubbleViewLayoutRes, null); + mAnchor = anchor; + mBubblePopupWindow = new PopupWindow(mBubbleView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); + mBubblePopupWindow.setFocusable(false); + mBubblePopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + mBubbleView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + mBubbleViewWidth = mBubbleView.getMeasuredWidth(); + mBubbleViewHeight = mBubbleView.getMeasuredHeight(); + } + + /** + * 显示 + */ + public void show() { + show(0, 0); + } + + /** + * 显示 + * @param xCustomOffset x轴偏移量 + * @param yCustomOffset y轴偏移量 + */ + public void show(int xCustomOffset, int yCustomOffset) { + + int[] location = new int[2]; + mAnchor.getLocationInWindow(location); + LeBubbleTextView.ArrowDirection arrowDirection = mBubbleView.getArrowDirection(); + int xOffset = 0, yOffset = 0; + int anchorWidth = mAnchor.getWidth(); + int anchorHeight = mAnchor.getHeight(); + switch (arrowDirection) { + case LEFT: { + xOffset = anchorWidth; + int arrowOffset = (mBubbleViewHeight / 2) - (int) (mBubbleViewHeight * mBubbleView.getRelative()); + yOffset = -(mBubbleViewHeight - anchorHeight) / 2 + arrowOffset; + } + break; + case TOP: { + yOffset = anchorHeight; + int arrowOffset = (mBubbleViewWidth / 2) - (int) (mBubbleViewWidth * mBubbleView.getRelative()); + xOffset = -(mBubbleViewWidth - anchorWidth) / 2 + arrowOffset; + } + break; + case BOTTOM: { + yOffset = -mBubbleViewHeight; + int arrowOffset = (mBubbleViewWidth / 2) - (int) (mBubbleViewWidth * mBubbleView.getRelative()); + xOffset = -(mBubbleViewWidth - anchorWidth) / 2 + arrowOffset; + } + break; + default: { + xOffset = -mBubbleViewWidth - 10; + int arrowOffset = (mBubbleViewHeight / 2) - (int) (mBubbleViewHeight * mBubbleView.getRelative()); + yOffset = -(mBubbleViewHeight - anchorHeight) / 2 + arrowOffset; + } + } + mBubblePopupWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, location[0] + xOffset + xCustomOffset, location[1] + yOffset + yCustomOffset); + } + + public PopupWindow getBubblePopupWindow() { + return mBubblePopupWindow; + } + + /** + * 消失 + */ + public void dismissBubblePopupWindow() { + mBubblePopupWindow.dismiss(); + } + + /** + * @see LeBubbleTextViewHelper#getBubbleView() + * @return + */ + @Deprecated + public LeBubbleTextView getBubbleTextView() { + if(mBubbleView instanceof LeBubbleTextView) { + return (LeBubbleTextView)mBubbleView; + }else { + return null; + } + } + + public LeBubbleView getBubbleView() { + return mBubbleView; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViews.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViews.java new file mode 100644 index 000000000..dde419e86 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTextViews.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Created by dupengtao on 15/7/25. + *

+ * + * + * + * + * + * + * + * + * + * + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + */ +public class LeBubbleTextViews extends LeBubbleView implements Runnable { + + private TextView tvContent; + private ArrayList views; + + public LeBubbleTextViews(Context context) { + super(context); + } + + public LeBubbleTextViews(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LeBubbleTextViews(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initChildView(float radius, int backgroundColor, int textColor, float textSize, String... contents) { + super.initChildView(radius, backgroundColor, textColor, textSize, contents); + views = new ArrayList<>(contents.length); + int curId = 0; + View curView = null; + for(String content : contents){ + tvContent = new TextView(mContext); + tvContent.setId(curId); + tvContent.setTextColor(textColor); + tvContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + tvContent.setText(content); + int px22 = dip2px(21); + int px16 = dip2px(15); + tvContent.setPaddingRelative(px22, px16, px22, px16); + if(curId > 0){ + + RelativeLayout.LayoutParams contentTvParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + contentTvParams.setMargins(dip2px(22), dip2px(1), dip2px(22), dip2px(15)); + //contentTvParams.addRule(RelativeLayout.ALIGN_TOP,titleTextView.getId()); + contentTvParams.addRule(RelativeLayout.BELOW, curView.getId()); + tvContent.setLayoutParams(contentTvParams); + +// RelativeLayout.LayoutParams curParams = (RelativeLayout.LayoutParams)curView.getLayoutParams(); +// LayoutParams tvParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); +// curParams.addRule(RelativeLayout.BELOW, tvContent.getId()); + + conRl.addView(tvContent,contentTvParams); + } + views.add(tvContent); + curId = View.generateViewId(); + curView = tvContent; + } + } + + public List getContentTextViews() { + return views; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTitleTextView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTitleTextView.java new file mode 100644 index 000000000..044accd25 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleTitleTextView.java @@ -0,0 +1,173 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.TouchDelegate; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; + + +/** + * Created by dupengtao on 15/7/25. + *

+ * + * + * + * + * + * + * + * + * + * + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + */ +public class LeBubbleTitleTextView extends LeBubbleView implements Runnable { + + private ImageView cancelImage; + private TextView titleTextView; + private TextView contentTextView; + private String titleText; + + + public LeBubbleTitleTextView(Context context) { + super(context); + } + + public LeBubbleTitleTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public LeBubbleTitleTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onInitialize(AttributeSet attrs, int defStyleAttr, TypedArray a) { + titleText = a.getString(R.styleable.LeBubbleTextView_bubbleTitleText); + } + + private void initCancelImageView() { + cancelImage = new ImageView(mContext); + } + + private void initContentTextView(int textColor, String content) { + contentTextView = new TextView(mContext); + contentTextView.setId(View.generateViewId()); + LayoutParams contentTvParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + contentTvParams.setMargins(dip2px(22), dip2px(1), dip2px(22), dip2px(15)); + //contentTvParams.addRule(RelativeLayout.ALIGN_TOP,titleTextView.getId()); + contentTvParams.addRule(RelativeLayout.BELOW, titleTextView.getId()); + contentTextView.setLayoutParams(contentTvParams); + //dark + contentTextView.setTextColor(textColor); + contentTextView.setTextSize(14); + + contentTextView.setText(content); + } + + private void initTitleTextView(int textColor) { + titleTextView = new TextView(mContext); + titleTextView.setId(View.generateViewId()); + LayoutParams titleTvParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + titleTvParams.setMargins(dip2px(22), dip2px(15), dip2px(22), 0); + titleTextView.setLayoutParams(titleTvParams); + titleTextView.setSingleLine(true); + //dark + if (curStyle == STYLE_DARK) { + titleTextView.setTextColor(Color.WHITE); + } else { + titleTextView.setTextColor(Color.BLACK); + } + titleTextView.setTextSize(17); + + titleTextView.setText(titleText); + + System.out.print(1); + } + + private void initCancelView(int conRlw) { + cancelImage.setId(View.generateViewId()); + LayoutParams cancelParams = new LayoutParams(dip2px(13), dip2px(13)); + //cancelParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + cancelParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + cancelParams.setMargins(conRlw - dip2px(22), dip2px(8), dip2px(8), 0); + cancelImage.setLayoutParams(cancelParams); + //cancelImage.setImageResource(R.drawable.le_bubble_cancel); + int cancel = R.drawable.le_bubble_cancel; + Bitmap source = BitmapFactory.decodeResource(this.getResources(), cancel); + int color; + if (curStyle == STYLE_DARK) { + color = Color.parseColor("#99FFFFFF"); + } else { + color = Color.parseColor("#99000000"); + } + TintedBitmapDrawable cancelBitmapDrawable = new TintedBitmapDrawable(mContext.getResources(), source, color); + cancelImage.setImageDrawable(cancelBitmapDrawable); + increaseClickArea(); + } + + private void increaseClickArea() { + Rect conRlRect = new Rect(); + conRl.getHitRect(conRlRect); + Rect rect = new Rect(conRlRect); + //cancelImage.getHitRect(rect); + //rect.top -= 300; // increase top hit area + rect.left = rect.right / 2; // increase left hit area + //rect.bottom += 300; // increase bottom hit area + //rect.right += 300; // increase right hit area + conRl.setTouchDelegate(new TouchDelegate(rect, cancelImage)); + } + + + @Override + protected void initChildView(float radius, int backgroundColor, int textColor, float textSize, String content) { + super.initChildView(radius, backgroundColor, textColor, textSize, content); + //cancel view + initCancelImageView(); + //title view + initTitleTextView(textColor); + conRl.addView(titleTextView); + //content view + initContentTextView(textColor, content); + conRl.addView(contentTextView); + } + + public void setCancelImageOnClickListener(OnClickListener l) { + cancelImage.setOnClickListener(l); + } + + @Override + protected void onPostCallBack(int conRlw, int conRlh) { + super.onPostCallBack(conRlw, conRlh); + //add cancel image view + initCancelView(conRlw); + conRl.addView(cancelImage); + } + + public View getCancelImage() { + return cancelImage; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleView.java new file mode 100644 index 000000000..e7f0deadd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeBubbleView.java @@ -0,0 +1,300 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.Matrix; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.R; + + +/** + * Created by dupengtao on 15/7/25. + *

+ * + * + * + * + * + * + * + * + * + * + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + */ +public class LeBubbleView extends RelativeLayout implements Runnable { + + public static final int STYLE_DARK = 1; + public static final int STYLE_LIGHT = 2; + public static final int STYLE_OTHER = 3; + + protected Context mContext; + protected ArrowDirection arrowDirection; + protected float relative; + protected RelativeLayout conRl; + protected ImageView arrowImage; + protected int pressBackgroundColor, backgroundColor; + protected TintedBitmapDrawable norDrawable, pressDrawable; + protected int mArrowOffset; + protected int curStyle; + + + public LeBubbleView(Context context) { + super(context); + initialize(context, null, 0); + } + + public LeBubbleView(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(context, attrs, 0); + } + + public LeBubbleView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + mContext = context; + //TODO custom attribute + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LeBubbleTextView, defStyleAttr, R.style.LeBubbleTextView_Dark); + float radius = a.getDimension(R.styleable.LeBubbleTextView_bubbleCornerRadius, 0); + backgroundColor = a.getColor(R.styleable.LeBubbleTextView_bubbleBackgroundColor, 0); + +// TypedArray typedArray = getResources().obtainTypedArray(R.array.feed_icons); +// String[] titleArr = getResources().getStringArray(R.array.feed_names); +// if( null != titleArr ){ +// int titleLength = titleArr.length; +// for( int index = 0; index < titleLength; index++ ){ +// int feedResId = typedArray.getResourceId( index, 0 ); +// //... +// } +// } + pressBackgroundColor = a.getColor(R.styleable.LeBubbleTextView_bubbleBackgroundPressColor, 0); + int textColor = a.getColor(R.styleable.LeBubbleTextView_bubbleTextColor, 0); + float textSize = a.getDimension(R.styleable.LeBubbleTextView_bubbleTextSize, 0); + String contentText = a.getString(R.styleable.LeBubbleTextView_bubbleText); + + + + int intDirection = a.getInt(R.styleable.LeBubbleTextView_bubbleArrowDirection, 3); + setCurDirection(intDirection); + + float relativePosition = a.getFraction(R.styleable.LeBubbleTextView_relativePosition, 1, 1, 0.3f); + + setRelativePosition(relativePosition); + setCurThemeStyle(textColor); + onInitialize(attrs, defStyleAttr, a); + a.recycle(); + + String[] contents = contentText.split(","); + initContent(radius, backgroundColor, textColor, textSize, contents); + + } + + protected void onInitialize(AttributeSet attrs, int defStyleAttr, TypedArray a) { + + } + + public void setCurThemeStyle(int textColor) { + + int darkColor = mContext.getResources().getColor(R.color.bubbleView_dark_text_color); + int lightColor = mContext.getResources().getColor(R.color.bubbleView_light_text_color); + if (textColor == darkColor) { + curStyle = STYLE_DARK; + } else if (textColor == lightColor) { + curStyle = STYLE_LIGHT; + } else { + curStyle = STYLE_OTHER; + } + } + + private void setRelativePosition(float relativePosition) { + if (relativePosition < 0.2f) { + relative = 0.2f; + } else if (relativePosition > 0.8f) { + relative = 0.8f; + } else { + relative = relativePosition; + } + } + + private void setCurDirection(int intDirection) { + switch (intDirection) { + case 1: { + arrowDirection = ArrowDirection.LEFT; + } + break; + case 2: { + arrowDirection = ArrowDirection.TOP; + } + break; + case 3: { + arrowDirection = ArrowDirection.RIGHT; + } + break; + case 4: { + arrowDirection = ArrowDirection.BOTTOM; + } + } + } + + + private void initContent(float radius, final int backgroundColor, int textColor, float textSize, String... contents) { + + + conRl = new RelativeLayout(mContext); + conRl.setId(View.generateViewId()); + LayoutParams conRlParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + //conRl.setLayoutParams(conRlParams); + LeRoundRectDrawable2 roundRectDrawable = new LeRoundRectDrawable2(backgroundColor, radius); + conRl.setBackground(roundRectDrawable); + + initChildView(radius, backgroundColor, textColor, textSize, contents); + arrowImage = new ImageView(mContext); + arrowImage.setId(View.generateViewId()); + LayoutParams arrowParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + + int r; + switch (arrowDirection) { + case LEFT: { + r = 180; + conRlParams.addRule(RelativeLayout.END_OF, arrowImage.getId()); + } + break; + case TOP: { + r = 270; + conRlParams.addRule(RelativeLayout.BELOW, arrowImage.getId()); + } + break; + case BOTTOM: { + r = 90; + arrowParams.addRule(RelativeLayout.BELOW, conRl.getId()); + } + break; + default: { + r = 0; + arrowParams.addRule(RelativeLayout.END_OF, conRl.getId()); + } + } + + //int arrowRes = backgroundColor == Color.parseColor("#B3000000")?R.drawable.le_bubble_arrow_light:R.drawable.le_bubble_arrow_light; + int arrowRes = R.drawable.le_bubble_arrow_light; + Bitmap source = BitmapFactory.decodeResource(this.getResources(), arrowRes); + + Bitmap rotateBitmap = rotateBitmap(source, r); + + norDrawable = new TintedBitmapDrawable(mContext.getResources(), rotateBitmap, backgroundColor); + pressDrawable = new TintedBitmapDrawable(mContext.getResources(), rotateBitmap, pressBackgroundColor); + + arrowImage.setImageDrawable(norDrawable); + this.addView(arrowImage, arrowParams); + this.addView(conRl, conRlParams); + + arrowImage.setImageTintList(ColorStateList.valueOf(backgroundColor)); + + setBackground(new LeStateColorDrawable(Color.TRANSPARENT) { + @Override + protected void onIsPressed(boolean isPressed) { + LeRoundRectDrawable2 conRlBackground = (LeRoundRectDrawable2) conRl.getBackground(); + if (isPressed) { + conRlBackground.getPaint().setColor(pressBackgroundColor); + //arrowImage.setImageTintList(ColorStateList.valueOf(pressBackgroundColor)); + arrowImage.setImageDrawable(pressDrawable); + } else { + conRlBackground.getPaint().setColor(backgroundColor); + //arrowImage.setImageTintList(ColorStateList.valueOf(backgroundColor)); + arrowImage.setImageDrawable(norDrawable); + } + conRl.invalidate(); + arrowImage.invalidate(); + } + }); + + conRl.post(this); + + this.setClickable(true); + + } + + protected void initChildView(float radius, int backgroundColor, int textColor, float textSize, String... content) { + + } + + protected void initChildView(float radius, int backgroundColor, int textColor, float textSize, String content) { + + } + + public Bitmap rotateBitmap(Bitmap source, float angle) { + Matrix matrix = new Matrix(); + matrix.postRotate(angle); + return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); + } + + protected int dip2px(float dpValue) { + final float scale = mContext.getResources() + .getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + @Override + public void run() { + int conRlw = conRl.getWidth(); + int conRlh = conRl.getHeight(); + LayoutParams params = (LayoutParams) arrowImage.getLayoutParams(); + switch (arrowDirection) { + case TOP: + case BOTTOM: + mArrowOffset = (int) ((conRlw * relative) - arrowImage.getWidth() / 2); + params.setMargins(mArrowOffset, 0, 0, 0); + break; + case LEFT: + default: + mArrowOffset = (int) ((conRlh * relative) - arrowImage.getHeight() / 2); + params.setMargins(0, mArrowOffset, 0, 0); + } + + onPostCallBack(conRlw, conRlh); + } + + protected void onPostCallBack(int conRlw, int conRlh) { + + } + + public ArrowDirection getArrowDirection() { + return arrowDirection; + } + + public int getArrowOffset() { + return mArrowOffset; + } + + public float getRelative() { + return relative; + } + + public enum ArrowDirection { + LEFT, TOP, RIGHT, BOTTOM + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeRoundRectDrawable2.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeRoundRectDrawable2.java new file mode 100644 index 000000000..e5161c400 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeRoundRectDrawable2.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * 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.yizhuan.erban.ui.widget.bubble; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + + +/** + * Very simple drawable that draws a rounded rectangle background with arbitrary corners and also + * reports proper outline for L. + *

+ * Simpler and uses less resources compared to GradientDrawable or ShapeDrawable. + */ +public class LeRoundRectDrawable2 extends Drawable { + private float mRadius; + private final Paint mPaint; + private final RectF mBoundsF; + private final Rect mBoundsI; + private float mPadding; + private boolean mInsetForPadding = false; + private boolean mInsetForRadius = true; + + public LeRoundRectDrawable2(int backgroundColor, float radius) { + mRadius = radius; + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); + mPaint.setColor(backgroundColor); + mBoundsF = new RectF(); + mBoundsI = new Rect(); + } + + void setPadding(float padding, boolean insetForPadding, boolean insetForRadius) { + if (padding == mPadding && mInsetForPadding == insetForPadding && + mInsetForRadius == insetForRadius) { + return; + } + mPadding = padding; + mInsetForPadding = insetForPadding; + mInsetForRadius = insetForRadius; + updateBounds(null); + invalidateSelf(); + } + + float getPadding() { + return mPadding; + } + + @Override + public void draw(Canvas canvas) { + canvas.drawRoundRect(mBoundsF, mRadius, mRadius, mPaint); + } + + private void updateBounds(Rect bounds) { + if (bounds == null) { + bounds = getBounds(); + } + mBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + mBoundsI.set(bounds); + //if (mInsetForPadding) { + //float vInset = LeRoundRectDrawable2WithShadow.calculateVerticalPadding(mPadding, mRadius, mInsetForRadius); + //float hInset = LeRoundRectDrawable2WithShadow.calculateHorizontalPadding(mPadding, mRadius, mInsetForRadius); + //mBoundsI.inset((int) Math.ceil(hInset), (int) Math.ceil(vInset)); + // to make sure they have same bounds. + //mBoundsF.set(mBoundsI); + //} + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + updateBounds(bounds); + } + + @Override + public void getOutline(Outline outline) { + outline.setRoundRect(mBoundsI, mRadius); + } + + void setRadius(float radius) { + if (radius == mRadius) { + return; + } + mRadius = radius; + updateBounds(null); + invalidateSelf(); + } + + @Override + public void setAlpha(int alpha) { + // not supported because older versions do not support + } + + @Override + public void setColorFilter(ColorFilter cf) { + // not supported because older versions do not support + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + public float getRadius() { + return mRadius; + } + + public void setColor(int color) { + mPaint.setColor(color); + invalidateSelf(); + } + + public Paint getPaint() { + return mPaint; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeStateColorDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeStateColorDrawable.java new file mode 100644 index 000000000..9b08c3c4b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/LeStateColorDrawable.java @@ -0,0 +1,49 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.graphics.drawable.ColorDrawable; + +/** + * Created by dupengtao on 15/8/12. + */ +public abstract class LeStateColorDrawable extends ColorDrawable { + + private boolean mPressed = false; + + public LeStateColorDrawable(int color) { + super(color); + } + + @Override + protected boolean onStateChange(int[] state) { + + boolean pressed = isPressed(state); + if (mPressed != pressed) { + mPressed = pressed; + onIsPressed(mPressed); + } + return true; + } + + protected abstract void onIsPressed(boolean isPressed); + + @Override + public boolean setState(int[] stateSet) { + return super.setState(stateSet); + } + + @Override + public boolean isStateful() { + return true; + } + + private boolean isPressed(int[] state) { + boolean pressed = false; + for (int i = 0, j = state != null ? state.length : 0; i < j; i++) { + if (state[i] == android.R.attr.state_pressed) { + pressed = true; + break; + } + } + return pressed; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/TintedBitmapDrawable.java b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/TintedBitmapDrawable.java new file mode 100644 index 000000000..6529b1a25 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/bubble/TintedBitmapDrawable.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.ui.widget.bubble; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LightingColorFilter; +import android.graphics.Paint; +import android.graphics.drawable.BitmapDrawable; + +/** + * Created by dupengtao on 15/8/24. + */ +public final class TintedBitmapDrawable extends BitmapDrawable { + private int tint; + private int alpha; + + public TintedBitmapDrawable(final Resources res, final Bitmap bitmap, final int tint) { + super(res, bitmap); + this.tint = tint; + this.alpha = Color.alpha(tint); + } + + public TintedBitmapDrawable(final Resources res, final int resId, final int tint) { + super(res, BitmapFactory.decodeResource(res, resId)); + this.tint = tint; + this.alpha = Color.alpha(tint); + } + + public void setTint(final int tint) { + this.tint = tint; + this.alpha = Color.alpha(tint); + } + + @Override + public void draw(final Canvas canvas) { + final Paint paint = getPaint(); + if (paint.getColorFilter() == null) { + paint.setColorFilter(new LightingColorFilter(tint, 0)); + paint.setAlpha(alpha); + } + super.draw(canvas); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftDialog.java new file mode 100644 index 000000000..4ac41c231 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftDialog.java @@ -0,0 +1,77 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.databinding.DialogGiftAllServiceBinding; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; + +/** + * Created by huangmeng1 on 2018/3/29. + */ + +public class AllServiceGiftDialog extends BaseDialog { + + public static final int ALL_SERVICE_GIFT_LEVEL_1 = 1; + public static final int ALL_SERVICE_GIFT_LEVEL_2 = 2; + public static final int ALL_SERVICE_GIFT_LEVEL_3 = 3; + + protected int giftLevel = 1; + protected AllServiceGiftProtocol.DataBean dataBean; + private DialogGiftAllServiceBinding binding; + + public AllServiceGiftDialog(Context context, AllServiceGiftProtocol.DataBean dataBean) { + this(context, 0); + this.dataBean = dataBean; + } + + public AllServiceGiftDialog(Context context, int theme, AllServiceGiftProtocol.DataBean dataBean) { + super(context, theme); + this.dataBean = dataBean; + } + + public AllServiceGiftDialog(Context context, int theme) { + super(context, theme); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View inflate = LayoutInflater.from(getContext()).inflate(R.layout.dialog_gift_all_service, null); + setContentView(inflate.getRootView()); + setCancelable(true); + setCanceledOnTouchOutside(true); + binding = DataBindingUtil.bind(inflate); + + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP; + windowParams.x = 0; + windowParams.y = SizeUtils.dp2px(getContext(), 62); + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + window.setWindowAnimations(R.style.anim_left); + } + if (dataBean != null) { + binding.tvRoomId.setOnClickListener(v -> AVRoomActivity.start(getContext(), dataBean.getRoomErbanNo())); + binding.setGiftBean(dataBean); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelOneDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelOneDialog.java new file mode 100644 index 000000000..d54fa441e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelOneDialog.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.databinding.DialogGiftAllServiceLevelOneBinding; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; + +/** + * Created by MadisonRong on 11/05/2018. + */ + +public class AllServiceGiftLevelOneDialog extends AllServiceGiftDialog { + + private DialogGiftAllServiceLevelOneBinding binding; + + public AllServiceGiftLevelOneDialog(Context context, AllServiceGiftProtocol.DataBean dataBean) { + super(context, R.style.FullScreenDialog, dataBean); + giftLevel = ALL_SERVICE_GIFT_LEVEL_1; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + requestWindowFeature(Window.FEATURE_NO_TITLE); + View inflate = LayoutInflater.from(getContext()).inflate(R.layout.dialog_gift_all_service_level_one, null); + setContentView(inflate.getRootView()); + setCancelable(true); + setCanceledOnTouchOutside(true); + binding = DataBindingUtil.bind(inflate); + + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + //MATCH_PARENT会挡住键盘, + // wrap_parent在小米8又会截掉一点,在华为测试关闭按钮点击不到 + //暂时找不到原因, + windowParams.height = getContext().getResources() + .getDimensionPixelOffset(R.dimen.all_service_one_dialog_height); + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP; + windowParams.x = 0; + windowParams.y = 0; + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + window.setWindowAnimations(R.style.anim_left); + } + if (dataBean != null) { + Observable.timer((long) dataBean.getNotifyStaySecond(), TimeUnit.SECONDS) + .subscribe(aLong -> { + dismiss(); + }); + binding.setGiftBean(dataBean); + } + binding.ivCloseDialogOne.setOnClickListener(v -> dismiss()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelThreeDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelThreeDialog.java new file mode 100644 index 000000000..8e3299d09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelThreeDialog.java @@ -0,0 +1,108 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.LinearInterpolator; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.databinding.DialogGiftAllServiceLevelThreeBinding; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; + +/** + * Created by MadisonRong on 11/05/2018. + */ + +public class AllServiceGiftLevelThreeDialog extends AllServiceGiftDialog { + + private DialogGiftAllServiceLevelThreeBinding binding; + private float screenWidth; + + public AllServiceGiftLevelThreeDialog(Context context, AllServiceGiftProtocol.DataBean dataBean) { + super(context, R.style.FullScreenDialog, dataBean); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + requestWindowFeature(Window.FEATURE_NO_TITLE); + View inflate = LayoutInflater.from(getContext()).inflate(R.layout.dialog_gift_all_service_level_three, null); + setContentView(inflate.getRootView()); + setCancelable(true); + setCanceledOnTouchOutside(true); + binding = DataBindingUtil.bind(inflate); + + Window window = getWindow(); + Point point = new Point(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = getContext().getResources() + .getDimensionPixelOffset(R.dimen.all_service_three_dialog_height); + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP; + windowParams.x = 0; + windowParams.y = 0; + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + window.setWindowAnimations(R.style.anim_fade); + window.getWindowManager().getDefaultDisplay().getSize(point); + screenWidth = point.x; + } + if (dataBean != null) { + binding.giftClose.setOnClickListener(v -> { + dismiss(); + }); + binding.tvRoomId.setOnClickListener(v -> { + if (dataBean.getRoomUid() == JavaUtil.str2long(InitialModel.get().getPublicChatHallUid())) { + PublicChatHallHomeActivity.openPublicChatHallPage(getContext()); + } else { + AVRoomActivity.start(getContext(), dataBean.getRoomUid()); + } + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.FULL_GIFT_WATCHING, "全服礼物-前往围观计数"); + }); + // 设置定时器 + Observable.timer((long) dataBean.getNotifyStaySecond(), TimeUnit.SECONDS) + .subscribe(aLong -> { + dismiss(); + }); + binding.setGiftBean(dataBean); + binding.tvRoomId.setVisibility(dataBean.getRoomUid() == 0 + || (AvRoomDataManager.get().mCurrentRoomInfo != null && dataBean.getRoomUid() == AvRoomDataManager.get().mCurrentRoomInfo.getUid()) + ? View.GONE : View.VISIBLE); + setOnShowListener(dialog -> { + if (dataBean.isSendMsg() && !Objects.equals(dataBean.getMsg(), "")) { + binding.giftMessage.setX(screenWidth); + binding.giftMessage.animate() + .translationXBy(-(screenWidth + binding.giftMessage.getWidth())) + .setDuration((long) dataBean.getNotifyStaySecond() * 1000) + .setInterpolator(new LinearInterpolator()) + .start(); + } else { + binding.giftMessage.setVisibility(View.GONE); + } + }); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelTwoDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelTwoDialog.java new file mode 100644 index 000000000..5e8950e6b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/AllServiceGiftLevelTwoDialog.java @@ -0,0 +1,107 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.LinearInterpolator; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.databinding.DialogGiftAllServiceLevelTwoBinding; +import com.yizhuan.erban.public_chat_hall.activity.PublicChatHallHomeActivity; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.noble.AllServiceGiftProtocol; +import com.yizhuan.xchat_android_core.statistic.StatisticManager; +import com.yizhuan.xchat_android_core.statistic.protocol.StatisticsProtocol; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; + +/** + * Created by MadisonRong on 11/05/2018. + */ + +public class AllServiceGiftLevelTwoDialog extends AllServiceGiftDialog { + + private DialogGiftAllServiceLevelTwoBinding binding; + private float screenWidth; + + public AllServiceGiftLevelTwoDialog(Context context, AllServiceGiftProtocol.DataBean dataBean) { + super(context, R.style.FullScreenDialog, dataBean); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + requestWindowFeature(Window.FEATURE_NO_TITLE); + View inflate = LayoutInflater.from(getContext()).inflate(R.layout.dialog_gift_all_service_level_two, null); + setContentView(inflate.getRootView()); + setCancelable(true); + setCanceledOnTouchOutside(true); + binding = DataBindingUtil.bind(inflate); + + Window window = getWindow(); + Point point = new Point(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = getContext().getResources() + .getDimensionPixelOffset(R.dimen.all_service_two_dialog_height); + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP; + windowParams.x = 0; + windowParams.y = 0; + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + window.setWindowAnimations(R.style.anim_left); + window.getWindowManager().getDefaultDisplay().getSize(point); + screenWidth = point.x; + } + if (dataBean != null) { + binding.tvRoomId.setOnClickListener(v -> { + if (dataBean.getRoomUid() == JavaUtil.str2long(InitialModel.get().getPublicChatHallUid())) { + PublicChatHallHomeActivity.openPublicChatHallPage(getContext()); + } else { + AVRoomActivity.start(getContext(), dataBean.getRoomUid()); + } + + StatisticManager.Instance().onEvent(StatisticsProtocol.Event.FULL_GIFT_WATCHING, "全服礼物-前往围观计数"); + }); + // 设置定时器 + Observable.timer((long) (dataBean.getNotifyStaySecond()), TimeUnit.SECONDS) + .subscribe(aLong -> dismiss()); + binding.setGiftBean(dataBean); + binding.tvRoomId.setVisibility(dataBean.getRoomUid() == 0 + || (AvRoomDataManager.get().mCurrentRoomInfo != null && dataBean.getRoomUid() == AvRoomDataManager.get().mCurrentRoomInfo.getUid()) + ? View.GONE : View.VISIBLE); + setOnShowListener(dialog -> { + if (dataBean.isSendMsg() && !Objects.equals(dataBean.getMsg(), "")) { + binding.tvGiftMessage.setX(screenWidth); + binding.tvGiftMessage.animate() + .translationXBy(-(screenWidth + binding.tvGiftMessage.getWidth())) + .setDuration((long) (dataBean.getNotifyStaySecond() * 1000)) + .setInterpolator(new LinearInterpolator()) + .start(); + } else { + binding.tvGiftMessage.setVisibility(View.GONE); + } + }); + } + + binding.ivCloseDialogTwo.setOnClickListener(v -> dismiss()); + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/BaseDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/BaseDialog.java new file mode 100644 index 000000000..b7c1568ed --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/BaseDialog.java @@ -0,0 +1,26 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.support.v7.app.AppCompatDialog; +import android.widget.Toast; + +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +/** + * Created by huangmeng1 on 2018/4/11. + */ + +public class BaseDialog extends AppCompatDialog { + public BaseDialog(Context context) { + super(context); + } + + public BaseDialog(Context context, int theme) { + super(context, theme); + } + + public void toast(String msg) { +// Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort(msg); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonLoadingDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonLoadingDialog.java new file mode 100644 index 000000000..df52fa50c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonLoadingDialog.java @@ -0,0 +1,50 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * @author jack + * @Description + * @Date 2019/1/22 + */ +public class CommonLoadingDialog extends BaseDialog { + + private String msg = "加载中..."; + + private TextView tvTip; + + public CommonLoadingDialog(Context context, String tip) { + super(context, R.style.dialog); + msg = tip; + init(); + } + + private void init() { + this.setCancelable(false); + this.setCanceledOnTouchOutside(false); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_progress_dialog); + + tvTip = (TextView) findViewById(R.id.tv_tip); + tvTip.setText(msg); + + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public CommonLoadingDialog showDialog() { + super.show(); + return this; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonTipDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonTipDialog.java new file mode 100644 index 000000000..23401826b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/CommonTipDialog.java @@ -0,0 +1,72 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.os.Bundle; +import android.view.Window; +import android.widget.TextView; + +import com.yizhuan.erban.R; + +/** + * @author jack + * @Description + * @Date 2019/1/21 + */ +public class CommonTipDialog extends BaseDialog { + private String tipMsg = ""; + + public CommonTipDialog(Context context) { + super(context, R.style.dialog); + init(); + } + + private void init() { + this.setCancelable(true); + this.setCanceledOnTouchOutside(true); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.layout_ok_cancel_dialog); + + TextView tip = findViewById(R.id.message); + tip.setText(tipMsg); + + TextView ok = findViewById(R.id.btn_ok); + ok.setText("确定"); + ok.setOnClickListener(v -> { + this.dismiss(); + if (l != null) { + l.onOk(); + } + }); + TextView cancel = findViewById(R.id.btn_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(v -> { + this.dismiss(); + if (l != null) { + l.onCancel(); + } + }); + } + + public void setTipMsg(String tipMsg) { + this.tipMsg = tipMsg; + } + + private OnActionListener l; + + public void setOnActionListener(OnActionListener l) { + this.l = l; + } + + public interface OnActionListener { + default void onOk() { + } + + default void onCancel() { + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/GiftManualQuantityDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/GiftManualQuantityDialog.java new file mode 100644 index 000000000..53d84837b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/GiftManualQuantityDialog.java @@ -0,0 +1,92 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.utils.KeyBoardUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +/** + * @author jack + * @Description + * @Date 2019/3/13 + */ +public class GiftManualQuantityDialog extends Dialog implements View.OnClickListener { + + private EditText etInput; + private TextView tvOk; + + private Context context; + + public GiftManualQuantityDialog(Context context) { + super(context, R.style.inputDialog); + this.context = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Window window = getWindow(); + if (window != null) { + window.getDecorView().setBackgroundColor(Color.TRANSPARENT); + window.getDecorView().setPadding(0, 0, 0, 0); + window.getDecorView().setMinimumWidth(context.getResources().getDisplayMetrics().widthPixels); + WindowManager.LayoutParams lps = window.getAttributes(); + lps.width = WindowManager.LayoutParams.MATCH_PARENT; + lps.height = WindowManager.LayoutParams.WRAP_CONTENT; + lps.gravity = Gravity.BOTTOM; + window.setAttributes(lps); + + } + + setContentView(R.layout.dialog_manual_quantity_gift); + setCanceledOnTouchOutside(true); + etInput = (EditText) findViewById(R.id.et_input); + tvOk = (TextView) findViewById(R.id.tv_ok); + tvOk.setOnClickListener(this); + } + + @Override + protected void onStart() { + super.onStart(); + KeyBoardUtils.showKeyBoard(context, etInput); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == tvOk.getId()) { + String str = etInput.getText().toString(); + if (TextUtils.isEmpty(str)) { +// Toast.makeText(context, "请输入数量!", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("请输入数量!"); + return; + } + + if (onConfirmClick != null) { + onConfirmClick.onConfirm(Integer.parseInt(str)); + } + } + } + + private OnConfirmClick onConfirmClick; + + public void setOnConfirmClick(OnConfirmClick onConfirmClick) { + this.onConfirmClick = onConfirmClick; + } + + public interface OnConfirmClick { + void onConfirm(int quantity); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/MonsterDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/MonsterDialog.java new file mode 100644 index 000000000..8fa11c5b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/MonsterDialog.java @@ -0,0 +1,172 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.os.CountDownTimer; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.databinding.DialogMonsterBinding; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterInfo; +import com.yizhuan.xchat_android_core.monsterhunting.bean.MonsterProtocol; + +import java.text.SimpleDateFormat; + +/** + * Created by huangmeng1 on 2018/3/29. + */ + +public class MonsterDialog extends BaseDialog implements View.OnClickListener { + + private static final String TAG = "MonsterDialog"; + + private MonsterProtocol.DataBean dataBean; + private DialogMonsterBinding binding; + private SimpleDateFormat simformat = new SimpleDateFormat("mm:ss"); + private long count; + private CountDownTimer countDownTimer; + + public MonsterDialog(Context context, MonsterProtocol.DataBean dataBean) { + this(context, 0); + this.dataBean = dataBean; + } + + public MonsterDialog(Context context, int theme) { + super(context, theme); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View inflate = LayoutInflater.from(getContext()).inflate(R.layout.dialog_monster, null); + setContentView(inflate.getRootView()); + setCanceledOnTouchOutside(true); + setCancelable(true); + binding = DataBindingUtil.bind(inflate); + + binding.ivClose.setOnClickListener(v -> dismiss()); + binding.ivBg.setOnClickListener(this); + binding.tvMsg.setOnClickListener(this); + + long beforeAppearSeconds = dataBean.getBeforeAppearSeconds(); + long millisInFuture = beforeAppearSeconds * 1000; + if (millisInFuture == 0) { + binding.llTime.setVisibility(View.INVISIBLE); + } + + if (beforeAppearSeconds >= 30) { + count = 30; + } else if (beforeAppearSeconds < 30 && beforeAppearSeconds > 15) { + count = beforeAppearSeconds - 15; + } else if (beforeAppearSeconds <= 15) { + count = 15; + } + if (dataBean.getMonsterStatus() == MonsterInfo.MONSTER_STATUS_DID_DEAD) { + binding.getRoot().postDelayed(new Runnable() { + @Override + public void run() { + dismiss(); + } + }, 30 * 1000); + } else if (dataBean.getMonsterStatus() == MonsterInfo.MONSTER_STATUS_DID_LEAVE) { + binding.getRoot().postDelayed(new Runnable() { + @Override + public void run() { + dismiss(); + } + }, 10 * 1000); + } + countDownTimer = new CountDownTimer(millisInFuture, 1000) { + @Override + public void onTick(long millisUntilFinished) { + Log.e(TAG, "onTick() called with: millisUntilFinished = [" + millisUntilFinished + "]"); + count--; + if (count == 0) { + cancelCountDownTimer(); + dismiss(); + } + String format = simformat.format(millisUntilFinished); + String[] chars = format.split(""); + binding.tv1.setText(chars[1]); + binding.tv2.setText(chars[2]); + binding.tv3.setText(chars[4]); + binding.tv4.setText(chars[5]); + } + + @Override + public void onFinish() { + binding.tv1.setText("0"); + binding.tv2.setText("0"); + binding.tv3.setText("0"); + binding.tv4.setText("0"); + dismiss(); + } + }; + countDownTimer.start(); + + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP; + windowParams.x = 0; + windowParams.y = SizeUtils.dp2px(getContext(), 15); + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + window.setWindowAnimations(R.style.anim_left); + } + if (dataBean != null) { + binding.setMonsterInfo(dataBean); + } + + this.setOnCancelListener(dialog -> { + cancelCountDownTimer(); + }); + + this.setOnDismissListener(dialog -> { + cancelCountDownTimer(); + }); + } + + public void cancelCountDownTimer() { + if (countDownTimer != null) { + countDownTimer.cancel(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_bg: + case R.id.tv_msg: + long beforeAppearSeconds = dataBean.getBeforeAppearSeconds(); + if (beforeAppearSeconds >= 30) { + CommonWebViewActivity.start(getContext(), UriProvider.IM_SERVER_URL + "/modules/monster/intro.html"); + } else if (beforeAppearSeconds < 30 && beforeAppearSeconds > 15) { + CommonWebViewActivity.start(getContext(), UriProvider.IM_SERVER_URL + "/modules/monster/intro.html"); + } else if (beforeAppearSeconds <= 15) { + AVRoomActivity.start(getContext(), dataBean.getAppearRoomUid()); + } + if (dataBean.getMonsterStatus() == MonsterInfo.MONSTER_STATUS_DID_DEAD) { + CommonWebViewActivity.start(getContext(), UriProvider.IM_SERVER_URL + + "/modules/monster/index.html?monsterId=" + dataBean.getMonsterId()); + } + break; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleDialog.java new file mode 100644 index 000000000..da7a54a48 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleDialog.java @@ -0,0 +1,85 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.util.TypedValue; +import android.view.View; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +/** + *

开通贵族弹窗提示

+ * + * @author jiahui + * @date 2018/1/17 + */ +public class OpenNobleDialog extends AppCompatDialog implements View.OnClickListener { + public static final String TAG = "OpenNobleDialog"; + private TextView tvTitle; + private TextView tvFirstLine; + private TextView tvSecondLine; + private int currentLevel; + private int needLevel; + /** 比如 送该礼物 / 发送该表情 */ + private String xxxOperation; + + public OpenNobleDialog(Context context, int currentLevel, int needLevel, String xxxOperation) { + super(context, R.style.ErbanUserInfoDialog); + this.currentLevel = currentLevel; + this.needLevel = needLevel; + this.xxxOperation = xxxOperation; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + setContentView(R.layout.fragment_dialog_open_noble); + setCanceledOnTouchOutside(true); + findViewById(R.id.btn_close).setOnClickListener(this); + findViewById(R.id.btn_open_noble).setOnClickListener(this); + tvTitle = (TextView) findViewById(R.id.tv_title); + tvFirstLine = (TextView) findViewById(R.id.tv_first_line); + tvSecondLine = (TextView) findViewById(R.id.tv_second_line); + + // 点击房间在线列表的贵族位置 + if (currentLevel == 0 && needLevel == 0 && TextUtils.isEmpty(xxxOperation)) { + tvTitle.setText("需开通贵族"); + tvFirstLine.setText("才可坐此座位"); + tvSecondLine.setText("·当前为平民·"); + } else { + // 显示文案 + String currentLevelName = TextUtils.isEmpty(NobleUtil.getNobleName(currentLevel)) ? "平民" : NobleUtil.getNobleName(currentLevel); + String needNobleName = TextUtils.isEmpty(NobleUtil.getNobleName(needLevel)) ? "贵族" : NobleUtil.getNobleName(needLevel); + String firstLineText = getContext().getResources().getString(R.string.noble_current_level, currentLevelName); + String secondLineText = getContext().getResources().getString(R.string.noble_need_level, needNobleName); + tvTitle.setText(secondLineText); + tvFirstLine.setText("才可使用该礼物"); + tvSecondLine.setText(firstLineText); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_close: + dismiss(); + break; + case R.id.btn_open_noble: + String query = (needLevel <= 0) ? "" : "?nobleId=" + needLevel; + CommonWebViewActivity.start(getContext(), UriProvider.getNobleIntro() + query); + dismiss(); + break; + default: + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleGlobalNoticeDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleGlobalNoticeDialog.java new file mode 100644 index 000000000..a61df78b0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dialog/OpenNobleGlobalNoticeDialog.java @@ -0,0 +1,77 @@ +package com.yizhuan.erban.ui.widget.dialog; + +import android.animation.Animator; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.v7.app.AppCompatDialog; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.erban.ui.widget.MarqueeLayout; + +/** + *

+ * + * @author jiahui + * @date 2018/1/22 + */ +public class OpenNobleGlobalNoticeDialog extends AppCompatDialog implements MarqueeLayout.OnAnimatorListener { + + private MarqueeLayout mMarqueeLayout; + private CharSequence mContent; + + public OpenNobleGlobalNoticeDialog(Context context, CharSequence content) { + this(context, 0); + mContent = content; + } + + public OpenNobleGlobalNoticeDialog(Context context, int theme) { + super(context, theme); + } + + protected OpenNobleGlobalNoticeDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.noble_open_global_notice_layout); + mMarqueeLayout = (MarqueeLayout) findViewById(R.id.marquee_view); + + Window window = getWindow(); + if (window != null) { + window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + WindowManager.LayoutParams windowParams = window.getAttributes(); + windowParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowParams.dimAmount = 0.0f; + windowParams.gravity = Gravity.TOP ; + windowParams.x = 0; + windowParams.y = SizeUtils.dp2px(getContext(), 62); + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); + window.setAttributes(windowParams); + } + + if (TextUtils.isEmpty(mContent)) dismiss(); + + mMarqueeLayout.setOnAnimatorListener(this); + mMarqueeLayout.setText(mContent); + mMarqueeLayout.startMarquee(); + } + + + @Override + public void onAnimationEnd(Animator animation) { + if (isShowing()) { + dismiss(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceAdapter.java new file mode 100644 index 000000000..becd9fde1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceAdapter.java @@ -0,0 +1,110 @@ +package com.yizhuan.erban.ui.widget.dynamicface; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.utils.ImageLoadUtils; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_library.utils.config.BasicConfig; + +import java.io.File; +import java.util.List; + +/** + * @author chenran + * @date 2017/9/8 + */ + +public class DynamicFaceAdapter extends BaseAdapter implements View.OnClickListener { + private List faceInfoList; + private Context context; + private OnFaceItemClickListener onFaceItemClickListener; + + public void setOnFaceItemClickListener(OnFaceItemClickListener onFaceItemClickListener) { + this.onFaceItemClickListener = onFaceItemClickListener; + } + + public DynamicFaceAdapter(Context context, List faceInfoList) { + this.faceInfoList = faceInfoList; + this.context = context; + } + + @Override + public int getCount() { + if (faceInfoList == null) { + return 0; + } else { + return faceInfoList.size(); + } + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + FaceViewHolder holder; + if (null == convertView) { + holder = new FaceViewHolder(); + //mContext指的是调用的Activity + convertView = LayoutInflater.from(context).inflate(R.layout.list_item_face, null); + holder.faceIcon = (ImageView) convertView.findViewById(R.id.face_image); + holder.faceName = (TextView) convertView.findViewById(R.id.face_name); + holder.container = convertView.findViewById(R.id.face_layout); + holder.ivNobleTag = convertView.findViewById(R.id.iv_noble_tag); + convertView.setTag(holder); + } else { + holder = (FaceViewHolder) convertView.getTag(); + } + FaceInfo faceInfo = faceInfoList.get(position); + holder.container.setTag(faceInfo); + holder.container.setOnClickListener(this); + File file = new File(faceInfo.getFacePath(faceInfo.getIconImageIndex())); + ImageLoadUtils.loadImage(BasicConfig.INSTANCE.getAppContext(), file, holder.faceIcon); + holder.faceName.setText(faceInfo.getCNName()); + int nobleId = faceInfo.getNobleId(); + if (nobleId == 0) { + // 普通表情 + holder.ivNobleTag.setImageDrawable(null); + } else { + int drawableId = nobleId == 1 ? R.drawable.ic_tag_1 : nobleId == 2 ? R.drawable.ic_tag_2 : nobleId == 3 ? + R.drawable.ic_tag_3 : nobleId == 4 ? R.drawable.ic_tag_4 : nobleId == 5 ? R.drawable.ic_tag_5 : nobleId == 6 ? + R.drawable.ic_tag_6 : nobleId == 7 ? R.drawable.ic_tag_7 : 0; + holder.ivNobleTag.setImageResource(drawableId); + } + + return convertView; + } + + @Override + public void onClick(View v) { + if (onFaceItemClickListener != null) { + FaceInfo faceInfo = (FaceInfo) v.getTag(); + onFaceItemClickListener.onFaceItemClick(faceInfo); + } + } + + public interface OnFaceItemClickListener { + void onFaceItemClick(FaceInfo faceInfo); + } + + private class FaceViewHolder { + private ImageView faceIcon; + private TextView faceName; + private View container; + private ImageView ivNobleTag; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceBuilder.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceBuilder.java new file mode 100644 index 000000000..5ad2a4c85 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceBuilder.java @@ -0,0 +1,362 @@ +package com.yizhuan.erban.ui.widget.dynamicface; + +import com.yizhuan.erban.R; + +/** + * Created by chenran on 2017/9/9. + */ + +public class DynamicFaceBuilder { +// public static final int FACE_ITEM_DAXIAO = 1; +// public static final int FACE_ITEM_LIUHAN = 2; +// public static final int FACE_ITEM_SEMIMI = 3; +// public static final int FACE_ITEM_LIULEI = 4; +// public static final int FACE_ITEM_FEIWEN = 5; +// public static final int FACE_ITEM_JUSANG = 6; +// public static final int FACE_ITEM_WUYAN = 7; +// public static final int FACE_ITEM_KAXINTUSHETOU = 8; +// public static final int FACE_ITEM_BAIBAI = 9; +// public static final int FACE_ITEM_BISHI = 10; +// public static final int FACE_ITEM_EMOHUAIXIAO = 11; +// public static final int FACE_ITEM_TIANSHIWEIXIAO = 12; +// public static final int FACE_ITEM_SHENGQI = 13; +// public static final int FACE_ITEM_BAOBAO = 14; +// public static final int FACE_ITEM_TINGYINYUE = 15; +// public static final int FACE_ITEM_WABIKONG = 16; +// public static final int FACE_ITEM_SHAIZI = 17; +// public static final int FACE_ITEM_SHITOUJIANDAOBU = 18; +// public static final int FACE_ITEM_CHOUQIAN = 19; +// +// private HashMap faceMap; +// +// public DynamicFaceBuilder() { +// faceMap = new HashMap<>(); +// +// } +// +// public int[] daxiao_res = new int[]{ +// R.drawable.daxiao_1_1, +// R.drawable.daxiao_1_2, +// R.drawable.daxiao_1_3, +// R.drawable.daxiao_1_4, +// R.drawable.daxiao_1_5, +// R.drawable.daxiao_1_6 +// }; +// +// public int[] liuhan_res = new int[]{ +// R.drawable.liuhan_2_1, +// R.drawable.liuhan_2_2, +// R.drawable.liuhan_2_3, +// R.drawable.liuhan_2_4, +// R.drawable.liuhan_2_5, +// R.drawable.liuhan_2_6, +// R.drawable.liuhan_2_7, +// R.drawable.liuhan_2_8 +// }; +// +// public int[] semimi_res = new int[]{ +// R.drawable.semimi_3_1, +// R.drawable.semimi_3_2, +// R.drawable.semimi_3_3 +// }; +// +// public int[] liulei_res = new int[]{ +// R.drawable.liulei_4_1, +// R.drawable.liulei_4_2, +// R.drawable.liulei_4_3, +// R.drawable.liulei_4_4 +// }; +// +// public int[] feiwen_res = new int[]{ +// R.drawable.feiwen_5_1, +// R.drawable.feiwen_5_2, +// R.drawable.feiwen_5_3, +// R.drawable.feiwen_5_4, +// R.drawable.feiwen_5_5, +// R.drawable.feiwen_5_6, +// R.drawable.feiwen_5_7, +// R.drawable.feiwen_5_8 +// }; +// +// public int[] jusang_res = new int[]{ +// R.drawable.jusang_6_1, +// R.drawable.jusang_6_2, +// R.drawable.jusang_6_3, +// R.drawable.jusang_6_4, +// R.drawable.jusang_6_5, +// R.drawable.jusang_6_6, +// R.drawable.jusang_6_7, +// R.drawable.jusang_6_8 +// }; +// +// public int[] wuyan_res = new int[]{ +// R.drawable.wuyan_7_1, +// R.drawable.wuyan_7_2, +// R.drawable.wuyan_7_3, +// R.drawable.wuyan_7_4, +// R.drawable.wuyan_7_5, +// R.drawable.wuyan_7_6, +// R.drawable.wuyan_7_7 +// }; +// +// public int[] kaixintushetou_res = new int[]{ +// R.drawable.kaxintushetou_8_1, +// R.drawable.kaxintushetou_8_2, +// R.drawable.kaxintushetou_8_3, +// R.drawable.kaxintushetou_8_4, +// R.drawable.kaxintushetou_8_5, +// R.drawable.kaxintushetou_8_6, +// R.drawable.kaxintushetou_8_7, +// R.drawable.kaxintushetou_8_8 +// }; +// +// public int[] baibai_res = new int[]{ +// R.drawable.baibai_9_1, +// R.drawable.baibai_9_2, +// R.drawable.baibai_9_3, +// R.drawable.baibai_9_4, +// R.drawable.baibai_9_5, +// R.drawable.baibai_9_6 +// }; +// +// public int[] bishi_res = new int[]{ +// R.drawable.bishi_10_1, +// R.drawable.bishi_10_2 +// }; +// +// public int[] emohuaixiao_res = new int[]{ +// R.drawable.emohuaixiao_11_1, +// R.drawable.emohuaixiao_11_2, +// R.drawable.emohuaixiao_11_3, +// R.drawable.emohuaixiao_11_4 +// }; +// +// public int[] tianshiweixiao_res = new int[]{ +// R.drawable.tianshiweixiao_12_1, +// R.drawable.tianshiweixiao_12_2, +// R.drawable.tianshiweixiao_12_3, +// R.drawable.tianshiweixiao_12_4, +// R.drawable.tianshiweixiao_12_5, +// R.drawable.tianshiweixiao_12_6 +// }; +// +// public int[] shengqi_res = new int[]{ +// R.drawable.shengqi_13_1, +// R.drawable.shengqi_13_2, +// R.drawable.shengqi_13_3, +// R.drawable.shengqi_13_4, +// R.drawable.shengqi_13_5, +// R.drawable.shengqi_13_6 +// }; +// +// public int[] baobao_res = new int[]{ +// R.drawable.baobao_14_1, +// R.drawable.baobao_14_2, +// R.drawable.baobao_14_3, +// R.drawable.baobao_14_4, +// R.drawable.baobao_14_5 +// }; +// +// public int[] tingyinyue_res = new int[]{ +// R.drawable.tingyinyue_15_1, +// R.drawable.tingyinyue_15_2, +// R.drawable.tingyinyue_15_3, +// R.drawable.tingyinyue_15_4, +// R.drawable.tingyinyue_15_5, +// R.drawable.tingyinyue_15_6 +// }; +// +// public int[] wabikong_res = new int[]{ +// R.drawable.wabikong_21_1, +// R.drawable.wabikong_21_2, +// R.drawable.wabikong_21_3 +// }; +// +// public int[] shaizi_res = new int[]{ +// R.drawable.shaizi_17_1, +// R.drawable.shaizi_17_2, +// R.drawable.shaizi_17_3, +// R.drawable.shaizi_17_4, +// R.drawable.shaizi_17_5 +// }; +// +// public int[] shaizi_result_res = new int[] { +// R.drawable.shaizi_17_6, +// R.drawable.shaizi_17_7, +// R.drawable.shaizi_17_8, +// R.drawable.shaizi_17_9, +// R.drawable.shaizi_17_10, +// R.drawable.shaizi_17_11 +// }; +// +// public int[] shitoujiandaobu_res = new int[]{ +// R.drawable.shitoujiandaobu_18_1, +// R.drawable.shitoujiandaobu_18_2, +// R.drawable.shitoujiandaobu_18_3 +// }; +// +// public int[] shitoujiandaobu_result_res = new int[]{ +// R.drawable.shitoujiandaobu_18_1, +// R.drawable.shitoujiandaobu_18_2, +// R.drawable.shitoujiandaobu_18_3 +// }; +// +// public int[] chouqian_res = new int[]{ +// R.drawable.chouqian_20_1, +// R.drawable.chouqian_20_2, +// R.drawable.chouqian_20_3, +// R.drawable.chouqian_20_4, +// R.drawable.chouqian_20_5, +// R.drawable.chouqian_20_6 +// }; +// +// public int[] chouqian_result_res = new int[]{ +// R.drawable.chouqian_20_7, +// R.drawable.chouqian_20_8, +// R.drawable.chouqian_20_9, +// R.drawable.chouqian_20_10, +// R.drawable.chouqian_20_11, +// R.drawable.chouqian_20_12, +// R.drawable.chouqian_20_13, +// R.drawable.chouqian_20_14 +// }; +// +// public void createFaceItem(int faceId) { +// FaceItem faceItem = new FaceItem(faceId); +// if (faceId == FACE_ITEM_DAXIAO) { +// faceItem.setFaceName("大笑"); +// faceItem.setFaceResId(R.drawable.daxiao_1_0); +// } else if (faceId == FACE_ITEM_LIUHAN) { +// faceItem.setFaceName("流汗"); +// faceItem.setFaceResId(R.drawable.liuhan_2_0); +// } else if (faceId == FACE_ITEM_SEMIMI) { +// faceItem.setFaceName("色眯眯"); +// faceItem.setFaceResId(R.drawable.semimi_3_0); +// }else if (faceId == FACE_ITEM_LIULEI) { +// faceItem.setFaceName("流泪"); +// faceItem.setFaceResId(R.drawable.liulei_4_0); +// }else if (faceId == FACE_ITEM_FEIWEN) { +// faceItem.setFaceName("飞吻"); +// faceItem.setFaceResId(R.drawable.feiwen_5_0); +// }else if (faceId == FACE_ITEM_JUSANG) { +// faceItem.setFaceName("沮丧"); +// faceItem.setFaceResId(R.drawable.jusang_6_0); +// }else if (faceId == FACE_ITEM_WUYAN) { +// faceItem.setFaceName("无言"); +// faceItem.setFaceResId(R.drawable.wuyan_7_0); +// }else if (faceId == FACE_ITEM_KAXINTUSHETOU) { +// faceItem.setFaceName("吐舌头"); +// faceItem.setFaceResId(R.drawable.kaxintushetou_8_0); +// }else if (faceId == FACE_ITEM_BAIBAI) { +// faceItem.setFaceName("拜拜"); +// faceItem.setFaceResId(R.drawable.baibai_9_0); +// }else if (faceId == FACE_ITEM_BISHI) { +// faceItem.setFaceName("鄙视"); +// faceItem.setFaceResId(R.drawable.bishi_10_0); +// }else if (faceId == FACE_ITEM_EMOHUAIXIAO) { +// faceItem.setFaceName("鄙视"); +// faceItem.setFaceResId(R.drawable.bishi_10_0); +// }else if (faceId == FACE_ITEM_TIANSHIWEIXIAO) { +// }else if (faceId == FACE_ITEM_SHENGQI) { +// }else if (faceId == FACE_ITEM_BAOBAO) { +// }else if (faceId == FACE_ITEM_TINGYINYUE) { +// }else if (faceId == FACE_ITEM_WABIKONG) { +// }else if (faceId == FACE_ITEM_SHAIZI) { +// }else if (faceId == FACE_ITEM_SHITOUJIANDAOBU) { +// }else if (faceId == FACE_ITEM_CHOUQIAN) { +// } +// } +// +// public void createResultItem(int faceId, int resultNumber) { +// FaceResultItem faceResultItem = new FaceResultItem(); +// faceResultItem.setFaceId(faceId); +// faceResultItem.setResultNumber(resultNumber); +// +// if (faceId == FACE_ITEM_DAXIAO) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(daxiao_res); +// } else if (faceId == FACE_ITEM_LIUHAN) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(liuhan_res); +// } else if (faceId == FACE_ITEM_SEMIMI) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(semimi_res); +// }else if (faceId == FACE_ITEM_LIULEI) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(liulei_res); +// }else if (faceId == FACE_ITEM_FEIWEN) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(feiwen_res); +// }else if (faceId == FACE_ITEM_JUSANG) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(jusang_res); +// }else if (faceId == FACE_ITEM_WUYAN) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(wuyan_res); +// }else if (faceId == FACE_ITEM_KAXINTUSHETOU) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(kaixintushetou_res); +// }else if (faceId == FACE_ITEM_BAIBAI) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(baibai_res); +// }else if (faceId == FACE_ITEM_BISHI) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(bishi_res); +// }else if (faceId == FACE_ITEM_EMOHUAIXIAO) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(emohuaixiao_res); +// }else if (faceId == FACE_ITEM_TIANSHIWEIXIAO) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(tianshiweixiao_res); +// }else if (faceId == FACE_ITEM_SHENGQI) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(shengqi_res); +// }else if (faceId == FACE_ITEM_BAOBAO) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(baobao_res); +// }else if (faceId == FACE_ITEM_TINGYINYUE) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(tingyinyue_res); +// }else if (faceId == FACE_ITEM_WABIKONG) { +// faceResultItem.setResultFace(false); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(wabikong_res); +// }else if (faceId == FACE_ITEM_SHAIZI) { +// faceResultItem.setResultFace(true); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(shaizi_res); +// faceResultItem.setResultNumber(resultNumber); +// faceResultItem.setFaceResultRes(shaizi_result_res[resultNumber]); +// faceResultItem.setResultDuration(4000); +// }else if (faceId == FACE_ITEM_SHITOUJIANDAOBU) { +// faceResultItem.setResultFace(true); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(shitoujiandaobu_res); +// faceResultItem.setResultNumber(resultNumber); +// faceResultItem.setFaceResultRes(shaizi_result_res[resultNumber]); +// faceResultItem.setResultDuration(4000); +// }else if (faceId == FACE_ITEM_CHOUQIAN) { +// faceResultItem.setResultFace(true); +// faceResultItem.setFaceMoveDuration(3000); +// faceResultItem.setFaceMoveRes(chouqian_res); +// faceResultItem.setResultNumber(resultNumber); +// faceResultItem.setFaceResultRes(chouqian_result_res[resultNumber]); +// faceResultItem.setResultDuration(4000); +// } +// } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceDialog.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceDialog.java new file mode 100644 index 000000000..7aa93f070 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/DynamicFaceDialog.java @@ -0,0 +1,353 @@ +package com.yizhuan.erban.ui.widget.dynamicface; + +import android.content.Context; +import android.os.Bundle; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.BottomSheetDialog; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.GridView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.dialog.OpenNobleDialog; +import com.yizhuan.erban.ui.widget.marqueeview.Utils; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.market_verify.MarketVerifyModel; +import com.yizhuan.xchat_android_core.room.event.FaceIsReadyEvent; +import com.yizhuan.xchat_android_core.room.face.DynamicFaceModel; +import com.yizhuan.xchat_android_core.room.face.FaceInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + + +/** + * @author xiaoyu + * @date 2017/12/8 + */ + +public class DynamicFaceDialog extends BottomSheetDialog + implements DynamicFaceAdapter.OnFaceItemClickListener, View.OnClickListener { + private static final String TAG = "DynamicFaceDialog"; + private Context context; + private static int USER_SELECTED_POS = -1; + private static int USER_SELECTED_TAB = 0; + private static int TAB_NORMAL_FACE = 0; + private static int TAB_NOBLE_FACE = 1; + private TextView tvNormalTab; + private TextView tvNobleTab; + private ViewPager vpMenu; + private LinearLayout llIndicator; + private FaceFilter faceFilter; + + + public DynamicFaceDialog(Context context) { + super(context, R.style.ErbanBottomSheetDialog); + this.context = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + setCanceledOnTouchOutside(true); + setCancelable(true); + setContentView(R.layout.dialog_bottom_face); + EventBus.getDefault().register(this); + init(findViewById(R.id.rl_dynamic_face_dialog_root)); + FrameLayout bottomSheet = (FrameLayout) findViewById(android.support.design.R.id.design_bottom_sheet); + if (bottomSheet != null) { + BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(false); + BottomSheetBehavior.from(bottomSheet).setPeekHeight( + (int) context.getResources().getDimension(R.dimen.dialog_face_height)); + } + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.height = context.getResources().getDisplayMetrics().heightPixels - (Utils.hasSoftKeys(context) ? Utils.getNavigationBarHeight(context) : 0); + getWindow().setAttributes(params); + } + + private void init(View root) { + // 普通tab和贵族tab + tvNobleTab = root.findViewById(R.id.tv_noble_face_tab); + tvNormalTab = root.findViewById(R.id.tv_normal_face_tab); + vpMenu = root.findViewById(R.id.viewpager); + llIndicator = root.findViewById(R.id.ll_dynamic_face_dialog_indicator); + tvNobleTab.setOnClickListener(this); + tvNormalTab.setOnClickListener(this); + List faceInfos = null; + if (USER_SELECTED_TAB == TAB_NOBLE_FACE) { + faceInfos = getNobleFaceList(); + tvNobleTab.setSelected(true); + tvNormalTab.setSelected(false); + } + // 如果没有贵族表情,则显示普通表情 + if (ListUtils.isListEmpty(faceInfos) || USER_SELECTED_TAB == TAB_NORMAL_FACE) { + USER_SELECTED_TAB = TAB_NORMAL_FACE; + faceInfos = getNormalFaceList(); + tvNobleTab.setSelected(false); + tvNormalTab.setSelected(true); + } + if (faceInfos == null || faceInfos.size() == 0) { +// Toast.makeText(context, "表情准备中...", Toast.LENGTH_SHORT).show(); + SingleToastUtil.showToastShort("表情准备中..."); + return; + } + updateFace(faceInfos); + } + + private void updateFace(List faceInfos) { + List pagerView = new ArrayList<>(); + List> lists = resolveData(faceInfos); + int size = lists.size(); + for (int i = 0; i < size; i++) { + View view = LayoutInflater.from(context).inflate(R.layout.layout_face_grid_view, vpMenu, false); + GridView gridView = view.findViewById(R.id.gridView); + DynamicFaceAdapter adapter = new DynamicFaceAdapter(context, lists.get(i)); + adapter.setOnFaceItemClickListener(this); + gridView.setAdapter(adapter); + adapter.notifyDataSetChanged(); + pagerView.add(view); + } + + MyViewPagerAdapter pagerAdapter = new MyViewPagerAdapter(pagerView); + vpMenu.setAdapter(pagerAdapter); + pagerAdapter.notifyDataSetChanged(); + + // 准备indicator + int indicatorDotLength = Utils.dip2px(context, 6); + int indicatorDotSpace = Utils.dip2px(context, 5); + llIndicator.removeAllViews(); + for (int i = 0; i < size; i++) { + View view = new View(context); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(indicatorDotLength, indicatorDotLength); + if (i != 0) { + params.leftMargin = indicatorDotSpace; + } + view.setLayoutParams(params); + view.setBackgroundResource(R.drawable.bg_dynamic_face_dialog_selector); + llIndicator.addView(view); + } + // 选中当前页的indicator + if (USER_SELECTED_POS == -1) { + USER_SELECTED_POS = 0; + } else if (USER_SELECTED_POS + 1 > size) { + USER_SELECTED_POS = 0; + } + selectIndicator(llIndicator, USER_SELECTED_POS); + vpMenu.setCurrentItem(USER_SELECTED_POS); + vpMenu.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + selectIndicator(llIndicator, position); + USER_SELECTED_POS = position; + } + }); + } + + private List getNormalFaceList() { + List infos = new ArrayList<>(); + List faceInfos = DynamicFaceModel.get().getFaceInfos(); + if (ListUtils.isListEmpty(faceInfos)) return infos; + for (int i = 0; i < faceInfos.size(); i++) { + if (!faceInfos.get(i).isNobleFace() || faceInfos.get(i).getNobleId() == 0) { + infos.add(faceInfos.get(i)); + } + } + if (faceFilter != null){ + return faceFilter.onFilter(infos); + }else { + return infos; + } + + } + + private List getNobleFaceList() { + List infos = new ArrayList<>(); + List faceInfos = DynamicFaceModel.get().getFaceInfos(); + if (ListUtils.isListEmpty(faceInfos)) return infos; + for (int i = 0; i < faceInfos.size(); i++) { + if (faceInfos.get(i).isNobleFace() || faceInfos.get(i).getNobleId() > 0) { + infos.add(faceInfos.get(i)); + } + } + if (faceFilter != null){ + return faceFilter.onFilter(infos); + }else { + return infos; + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onFeceIsReady(FaceIsReadyEvent event) { + init(findViewById(R.id.rl_dynamic_face_dialog_root)); + } + + private void selectIndicator(ViewGroup viewGroup, int position) { + int size = viewGroup.getChildCount(); + for (int i = 0; i < size; i++) { + viewGroup.getChildAt(i).setSelected(i == position); + } + } + + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + } + + private static final int IMAGE_COUNT_PER_PAGE = 15; + + /** + * 解析数据,决定哪些表情可以出现在表情面板上面 + * @param faceInfos 普通表情 / 贵族表情 + * @return 返回格式是 List>, 子元素是一个个的列表,每一个子列表代表的是表情面板上看到的每一页 + */ + private List> resolveData(List faceInfos) { + int size = faceInfos.size(); + List> results = new ArrayList<>(); + // 动画完成后直接消失的表情 + List normalFaceList = new ArrayList<>(); + // 动画完成后要停留几秒展示结果的表情 + List luckFaceInfoList = new ArrayList<>(); + boolean marketChecking = MarketVerifyModel.get().isMarketChecking(); + for (FaceInfo faceInfo : faceInfos) { + // 是否需要出现在表情面板上 + if (faceInfo.getFaceType() == FaceInfo.TYPE_FACE_NORMAL) { + // 不需要隐藏的表情直接加入到 list 里 + if (!faceInfo.isLuckFace()) { + // 普通表情还是运气表情 + if (faceInfo.getResultCount() > 0) { + luckFaceInfoList.add(faceInfo); + } else { + normalFaceList.add(faceInfo); + } + } else { + // 如果此时正在审核中,则不将其加入到 list 里 + // 否则就加入到 list 里,出现在表情面板上 + if (!marketChecking) { + // 普通表情还是运气表情 + if (faceInfo.getResultCount() > 0) { + luckFaceInfoList.add(faceInfo); + } else { + normalFaceList.add(faceInfo); + } + } + } + } + } + List tmp = new ArrayList<>(); + for (FaceInfo faceInfo : normalFaceList) { + tmp.add(faceInfo); + // 满 IMAGE_COUNT_PER_PAGE 个后,换一页 + if (tmp.size() == IMAGE_COUNT_PER_PAGE) { + results.add(tmp); + tmp = new ArrayList<>(); + } + } + for (FaceInfo faceInfo : luckFaceInfoList) { + tmp.add(faceInfo); + // 满 IMAGE_COUNT_PER_PAGE 个后,换一页 + if (tmp.size() == IMAGE_COUNT_PER_PAGE) { + results.add(tmp); + tmp = new ArrayList<>(); + } + } + // 最后,未满 IMAGE_COUNT_PER_PAGE 个,将剩下的都加入到 list 里 + if (tmp.size() < IMAGE_COUNT_PER_PAGE) { + results.add(tmp); + } + return results; + } + + @Override + public void onFaceItemClick(FaceInfo faceInfo) { + if (faceInfo != null && !DynamicFaceModel.get().isShowingFace()) { + boolean canUseNobleFaceOrNot = DynamicFaceModel.get().canUseNobleFaceOrNot(faceInfo); + if (canUseNobleFaceOrNot) { + DynamicFaceModel.get().sendFace(faceInfo); + } else { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + int currentLevel = userInfo == null ? 0 : userInfo.getNobleInfo() == null ? 0 : userInfo.getNobleInfo().getLevel(); + new OpenNobleDialog(context, currentLevel, faceInfo.getNobleId(), "发送该表情").show(); + } + dismiss(); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.tv_noble_face_tab) { + // 在普通表情页面点击贵族表情页面 + if (USER_SELECTED_TAB == TAB_NORMAL_FACE) { + USER_SELECTED_TAB = TAB_NOBLE_FACE; + updateFace(getNobleFaceList()); + tvNobleTab.setSelected(true); + tvNormalTab.setSelected(false); + } + } else if (v.getId() == R.id.tv_normal_face_tab) { + if (USER_SELECTED_TAB == TAB_NOBLE_FACE) { + USER_SELECTED_TAB = TAB_NORMAL_FACE; + updateFace(getNormalFaceList()); + tvNobleTab.setSelected(false); + tvNormalTab.setSelected(true); + } + } + } + + public class MyViewPagerAdapter extends PagerAdapter { + + private List mLists; + + MyViewPagerAdapter(List array) { + this.mLists = array; + } + + @Override + public int getCount() { + return mLists.size(); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + container.addView(mLists.get(position)); + return mLists.get(position); + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + + } + + } + + public void setFaceFilter(FaceFilter faceFilter) { + this.faceFilter = faceFilter; + } + + public interface FaceFilter{ + List onFilter(List faceInfoList); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceItem.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceItem.java new file mode 100644 index 000000000..119658472 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceItem.java @@ -0,0 +1,39 @@ +package com.yizhuan.erban.ui.widget.dynamicface; + +/** + * Created by chenran on 2017/9/9. + */ + +public class FaceItem { + private int faceId; + private String faceName; + private String faceUrl; + + public String getFaceUrl() { + return faceUrl; + } + + public void setFaceUrl(String faceUrl) { + this.faceUrl = faceUrl; + } + + public FaceItem(int faceId) { + this.faceId = faceId; + } + + public int getFaceId() { + return faceId; + } + + public void setFaceId(int faceId) { + this.faceId = faceId; + } + + public String getFaceName() { + return faceName; + } + + public void setFaceName(String faceName) { + this.faceName = faceName; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceResultItem.java b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceResultItem.java new file mode 100644 index 000000000..8eac9f3f5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/dynamicface/FaceResultItem.java @@ -0,0 +1,89 @@ +package com.yizhuan.erban.ui.widget.dynamicface; + +/** + * Created by chenran on 2017/9/9. + */ + +public class FaceResultItem { + private int faceId; + private int[] faceMoveRes; + private int faceResultRes; + private boolean isResultFace; + private int resultNumber; + private int faceMoveDuration; + private int resultDuration; + private int faceFrameRate; + private String faceResultName; + + public int getFaceId() { + return faceId; + } + + public void setFaceId(int faceId) { + this.faceId = faceId; + } + + public int[] getFaceMoveRes() { + return faceMoveRes; + } + + public void setFaceMoveRes(int[] faceMoveRes) { + this.faceMoveRes = faceMoveRes; + } + + public int getFaceResultRes() { + return faceResultRes; + } + + public void setFaceResultRes(int faceResultRes) { + this.faceResultRes = faceResultRes; + } + + public boolean isResultFace() { + return isResultFace; + } + + public void setResultFace(boolean resultFace) { + isResultFace = resultFace; + } + + public int getResultNumber() { + return resultNumber; + } + + public void setResultNumber(int resultNumber) { + this.resultNumber = resultNumber; + } + + public int getFaceMoveDuration() { + return faceMoveDuration; + } + + public void setFaceMoveDuration(int faceMoveDuration) { + this.faceMoveDuration = faceMoveDuration; + } + + public int getResultDuration() { + return resultDuration; + } + + public void setResultDuration(int resultDuration) { + this.resultDuration = resultDuration; + } + + public int getFaceFrameRate() { + return faceFrameRate; + } + + public void setFaceFrameRate(int faceFrameRate) { + this.faceFrameRate = faceFrameRate; + } + + public String getFaceResultName() { + return faceResultName; + } + + public void setFaceResultName(String faceResultName) { + this.faceResultName = faceResultName; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideUtils.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideUtils.java new file mode 100644 index 000000000..099b343f9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideUtils.java @@ -0,0 +1,93 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.content.Context; +import android.graphics.Point; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +/** + * Create Zii at 2018/5/4. + */ +public class GuideUtils { + + public static int getScreenWidth(Context context) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + if (wm == null) { + return context.getResources().getDisplayMetrics().widthPixels; + } + Point point = new Point(); + wm.getDefaultDisplay().getRealSize(point); + return point.x; + } + + public static int getScreenHeight(Context context) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + if (wm == null) { + return context.getResources().getDisplayMetrics().heightPixels; + } + Point point = new Point(); + wm.getDefaultDisplay().getRealSize(point); + return point.y; + } + + public static int[] getScreenSize(Context context) { + int[] sizes = new int[2]; + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + if (wm == null) { + sizes[0] = context.getResources().getDisplayMetrics().widthPixels; + sizes[1] = context.getResources().getDisplayMetrics().heightPixels; + return sizes; + } + Point point = new Point(); + wm.getDefaultDisplay().getRealSize(point); + sizes[0] = point.x; + sizes[1] = point.y; + return sizes; + } + + public static float dp2px(Context context, final float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return dpValue * scale + 0.5f; + } + + public static int getMeasuredWidth(final View view) { + return measureView(view)[0]; + } + + public static int getMeasuredHeight(final View view) { + return measureView(view)[1]; + } + + public static int[] measureView(final View view) { + ViewGroup.LayoutParams lp = view.getLayoutParams(); + if (lp == null) { + lp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ); + } + int widthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width); + int lpHeight = lp.height; + int heightSpec; + if (lpHeight > 0) { + heightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY); + } else { + heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + } + view.measure(widthSpec, heightSpec); + return new int[]{view.getMeasuredWidth(), view.getMeasuredHeight()}; + } + + + public static boolean isSameLocation(int[] last, int[] now) { + try { + return last[0] == now[0] && last[1] == now[1]; + } catch (Exception ex) { + ex.printStackTrace(); + } + return false; + } + + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideView.java new file mode 100644 index 000000000..fe9dea74d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/GuideView.java @@ -0,0 +1,201 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; + +import com.yizhuan.erban.ui.widget.higuide.Overlay.HightLight; +import com.yizhuan.erban.ui.widget.higuide.Overlay.Tips; +import com.yizhuan.erban.ui.widget.higuide.Overlay.Tips.Margin; + +/** + * Create By Zii at 2018/5/3. + */ +class GuideView extends FrameLayout { + + private Overlay mOverlay; + private Paint mPaint; + private Path mBgPath; + private Path mShapePath; + private RemoveCallback mRemoveCallback; + + public GuideView(Context context, Overlay overlay) { + super(context); + mOverlay = overlay; + init(); + } + + private void init() { + final int bgColor = mOverlay.getColorBg(); + + mBgPath = new Path(); + mShapePath = new Path(); + + mPaint = new Paint(); + mPaint.setColor(bgColor); + mPaint.setDither(true); + mPaint.setAntiAlias(true); + + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + mBgPath.reset(); + mShapePath.reset(); + + mBgPath.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW); + + for (HightLight hightLight : mOverlay.getHightLightList()) { + Path shapePath = calcHightLightShapePath(hightLight, mShapePath); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + mBgPath.op(shapePath, Path.Op.XOR); + } + } + + canvas.drawPath(mBgPath, mPaint); + } + + private Path calcHightLightShapePath(HightLight hightLight, Path shapePath) { + shapePath.reset(); + switch (hightLight.getShape()) { + case HiGuide.SHAPE_CIRCLE: + shapePath.addCircle(hightLight.getRectF().centerX(), + hightLight.getRectF().centerY(), + hightLight.getRadius(), Path.Direction.CW); + break; + case HiGuide.SHAPE_OVAL: + shapePath.addOval(hightLight.getRectF(), Path.Direction.CW); + break; + case HiGuide.SHAPE_RECT: + shapePath.addRect(hightLight.getRectF(), Path.Direction.CW); + break; + default: + break; + } + return shapePath; + } + + public void addTipsViews() { + for (HightLight hightLight : mOverlay.getHightLightList()) { + + if (hightLight != null + && hightLight.getTips() != null + && hightLight.getTips().layoutRes != -1) { + + addTipsView(hightLight.getTips(), hightLight.getRectF()); + } + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + //点击高亮 + if (mOverlay.getOnClickHightLightListener() != null) { + float x = event.getX(); + float y = event.getY(); + for (RectF rectF : mOverlay.getHightLightAreas()) { + if (rectF.contains(x, y)) { + mOverlay.getOnClickHightLightListener().onClick(this); + remove(); + return super.onTouchEvent(event); //点击高亮后不做其他的处理了,直接返回 + } + } + } + //全局点击 + if (mOverlay.getOnClickGuideViewListener() != null) { + mOverlay.getOnClickGuideViewListener().onClick(this); + } + if (mOverlay.isTouchDismiss()) { + remove(); + } + } + + return true; + } + + private void remove() { + ViewGroup parent = (ViewGroup) getParent(); + if (parent instanceof RelativeLayout || parent instanceof FrameLayout) { + parent.removeView(this); + } else { + parent.removeView(this); + View origin = parent.getChildAt(0); + ViewGroup graParent = (ViewGroup) parent.getParent(); + graParent.removeView(parent); + graParent.addView(origin, parent.getLayoutParams()); + } + + if (mRemoveCallback != null) { + mRemoveCallback.callback(); + } + } + + public void addTipsView(Tips tips, RectF hlRectF) { + View tipsView = LayoutInflater.from(getContext()).inflate(tips.layoutRes, this, false); + int tipsWidth = GuideUtils.getMeasuredWidth(tipsView); + Margin margin = tips.margin == null ? new Margin(0, 0, 0, 0) : tips.margin; + + LayoutParams lp = (LayoutParams) tipsView.getLayoutParams(); + + switch (tips.to) { + case Tips.TO_LEFT_OF: + lp.leftMargin = (int) (hlRectF.left - tipsWidth - margin.right); + switch (tips.align) { + case Tips.ALIGN_BOTTOM: + lp.topMargin = (int) (hlRectF.bottom + margin.top); + break; + case Tips.ALIGN_TOP: + lp.topMargin = (int) (hlRectF.top + margin.top); + break; + default: + lp.topMargin = margin.top; + break; + } + break; + case Tips.TO_RIGHT_OF: + lp.leftMargin = (int) (hlRectF.right + margin.left); + switch (tips.align) { + case Tips.ALIGN_BOTTOM: + lp.topMargin = (int) (hlRectF.bottom + margin.top); + break; + case Tips.ALIGN_TOP: + lp.topMargin = (int) (hlRectF.top + margin.top); + break; + default: + lp.topMargin = margin.top; + break; + } + break; + default: + lp.leftMargin = margin.left; + lp.topMargin = margin.top; + lp.rightMargin = margin.right; + lp.bottomMargin = margin.bottom; + break; + } + + tipsView.setLayoutParams(lp); + + addView(tipsView, lp); + } + + public void setRemoveCallback(RemoveCallback removeCallback) { + mRemoveCallback = removeCallback; + } + + public interface RemoveCallback { + + void callback(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiGuide.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiGuide.java new file mode 100644 index 000000000..e27e57a74 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiGuide.java @@ -0,0 +1,125 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.app.Activity; +import android.content.Context; +import android.support.annotation.IntDef; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.higuide.GuideView.RemoveCallback; +import com.yizhuan.erban.ui.widget.higuide.Overlay.Tips; + +import java.util.ArrayList; +import java.util.List; + +/** + * Create Zii at 2018/5/3. + */ +public class HiGuide { + + private Context mContext; + private ViewGroup mRootView; + private GuideView mGuideView; + private List mOverlays; + private Overlay mDefaultOverlay; + private boolean mIsOpenNext; + + public HiGuide(Context context) { + mContext = context; + + init(); + } + + private void init() { + mRootView = (ViewGroup) ((Activity) mContext).getWindow().getDecorView(); + mOverlays = new ArrayList<>(); + mDefaultOverlay = new Overlay(); + mOverlays.add(mDefaultOverlay); + } + + public HiGuide touchDismiss(boolean isDismiss) { + mDefaultOverlay.touchDismiss(isDismiss); + return this; + } + + public HiGuide bgColor(int color) { + mDefaultOverlay.bgColor(color); + return this; + } + + public HiGuide addHightLightClickListener(View.OnClickListener listener) { + mDefaultOverlay.addHightLightClickListener(listener); + return this; + } + + public HiGuide addGuideViewClickListener(View.OnClickListener listener) { + mDefaultOverlay.addGuideViewClickListener(listener); + return this; + } + + public HiGuide addHightLight(View view, int[] expand, @Shape int shape, Tips tips) { + mDefaultOverlay.addHightLight(view, expand, shape, tips); + return this; + } + + public HiGuide nextOverLay(Overlay overlay) { + mOverlays.add(overlay); + return this; + } + + public void show() { + mIsOpenNext = mOverlays.size() > 1; + + final Overlay overlay = mOverlays.get(0); + mGuideView = new GuideView(mContext, overlay); + mGuideView.setId(R.id.guide_view); + if (mRootView instanceof FrameLayout) { + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + mRootView.addView(mGuideView, mRootView.getChildCount(), lp); + } else { + FrameLayout frameLayout = new FrameLayout(mContext); + ViewGroup parent = (ViewGroup) mRootView.getParent(); + parent.removeView(mRootView); + parent.addView(frameLayout, mRootView.getLayoutParams()); + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + frameLayout.addView(mRootView, lp); + } + mGuideView.addTipsViews(); + mGuideView.setRemoveCallback(new RemoveCallback() { + @Override + public void callback() { + mGuideView = null; + if (mIsOpenNext) { + mOverlays.remove(0); + show(); + } + } + }); + } + + public void dismiss() { + if (mGuideView != null && mGuideView.getParent() instanceof ViewGroup && mGuideView.getParent() == mRootView) { + mRootView.removeView(mGuideView); + } + } + + public GuideView getGuideView() { + if (mGuideView != null) { + return mGuideView; + } + return ((Activity) mContext).findViewById(R.id.guide_view); + } + + public static final int SHAPE_CIRCLE = 0x21; + public static final int SHAPE_OVAL = 0x22; + public static final int SHAPE_RECT = 0x23; + + @IntDef({SHAPE_CIRCLE, SHAPE_OVAL, SHAPE_RECT}) + @interface Shape { + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiLightInfo.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiLightInfo.java new file mode 100644 index 000000000..1af7434ec --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/HiLightInfo.java @@ -0,0 +1,46 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.graphics.Rect; +import android.graphics.RectF; + +import lombok.Data; + +/** + * create by lvzebiao @2019/5/21 + */ +@Data +public class HiLightInfo { + + public final static int ROUND_RECT = 1; + + public final static int NORMAL_RECT = 2; + + private int centerX; + + private int centerY; + + private RectF rectF; + + /** + * 如{x1,y1,x2,y2,x3,y3,x4,y4} + * 左上,右上,右下,左下 + */ + private float[] radis; + + private int ShapeType; + + public float[] getRadis() { + if (radis == null) { + radis = new float[]{}; + } + return radis; + } + + public RectF getRectF() { + if (rectF == null) { + rectF = new RectF(0, 0, 0, 0); + } + return rectF; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/LightConfig.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/LightConfig.java new file mode 100644 index 000000000..b76f68c73 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/LightConfig.java @@ -0,0 +1,49 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.view.View; + +import lombok.Data; + +/** + * 这个类用于保存高亮的信息配置, + * 比如padding扩充多少,圆角信息等 + * create by lvzebiao @2019/5/21 + */ +@Data +public class LightConfig { + //高亮的view 需要等view位置确定后,再传入, + //如果=null则表示不需要高亮 + private View view; + + public LightConfig(View view) { + this.view = view; + } + + //水平padding + private int hPadding; + //垂直padding + private int vPadding; + + private float[] radius; + + private int leftPadding; + + private int rightPadding; + + private int topPadding; + + private int bottomPadding; + + public void setHPadding(int hPadding) { + this.hPadding = hPadding; + this.leftPadding = hPadding; + this.rightPadding = hPadding; + } + + public void setVPadding(int vPadding) { + this.vPadding = vPadding; + this.topPadding = vPadding; + this.bottomPadding = vPadding; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/OverLayer.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/OverLayer.java new file mode 100644 index 000000000..c64e20194 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/OverLayer.java @@ -0,0 +1,54 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.List; + +/** + * create by lvzebiao @2019/5/21 + */ +public class OverLayer { + + public List tipsViewList; + + public boolean needSkip; + + public ViewGroup.LayoutParams knowedParams; + + public ViewGroup.LayoutParams nextParams; + + public List hiLightInfoList; + + public OverLayer() { + tipsViewList = new ArrayList<>(); + hiLightInfoList = new ArrayList<>(); + } + + public OverLayer setNeedSkip(boolean needSkip) { + this.needSkip = needSkip; + return this; + } + + public OverLayer setNextParams(ViewGroup.LayoutParams nextParams) { + this.nextParams = nextParams; + return this; + } + + public OverLayer setKnowedParams(ViewGroup.LayoutParams knowedParams) { + this.knowedParams = knowedParams; + return this; + } + + public OverLayer addTipsView(View tipsView) { + tipsViewList.add(tipsView); + return this; + } + + public OverLayer addHiLightInfo(List hiLightInfoList) { + this.hiLightInfoList = hiLightInfoList; + return this; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/Overlay.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/Overlay.java new file mode 100644 index 000000000..5c1b99a18 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/Overlay.java @@ -0,0 +1,210 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.graphics.Color; +import android.graphics.RectF; +import android.support.annotation.IntDef; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.view.View; + +import java.util.ArrayList; +import java.util.List; + +/** + * Create by Zii at 2018/5/4. + */ +public class Overlay { + + private List mHightLightList; + private int mColorBg; + private boolean mIsTouchDismiss; + private View.OnClickListener mOnClickGuideViewListener; + private View.OnClickListener mOnClickHightLightListener; + private List mHightLightAreas; + + public Overlay() { + mHightLightList = new ArrayList<>(); + mColorBg = Color.parseColor("#80000000"); + mIsTouchDismiss = true; + mHightLightAreas = new ArrayList<>(); + } + + public Overlay touchDismiss(boolean isDismiss) { + mIsTouchDismiss = isDismiss; + return this; + } + + public Overlay bgColor(int color) { + mColorBg = color; + return this; + } + + public Overlay addHightLight(View view, int[] expand, @HiGuide.Shape int shape, Tips tips) { + HightLight hightLight = new HightLight(view, expand, shape, tips); + mHightLightList.add(hightLight); + addHightLightArea(hightLight); + return this; + } + + private void addHightLightArea(HightLight info) { + RectF rectF = info.getRectF(); + if (info.getShape() != HiGuide.SHAPE_CIRCLE) { + mHightLightAreas.add(rectF); + } else { + mHightLightAreas.add(new RectF(rectF.left, rectF.centerY() - info.getRadius(), + rectF.right, rectF.centerY() + info.getRadius())); + } + } + + public Overlay addHightLightClickListener(View.OnClickListener listener) { + mOnClickHightLightListener = listener; + return this; + } + + public boolean isTouchDismiss() { + return mIsTouchDismiss; + } + + public Overlay addGuideViewClickListener(View.OnClickListener listener) { + mOnClickGuideViewListener = listener; + return this; + } + + public List getHightLightAreas() { + return mHightLightAreas; + } + + public List getHightLightList() { + return mHightLightList; + } + + public int getColorBg() { + return mColorBg; + } + + public View.OnClickListener getOnClickGuideViewListener() { + return mOnClickGuideViewListener; + } + + public View.OnClickListener getOnClickHightLightListener() { + return mOnClickHightLightListener; + } + + public static class HightLight { + + private View mView; + private RectF mRectF; + @HiGuide.Shape + private int mShape; + private float mRadius; + private Tips mTips; + + HightLight(View view, int[] expand, @HiGuide.Shape int shape, Tips tips) { + mView = view; + mShape = shape; + + mRectF = new RectF(); + int[] location = new int[2]; + final int[] size = GuideUtils.measureView(mView); + view.getLocationOnScreen(location); + if (expand == null) { + expand = new int[2]; + } + mRectF.left = location[0] - expand[0]; + mRectF.top = location[1] - expand[1]; + mRectF.right = location[0] + size[0] + expand[0]; + mRectF.bottom = location[1] + size[1] + expand[1]; + + mRadius = Math.max((mRectF.right - mRectF.left) / 2, (mRectF.bottom - mRectF.top) / 2); + + mTips = tips; + } + + public Tips getTips() { + return mTips; + } + + public float getRadius() { + return mRadius; + } + + public View getView() { + return mView; + } + + public RectF getRectF() { + return mRectF; + } + + @HiGuide.Shape + public int getShape() { + return mShape; + } + + } + + public static class Tips { + + public static final int TO_RIGHT_OF = 1; + public static final int TO_LEFT_OF = 2; + public static final int ALIGN_TOP = 3; + public static final int ALIGN_BOTTOM = 4; + + @IntDef({TO_RIGHT_OF, TO_LEFT_OF}) + @interface To { + + } + + @IntDef({ALIGN_TOP, ALIGN_BOTTOM}) + @interface Align { + + } + + public static class Margin { + + public int left; + public int top; + public int bottom; + public int right; + + public Margin(int left, int top, int bottom, int right) { + this.left = left; + this.top = top; + this.bottom = bottom; + this.right = right; + } + } + + @LayoutRes + public int layoutRes = -1; + @To + public int to; + @Align + public int align; + public Margin margin; + + public Tips(int layoutRes) { + this.layoutRes = layoutRes; + } + + public Tips(@LayoutRes int layoutRes, @Nullable Margin margin) { + this.layoutRes = layoutRes; + this.margin = margin; + } + + public Tips(@LayoutRes int layoutRes, @To int to, @Align int align) { + this.layoutRes = layoutRes; + this.to = to; + this.align = align; + } + + public Tips(@LayoutRes int layoutRes, @To int to, @Align int align, @Nullable Margin margin) { + this.layoutRes = layoutRes; + this.to = to; + this.align = align; + this.margin = margin; + } + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideHelper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideHelper.java new file mode 100644 index 000000000..f8da68242 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideHelper.java @@ -0,0 +1,768 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.graphics.RectF; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; +import com.yizhuan.xchat_android_core.utils.SharedPreferenceUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import java.util.ArrayList; +import java.util.List; + + +/** + * create by lvzebiao @2019/5/21 + */ +public class TuTuGuideHelper { + + /** + * 是否需要显示礼物面板的引导 + */ + public final static String KEY_GUIDE_GIFT_DIALOG = "key_guide_gift_dialog"; + + /** + * 是否需要显示房间的引导 + */ + public final static String KEY_GUIDE_FIRST_ROOM = "key_guide_first_room"; + + /** + * 房间首页tab引导 + */ + public final static String KEY_GUIDE_MAIN_TAB = "key_guide_main_tab"; + + /** + * 消息tab引导 + */ + public final static String KEY_GUIDE_MSG_TAB = "key_guide_msg_tab"; + + /** + * 我的tab引导 + */ + public final static String KEY_GUIDE_ME_TAB = "key_guide_me_tab"; + public final static String KEY_GUIDE_CHATTER_BOX = "key_guide_chatter_box"; + + /** + * 是否需要显示声音匹配的引导 + */ + public final static String KEY_GUIDE_VOICE_MATCH = "key_guide_voice_match"; + + /** + * 是否需要显示声音匹配私聊页面的打招呼指引 + */ + public final static String KEY_GUIDE_VOICE_MATCH_SAY_HI = "key_guide_voice_match_say_hi"; + /** + * 首页女神页面的引导 + */ + public final static String KEY_GUIDE_MAIN_HOME = "key_guide_me_tab"; + /** + * 小世界首页引导 + */ + public final static String KEY_GUIDE_MINI_WORLD_MAIN = "key_guide_mini_world_main"; + /** + * 小世界客态页引导-未加入世界 + */ + public final static String KEY_GUIDE_MINI_WORLD_DETAIL_GUEST = "key_guide_mini_world_detail_guest"; + /** + * 小世界客态页引导-已加入世界 + */ + public final static String KEY_GUIDE_MINI_WORLD_DETAIL_MEMBER = "key_guide_mini_world_detail_member"; + + private ViewGroup mRootView; + + private TuTuGuideView guideParent; + + private Context context; + + public TuTuGuideHelper(Context context) { + this.context = context; + if (!ActivityUtil.isValidContext(context)) { + return; + } + View contentView = ((Activity) context).findViewById(android.R.id.content); + if (contentView instanceof ViewGroup) { + mRootView = (ViewGroup) contentView; + } + } + + public TuTuGuideHelper(Context context, Dialog dialog) { + this.context = context; + if (!ActivityUtil.isValidContext(context)) { + return; + } + if (dialog == null || dialog.getWindow() == null) { + return; + } + View contentView = dialog.getWindow().getDecorView(); + if (contentView instanceof ViewGroup) { + mRootView = (ViewGroup) contentView; + } + } + + /** + * 创建高亮引导的通用入口 + */ + public void createHiGuide(IGuideLayoutListener listener) { + createHiGuide(listener, null); + } + + public void createHiGuide(IGuideLayoutListener listener, TuTuGuideView.IGuideShowFinishListener showFinishListener) { + try { + if (mRootView == null) { + return; + } + guideParent = new TuTuGuideView(context); + mRootView.addView(guideParent, createLayoutParams()); + mRootView.post(() -> { + try { + if (listener == null) { + return; + } + List list = listener.onCreateList(); + if (ListUtils.isListEmpty(list)) { + return; + } + for (OverLayer overLayer : list) { + guideParent.addOverLayer(overLayer); + } + start(); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + if (showFinishListener != null) { + guideParent.setShowFinishListener(showFinishListener); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + public interface IGuideLayoutListener { + List onCreateList(); + } + + public List createMainTabOverLayer(View top) { + List list = new ArrayList<>(); + if (top == null) { + return list; + } + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig = new LightConfig(top); + int dp_24 = UIUtil.dip2px(context, 24); + lightConfig.setRadius(new float[]{0, 0, dp_24, dp_24, dp_24, dp_24, 0, 0}); + lightConfig.setHPadding(UIUtil.dip2px(context, 5)); + HiLightInfo info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_main_top_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 278.6f), UIUtil.dip2px(context, 92.6f) + ); + params.leftMargin = UIUtil.dip2px(context, 30.6f); + params.topMargin = UIUtil.dip2px(context, 20) + (int) info.getRectF().bottom; + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.leftMargin = UIUtil.dip2px(context, 252); + params.topMargin = UIUtil.dip2px(context, 139) + (int) info.getRectF().bottom; + overLayer.setKnowedParams(params); + + return list; + } + + public List createMeTabOverLayer(View radishItem) { + List list = new ArrayList<>(); + if (radishItem == null) { + return list; + } + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig = new LightConfig(radishItem); + int dp_9 = UIUtil.dip2px(context, 9); + lightConfig.setRadius(new float[]{dp_9, dp_9, dp_9, dp_9, dp_9, dp_9, dp_9, dp_9}); + lightConfig.setHPadding(-UIUtil.dip2px(context, 12)); + HiLightInfo info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_me_enter_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 295.3f), UIUtil.dip2px(context, 92) + ); + params.leftMargin = UIUtil.dip2px(context, 30.3f); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 92) - UIUtil.dip2px(context, 20); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.leftMargin = UIUtil.dip2px(context, 259); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 140) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + + return list; + } + + + public List createMsgTabOverLayer() { + List list = new ArrayList<>(); + //第一层 + OverLayer overLayer = new OverLayer(); + View view = View.inflate(context, R.layout.home_guide_for_enter, null); + view.setLayoutParams(createLayoutParams()); + ImageView iv_enter_text = view.findViewById(R.id.iv_enter_text); + if (iv_enter_text != null) { + iv_enter_text.setImageResource(R.drawable.icon_guide_msg_enter_tips); + } + overLayer.addTipsView(view); + + FrameLayout.LayoutParams params = createKnowedParams(context); + params.gravity = Gravity.BOTTOM | Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 52f); + params.bottomMargin = UIUtil.dip2px(context, 99); + overLayer.setKnowedParams(params); + list.add(overLayer); + + return list; + } + + + public List createRoomGuide(View micView, View sendGift) { + List list = new ArrayList<>(); + if (micView == null) { + return list; + } + //8号麦位高亮 + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig; + lightConfig = new LightConfig(micView); + int radiu = UIUtil.dip2px(context, 1) + micView.getWidth() / 2; + lightConfig.setRadius(new float[]{radiu, radiu, radiu, radiu, radiu, radiu, radiu, radiu}); + lightConfig.setHPadding(UIUtil.dip2px(context, 1)); + lightConfig.setVPadding(UIUtil.dip2px(context, 1)); + HiLightInfo info; + info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList; + hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView; + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_to_up_mic_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 209), UIUtil.dip2px(context, 66) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 51); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 14); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createNextParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 51); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 101); + overLayer.setNextParams(params); + + overLayer.setNeedSkip(true); + //送礼按钮高亮 + if (sendGift == null) { + return list; + } + overLayer = new OverLayer(); + list.add(overLayer); + + lightConfig = new LightConfig(sendGift); + radiu = UIUtil.dip2px(context, 24); + lightConfig.setRadius(new float[]{radiu, radiu, 0, 0, 0, 0, radiu, radiu}); + lightConfig.setRightPadding(UIUtil.dip2px(context, 15)); + lightConfig.setLeftPadding(UIUtil.dip2px(context, 6.5f)); + lightConfig.setVPadding(UIUtil.dip2px(context, 6.5f)); + info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_room_send_gift_tips); + params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 156), UIUtil.dip2px(context, 66) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 36); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 66) - UIUtil.dip2px(context, 21); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 36); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 107) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + + return list; + } + + public List createVoiceMatchGuide(View likeButtonView, View myVoiceView) { + List list = new ArrayList<>(); + if (likeButtonView == null) { + return list; + } + // 喜欢按钮 高亮 + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig; + lightConfig = new LightConfig(likeButtonView); + int radius = UIUtil.dip2px(context, 1) + likeButtonView.getWidth() / 2; + lightConfig.setRadius(new float[]{radius, radius, radius, radius, radius, radius, radius, radius}); + lightConfig.setHPadding(UIUtil.dip2px(context, 1)); + lightConfig.setVPadding(UIUtil.dip2px(context, 1)); + HiLightInfo info; + info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList; + hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView; + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_to_like_voice_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 216), UIUtil.dip2px(context, 96) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 21) - UIUtil.dip2px(context, 96); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createNextParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 138) - UIUtil.dip2px(context, 34); + overLayer.setNextParams(params); + + overLayer.setNeedSkip(true); + // 我的声音入口 高亮 + if (myVoiceView == null) { + return list; + } + overLayer = new OverLayer(); + list.add(overLayer); + + lightConfig = new LightConfig(myVoiceView); + radius = UIUtil.dip2px(context, 25); + lightConfig.setRadius(new float[]{radius, radius, 0, 0, 0, 0, radius, radius}); + float leftPadding = myVoiceView.getWidth() / 3 * 1.8f; + lightConfig.setLeftPadding((int) -leftPadding); + info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_to_record_voice_tips); + params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 190), UIUtil.dip2px(context, 97) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 36); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 21); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 36); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 139); + overLayer.setKnowedParams(params); + + return list; + } + + public List createMiniWorldGuestPageGuestGuide(View addWorldLayout) { + List list = new ArrayList<>(); + if (addWorldLayout == null) { + return list; + } + // 底部布局 高亮 + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig; + lightConfig = new LightConfig(addWorldLayout); + int radius = UIUtil.dip2px(context, 5) + addWorldLayout.getWidth() / 2; + lightConfig.setRadius(new float[]{radius, radius, radius, radius, radius, radius, radius, radius}); + lightConfig.setHPadding(UIUtil.dip2px(context, 5)); + lightConfig.setVPadding(UIUtil.dip2px(context, 5)); + HiLightInfo info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView; + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_to_add_world_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 277), UIUtil.dip2px(context, 115) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 25) - UIUtil.dip2px(context, 115); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 45) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + return list; + } + + public List createMiniWorldGuestPageMemberGuide(View memberChatLayout) { + List list = new ArrayList<>(); + if (memberChatLayout == null) { + return list; + } + // 底部布局 高亮 + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig; + lightConfig = new LightConfig(memberChatLayout); + int radius = UIUtil.dip2px(context, 5) + memberChatLayout.getWidth() / 2; + lightConfig.setRadius(new float[]{radius, radius, radius, radius, radius, radius, radius, radius}); + lightConfig.setHPadding(UIUtil.dip2px(context, 30)); + lightConfig.setVPadding(UIUtil.dip2px(context, 5)); + HiLightInfo info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView; + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_to_chat_in_world_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 278), UIUtil.dip2px(context, 114) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 25) - UIUtil.dip2px(context, 114); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 60); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 45) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + return list; + } + + + public List createGiftDialogOverLayer(View avatar) { + List list = new ArrayList<>(); + if (avatar == null) { + return list; + } + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig = new LightConfig(avatar); + int dp_9 = UIUtil.dip2px(context, 9); + lightConfig.setRadius(new float[]{dp_9, dp_9, dp_9, dp_9, dp_9, dp_9, dp_9, dp_9}); + lightConfig.setVPadding(UIUtil.dip2px(context, 8.5f)); + HiLightInfo info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + List hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_giftdialog_tips); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 315), UIUtil.dip2px(context, 66) + ); + params.leftMargin = UIUtil.dip2px(context, 31); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 66) - UIUtil.dip2px(context, 21); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.leftMargin = UIUtil.dip2px(context, 272); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 107) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + + return list; + } + + /** + * 高亮首页 + * + * @param views banner + * @param view item + * @return + */ + public List createMainHomeGuide(List views, View view) { + List list = new ArrayList<>(); + + OverLayer overLayer = new OverLayer(); + list.add(overLayer); + List hiLightInfoList = new ArrayList<>(); + for (View v : views) { + LightConfig lightConfig; + lightConfig = new LightConfig(v); + HiLightInfo info; + info = calcHiLightInfo(lightConfig); + if (info == null) { + continue; + } + hiLightInfoList.add(info); + + } + HiLightInfo info = hiLightInfoList.get(0); + + + overLayer.addHiLightInfo(hiLightInfoList); + + ImageView imageView; + //文案 + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_main_home_copywriting_1); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 278.6f), UIUtil.dip2px(context, 92.6f) + ); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 51); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 14); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); +// + //下面的logo + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_logo_left_center); + params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT + ); + params.gravity = Gravity.LEFT | Gravity.BOTTOM; +// params.rightMargin = UIUtil.dip2px(context, 51); +// params.topMargin = (int) info.getRectF().top; + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createNextParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 51); + params.topMargin = (int) info.getRectF().bottom + UIUtil.dip2px(context, 101); + overLayer.setNextParams(params); + + overLayer.setNeedSkip(true); +// + overLayer = new OverLayer(); + list.add(overLayer); + + LightConfig lightConfig = new LightConfig(view); + int radiu = UIUtil.dip2px(context, 24); + lightConfig.setRadius(new float[]{radiu, radiu, radiu, radiu, radiu, radiu, radiu, radiu}); + lightConfig.setRightPadding(UIUtil.dip2px(context, 15)); + lightConfig.setLeftPadding(UIUtil.dip2px(context, 6.5f)); + lightConfig.setVPadding(UIUtil.dip2px(context, 6.5f)); + info = calcHiLightInfo(lightConfig); + if (info == null) { + return list; + } + hiLightInfoList = new ArrayList<>(); + hiLightInfoList.add(info); + overLayer.addHiLightInfo(hiLightInfoList); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_main_home_copywriting_2); + params = new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 278.6f), UIUtil.dip2px(context, 92.6f) + ); + params.gravity = Gravity.LEFT; + params.leftMargin = UIUtil.dip2px(context, 54); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 66) - UIUtil.dip2px(context, 21) - UIUtil.dip2px(context, 21); + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + imageView.setImageResource(R.drawable.icon_guide_logo_right_bottom); + params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT + ); + params.gravity = Gravity.END | Gravity.BOTTOM; +// + imageView.setLayoutParams(params); + overLayer.addTipsView(imageView); + + params = createKnowedParams(context); + params.gravity = Gravity.END; + params.rightMargin = UIUtil.dip2px(context, 36); + params.topMargin = (int) info.getRectF().top - UIUtil.dip2px(context, 107) - UIUtil.dip2px(context, 34); + overLayer.setKnowedParams(params); + + return list; + } + + + /** + * 根据需要的配置,计算好高亮的区域信息 + * + * @param lightConfig + * @return + */ + private HiLightInfo calcHiLightInfo(LightConfig lightConfig) { + if (lightConfig == null || lightConfig.getView() == null) { + return null; + } + View hiLightView = lightConfig.getView(); + int[] parentLoca = new int[2]; + guideParent.getLocationOnScreen(parentLoca); + int[] lightLoca = new int[2]; + hiLightView.getLocationOnScreen(lightLoca); + HiLightInfo info = new HiLightInfo(); + int top = lightLoca[1] - parentLoca[1] - lightConfig.getTopPadding(); + int left = lightLoca[0] - parentLoca[0] - lightConfig.getLeftPadding(); + int bottom = top + hiLightView.getHeight() + lightConfig.getTopPadding() + lightConfig.getBottomPadding(); + int right = left + lightConfig.getLeftPadding() + lightConfig.getRightPadding() + hiLightView.getWidth(); + RectF rectF = new RectF(left, top, right, bottom); + info.setRectF(rectF); + if (lightConfig.getRadius() != null) { + info.setRadis(lightConfig.getRadius()); + info.setShapeType(HiLightInfo.ROUND_RECT); + } else { + info.setShapeType(HiLightInfo.NORMAL_RECT); + } + return info; + } + + public List createDiceOverLayer() { + List list = new ArrayList<>(); + //第一层 + OverLayer overLayer = new OverLayer(); + View view = View.inflate(context, R.layout.layout_dice_guide, null); + view.setLayoutParams(createLayoutParams()); + overLayer.addTipsView(view); + + list.add(overLayer); + + return list; + } + + public static ViewGroup.LayoutParams createLayoutParams() { + return new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + } + + public static FrameLayout.LayoutParams createSkipParams(Context context) { + return new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 46), UIUtil.dip2px(context, 25) + ); + } + + public static FrameLayout.LayoutParams createKnowedParams(Context context) { + return new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 76), UIUtil.dip2px(context, 34) + ); + } + + public static FrameLayout.LayoutParams createNextParams(Context context) { + return new FrameLayout.LayoutParams( + UIUtil.dip2px(context, 76), UIUtil.dip2px(context, 34) + ); + } + + public void start() { + if (mRootView == null || guideParent == null) { + return; + } + guideParent.next(); + } + + + public static boolean isNeedHiGuide(String type) { + boolean result = true; + if (TextUtils.isEmpty(type)) { + return false; + } + Boolean cache = (Boolean) SharedPreferenceUtils.get(type, true); + if (cache != null) { + result = cache; + } +// return result; + return false;// 20190727 所有新手引导去掉 + } + + public static void setNoNeedHiGuide(String type) { + if (TextUtils.isEmpty(type)) { + return; + } + SharedPreferenceUtils.put(type, false); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideView.java new file mode 100644 index 000000000..f663cf7dc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/higuide/TuTuGuideView.java @@ -0,0 +1,169 @@ +package com.yizhuan.erban.ui.widget.higuide; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.support.annotation.NonNull; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * create by lvzebiao @2019/5/21 + */ +public class TuTuGuideView extends FrameLayout { + + private int currentPage; + + private Path lightPath; + + private Path bgPath; + + private Paint paint; + + private Context context; + + public TuTuGuideView(@NonNull Context context) { + super(context); + this.context = context; + lightPath = new Path(); + lightPath.addRect(0, 0, 0, 0, Path.Direction.CW); + + bgPath = new Path(); + //init Paint + paint = new Paint(); + paint.setColor(context.getResources().getColor(R.color.black_transparent_65)); + paint.setAntiAlias(true); + paint.setDither(true); + setWillNotDraw(false); + + lightList = new ArrayList<>(); + layerList = new ArrayList<>(); + setOnClickListener(v -> next()); + + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + bgPath.reset(); + bgPath.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW); + + //添加高亮 + if (lightList != null) { + for (HiLightInfo info : lightList) { + lightPath.reset(); + if (info.getShapeType() == HiLightInfo.ROUND_RECT) { + lightPath.addRoundRect(info.getRectF(), info.getRadis(), Path.Direction.CW); + } else { + lightPath.addRect(info.getRectF(), Path.Direction.CW); + } + bgPath.op(lightPath, Path.Op.XOR); + } + } + canvas.drawPath(bgPath, paint); + } + + public void addOverLayer(OverLayer overLayer) { + layerList.add(overLayer); + } + + public void remove() { + ViewGroup parent = (ViewGroup) getParent(); + if (parent != null) { + parent.removeView(TuTuGuideView.this); + } + } + + public void show() { + invalidate(); + } + + private List lightList; + + private List layerList; + + public void next() { + removeAllViews(); + if (currentPage < layerList.size()) { + OverLayer overLayer = layerList.get(currentPage); + + lightList = overLayer.hiLightInfoList; + for (View index : overLayer.tipsViewList) { + addView(index); + } + if (overLayer.needSkip) { + TextView textView = new TextView(context); + textView.setText(R.string.skip_guide); + int padding = UIUtil.dip2px(context, 5); + textView.setPadding(padding, padding, padding, padding); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13); + textView.setTextColor(context.getResources().getColor(R.color.white_transparent_30)); + textView.setOnClickListener(v -> { + remove();// 跳过 + if (showFinishListener != null) { + showFinishListener.onSkip(); + } + }); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; + params.bottomMargin = UIUtil.dip2px(context, 60); + addView(textView, params); + } + if (overLayer.knowedParams != null) { + ImageView imageView = new ImageView(context); + imageView.setImageResource(R.drawable.icon_guide_knowed); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + addView(imageView, overLayer.knowedParams); + } + if (overLayer.nextParams != null) { + ImageView imageView = new ImageView(context); + imageView.setImageResource(R.drawable.icon_guide_next); + imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + addView(imageView, overLayer.nextParams); + } + invalidate(); + currentPage++; + } else { + remove();// 全部展示完毕 + if (showFinishListener != null) { + showFinishListener.onGuideFinish(); + } + } + + } + + private IGuideShowFinishListener showFinishListener; + + public void setShowFinishListener(IGuideShowFinishListener showFinishListener) { + this.showFinishListener = showFinishListener; + } + + public interface IGuideShowFinishListener { + /** + * 跳过 + */ + void onSkip(); + + /** + * 引导图已经全部展示完毕 + */ + default void onGuideFinish() { + + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/interfacex/MicListItem.java b/app/src/main/java/com/yizhuan/erban/ui/widget/interfacex/MicListItem.java new file mode 100644 index 000000000..a8d68c389 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/interfacex/MicListItem.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.ui.widget.interfacex; + +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +/** + * Created by zhouxiangfeng on 2017/6/15. + */ + +public interface MicListItem { + void initiate(UserInfo userInfo); + + UserInfo getUserInfo(); + + void setRoomOwner(boolean isOwner); + + void setSpeeking(boolean isSpeeking); + + void setAuctionRole(boolean isAuction); + + boolean isAuction(); + + boolean isOwner(); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/FragmentContainerHelper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/FragmentContainerHelper.java new file mode 100644 index 000000000..f71e10ca9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/FragmentContainerHelper.java @@ -0,0 +1,163 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.TargetApi; +import android.os.Build; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.ArrayList; +import java.util.List; + + +/** + * 使得MagicIndicator在FragmentContainer中使用 + * Created by hackware on 2016/9/4. + */ + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class FragmentContainerHelper { + private List mMagicIndicators = new ArrayList(); + private ValueAnimator mScrollAnimator; + private int mLastSelectedIndex; + private int mDuration = 150; + private Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); + + private Animator.AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE); + mScrollAnimator = null; + } + }; + + private ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float positionOffsetSum = (Float) animation.getAnimatedValue(); + int position = (int) positionOffsetSum; + float positionOffset = positionOffsetSum - position; + if (positionOffsetSum < 0) { + position = position - 1; + positionOffset = 1.0f + positionOffset; + } + dispatchPageScrolled(position, positionOffset, 0); + } + }; + + public FragmentContainerHelper() { + } + + public FragmentContainerHelper(MagicIndicator magicIndicator) { + mMagicIndicators.add(magicIndicator); + } + + /** + * IPagerIndicator支持弹性效果的辅助方法 + * + * @param positionDataList + * @param index + * @return + */ + public static PositionData getImitativePositionData(List positionDataList, int index) { + if (index >= 0 && index <= positionDataList.size() - 1) { // 越界后,返回假的PositionData + return positionDataList.get(index); + } else { + PositionData result = new PositionData(); + PositionData referenceData; + int offset; + if (index < 0) { + offset = index; + referenceData = positionDataList.get(0); + } else { + offset = index - positionDataList.size() + 1; + referenceData = positionDataList.get(positionDataList.size() - 1); + } + result.mLeft = referenceData.mLeft + offset * referenceData.width(); + result.mTop = referenceData.mTop; + result.mRight = referenceData.mRight + offset * referenceData.width(); + result.mBottom = referenceData.mBottom; + result.mContentLeft = referenceData.mContentLeft + offset * referenceData.width(); + result.mContentTop = referenceData.mContentTop; + result.mContentRight = referenceData.mContentRight + offset * referenceData.width(); + result.mContentBottom = referenceData.mContentBottom; + return result; + } + } + + public void handlePageSelected(int selectedIndex) { + handlePageSelected(selectedIndex, true); + } + + public void handlePageSelected(int selectedIndex, boolean smooth) { + if (mLastSelectedIndex == selectedIndex) { + return; + } + if (smooth) { + if (mScrollAnimator == null || !mScrollAnimator.isRunning()) { + dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_SETTLING); + } + dispatchPageSelected(selectedIndex); + float currentPositionOffsetSum = mLastSelectedIndex; + if (mScrollAnimator != null) { + currentPositionOffsetSum = (Float) mScrollAnimator.getAnimatedValue(); + mScrollAnimator.cancel(); + mScrollAnimator = null; + } + mScrollAnimator = new ValueAnimator(); + mScrollAnimator.setFloatValues(currentPositionOffsetSum, selectedIndex); // position = selectedIndex, positionOffset = 0.0f + mScrollAnimator.addUpdateListener(mAnimatorUpdateListener); + mScrollAnimator.addListener(mAnimatorListener); + mScrollAnimator.setInterpolator(mInterpolator); + mScrollAnimator.setDuration(mDuration); + mScrollAnimator.start(); + } else { + dispatchPageSelected(selectedIndex); + if (mScrollAnimator != null && mScrollAnimator.isRunning()) { + dispatchPageScrolled(mLastSelectedIndex, 0.0f, 0); + } + dispatchPageScrollStateChanged(ScrollState.SCROLL_STATE_IDLE); + dispatchPageScrolled(selectedIndex, 0.0f, 0); + } + mLastSelectedIndex = selectedIndex; + } + + public void setDuration(int duration) { + mDuration = duration; + } + + public void setInterpolator(Interpolator interpolator) { + if (interpolator == null) { + mInterpolator = new AccelerateDecelerateInterpolator(); + } else { + mInterpolator = interpolator; + } + } + + public void attachMagicIndicator(MagicIndicator magicIndicator) { + mMagicIndicators.add(magicIndicator); + } + + private void dispatchPageSelected(int pageIndex) { + for (MagicIndicator magicIndicator : mMagicIndicators) { + magicIndicator.onPageSelected(pageIndex); + } + } + + private void dispatchPageScrollStateChanged(int state) { + for (MagicIndicator magicIndicator : mMagicIndicators) { + magicIndicator.onPageScrollStateChanged(state); + } + } + + private void dispatchPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + for (MagicIndicator magicIndicator : mMagicIndicators) { + magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/GiftIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/GiftIndicator.java new file mode 100644 index 000000000..6a95b7eb0 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/GiftIndicator.java @@ -0,0 +1,121 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.xchat_android_core.gift.bean.GiftTab; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.reactivex.Observable; +import lombok.Getter; + +/** + *

公共多个滑动tab样式

+ * + * @author Administrator + * @date 2017/11/15 + */ +public class GiftIndicator extends LinearLayout { + + /**普通礼物*/ + public static final int TYPE_NORMAL = 0; + /**魔法礼物*/ + public static final int TYPE_MAGIC = 1; + /**贵族礼物*/ + public static final int TYPE_NOBLE = 2; + /**背包礼物*/ + public static final int TYPE_KNAP = 3; + /** + * 萝卜礼物 + */ + public static final int TYPE_RADISH = 4; + + private Map map = new HashMap<>(); + + public GiftIndicator(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + setOrientation(LinearLayout.HORIZONTAL); + } + + private List tabList = new ArrayList<>(); + + @Getter + private int currrentType = TYPE_NORMAL; + + private int mFalseColor; + private int mTrueColor; + + public void initTab(List list, int falseColor, int trueColor) { + for (int i = 0; i < list.size(); i++) { + GiftTab tab = list.get(i); + View view = inflate(GiftIndicator.this.getContext(), R.layout.layout_gift_indicator_item, null); + tab.setItemView(view); + addView(view, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + UIUtil.dip2px(getContext(), 31))); + TextView tvTitle = view.findViewById(R.id.tv_title); + tvTitle.setText(tab.getUnSelectedTitle()); + } + tabList = list; + mFalseColor = falseColor; + mTrueColor = trueColor; + setPosition(TYPE_NORMAL); + } + + public Observable addClick() { + return Observable.create(emitter -> { + for (int i = 0; i < tabList.size(); i++) { + final GiftTab index = tabList.get(i); + index.getItemView().setOnClickListener(v -> { + emitter.onNext(index.getType()); + setPosition(index.getType()); + }); + } + }); + } + + public void setPosition(int type) { + currrentType = type; + for (int i = 0; i < tabList.size(); i++) { + GiftTab tab = tabList.get(i); + View view = tab.getItemView(); + TextView tvTitle = view.findViewById(R.id.tv_title); + if (tab.getType() == currrentType) { + tvTitle.setTextColor(mTrueColor); + tvTitle.setText(tab.getSelectedTitle()); + } else { + tvTitle.setTextColor(mFalseColor); + tvTitle.setText(tab.getUnSelectedTitle()); + } + } + } + + public void hidePosition(int type) { + for (GiftTab tab : tabList) { + if (tab.getType() == type) { + tab.getItemView().setVisibility(GONE); + break; + } + } + } + + public void showPosition(int type) { + for (GiftTab tab : tabList) { + if (tab.getType() == type) { + tab.getItemView().setVisibility(VISIBLE); + break; + } + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/MagicIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/MagicIndicator.java new file mode 100644 index 000000000..4a678c511 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/MagicIndicator.java @@ -0,0 +1,63 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.abs.IPagerNavigator; + +/** + * 整个框架的入口,核心 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class MagicIndicator extends FrameLayout { + private IPagerNavigator mNavigator; + + public MagicIndicator(Context context) { + super(context); + } + + public MagicIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mNavigator != null) { + mNavigator.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + } + + public void onPageSelected(int position) { + if (mNavigator != null) { + mNavigator.onPageSelected(position); + } + } + + public void onPageScrollStateChanged(int state) { + if (mNavigator != null) { + mNavigator.onPageScrollStateChanged(state); + } + } + + public IPagerNavigator getNavigator() { + return mNavigator; + } + + public void setNavigator(IPagerNavigator navigator) { + if (mNavigator == navigator) { + return; + } + if (mNavigator != null) { + mNavigator.onDetachFromMagicIndicator(); + } + mNavigator = navigator; + removeAllViews(); + if (mNavigator instanceof View) { + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + addView((View) mNavigator, lp); + mNavigator.onAttachToMagicIndicator(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/NavigatorHelper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/NavigatorHelper.java new file mode 100644 index 000000000..a0e3f6d0f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/NavigatorHelper.java @@ -0,0 +1,171 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +import android.util.SparseArray; +import android.util.SparseBooleanArray; + + +/** + * 方便扩展IPagerNavigator的帮助类,将ViewPager的3个回调方法转换成 + * onSelected、onDeselected、onEnter等回调,方便扩展 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class NavigatorHelper { + private SparseBooleanArray mDeselectedItems = new SparseBooleanArray(); + private SparseArray mLeavedPercents = new SparseArray(); + + private int mTotalCount; + private int mCurrentIndex; + private int mLastIndex; + private float mLastPositionOffsetSum; + private int mScrollState; + + private boolean mSkimOver; + private NavigatorHelper.OnNavigatorScrollListener mNavigatorScrollListener; + + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + float currentPositionOffsetSum = position + positionOffset; + boolean leftToRight = false; + if (mLastPositionOffsetSum <= currentPositionOffsetSum) { + leftToRight = true; + } + if (mScrollState != ScrollState.SCROLL_STATE_IDLE) { + if (currentPositionOffsetSum == mLastPositionOffsetSum) { + return; + } + int nextPosition = position + 1; + boolean normalDispatch = true; + if (positionOffset == 0.0f) { + if (leftToRight) { + nextPosition = position - 1; + normalDispatch = false; + } + } + for (int i = 0; i < mTotalCount; i++) { + if (i == position || i == nextPosition) { + continue; + } + Float leavedPercent = mLeavedPercents.get(i, 0.0f); + if (leavedPercent != 1.0f) { + dispatchOnLeave(i, 1.0f, leftToRight, true); + } + } + if (normalDispatch) { + if (leftToRight) { + dispatchOnLeave(position, positionOffset, true, false); + dispatchOnEnter(nextPosition, positionOffset, true, false); + } else { + dispatchOnLeave(nextPosition, 1.0f - positionOffset, false, false); + dispatchOnEnter(position, 1.0f - positionOffset, false, false); + } + } else { + dispatchOnLeave(nextPosition, 1.0f - positionOffset, true, false); + dispatchOnEnter(position, 1.0f - positionOffset, true, false); + } + } else { + for (int i = 0; i < mTotalCount; i++) { + if (i == mCurrentIndex) { + continue; + } + boolean deselected = mDeselectedItems.get(i); + if (!deselected) { + dispatchOnDeselected(i); + } + Float leavedPercent = mLeavedPercents.get(i, 0.0f); + if (leavedPercent != 1.0f) { + dispatchOnLeave(i, 1.0f, false, true); + } + } + dispatchOnEnter(mCurrentIndex, 1.0f, false, true); + dispatchOnSelected(mCurrentIndex); + } + mLastPositionOffsetSum = currentPositionOffsetSum; + } + + private void dispatchOnEnter(int index, float enterPercent, boolean leftToRight, boolean force) { + if (mSkimOver || index == mCurrentIndex || mScrollState == ScrollState.SCROLL_STATE_DRAGGING || force) { + if (mNavigatorScrollListener != null) { + mNavigatorScrollListener.onEnter(index, mTotalCount, enterPercent, leftToRight); + } + mLeavedPercents.put(index, 1.0f - enterPercent); + } + } + + private void dispatchOnLeave(int index, float leavePercent, boolean leftToRight, boolean force) { + if (mSkimOver || index == mLastIndex || mScrollState == ScrollState.SCROLL_STATE_DRAGGING || ((index == mCurrentIndex - 1 || index == mCurrentIndex + 1) && mLeavedPercents.get(index, 0.0f) != 1.0f) || force) { + if (mNavigatorScrollListener != null) { + mNavigatorScrollListener.onLeave(index, mTotalCount, leavePercent, leftToRight); + } + mLeavedPercents.put(index, leavePercent); + } + } + + private void dispatchOnSelected(int index) { + if (mNavigatorScrollListener != null) { + mNavigatorScrollListener.onSelected(index, mTotalCount); + } + mDeselectedItems.put(index, false); + } + + private void dispatchOnDeselected(int index) { + if (mNavigatorScrollListener != null) { + mNavigatorScrollListener.onDeselected(index, mTotalCount); + } + mDeselectedItems.put(index, true); + } + + public void onPageSelected(int position) { + mLastIndex = mCurrentIndex; + mCurrentIndex = position; + dispatchOnSelected(mCurrentIndex); + for (int i = 0; i < mTotalCount; i++) { + if (i == mCurrentIndex) { + continue; + } + boolean deselected = mDeselectedItems.get(i); + if (!deselected) { + dispatchOnDeselected(i); + } + } + } + + public void onPageScrollStateChanged(int state) { + mScrollState = state; + } + + public void setNavigatorScrollListener(NavigatorHelper.OnNavigatorScrollListener navigatorScrollListener) { + mNavigatorScrollListener = navigatorScrollListener; + } + + public void setSkimOver(boolean skimOver) { + mSkimOver = skimOver; + } + + public int getTotalCount() { + return mTotalCount; + } + + public void setTotalCount(int totalCount) { + mTotalCount = totalCount; + mDeselectedItems.clear(); + mLeavedPercents.clear(); + } + + public int getCurrentIndex() { + return mCurrentIndex; + } + + public int getScrollState() { + return mScrollState; + } + + public interface OnNavigatorScrollListener { + void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight); + + void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight); + + void onSelected(int index, int totalCount); + + void onDeselected(int index, int totalCount); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ScrollState.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ScrollState.java new file mode 100644 index 000000000..72ec12748 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ScrollState.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +/** + * 自定义滚动状态,消除对ViewPager的依赖 + * Created by hackware on 2016/8/27. + */ + +public interface ScrollState { + int SCROLL_STATE_IDLE = 0; + int SCROLL_STATE_DRAGGING = 1; + int SCROLL_STATE_SETTLING = 2; +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ViewPagerHelper.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ViewPagerHelper.java new file mode 100644 index 000000000..5bb7a4c14 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ViewPagerHelper.java @@ -0,0 +1,31 @@ +package com.yizhuan.erban.ui.widget.magicindicator; + +import android.support.v4.view.ViewPager; + + +/** + * 简化和ViewPager绑定 + * Created by hackware on 2016/8/17. + */ + +public class ViewPagerHelper { + public static void bind(final MagicIndicator magicIndicator, ViewPager viewPager) { + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + + @Override + public void onPageSelected(int position) { + magicIndicator.onPageSelected(position); + } + + @Override + public void onPageScrollStateChanged(int state) { + magicIndicator.onPageScrollStateChanged(state); + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/abs/IPagerNavigator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/abs/IPagerNavigator.java new file mode 100644 index 000000000..589094c61 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/abs/IPagerNavigator.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.ui.widget.magicindicator.abs; + +/** + * 抽象的ViewPager导航器 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public interface IPagerNavigator { + + ///////////////////////// ViewPager的3个回调 + void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + void onPageSelected(int position); + + void onPageScrollStateChanged(int state); + ///////////////////////// + + /** + * 当IPagerNavigator被添加到MagicIndicator时调用 + */ + void onAttachToMagicIndicator(); + + /** + * 当IPagerNavigator从MagicIndicator上移除时调用 + */ + void onDetachFromMagicIndicator(); + + /** + * ViewPager内容改变时需要先调用此方法,自定义的IPagerNavigator应当遵守此约定 + */ + void notifyDataSetChanged(); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/ArgbEvaluatorHolder.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/ArgbEvaluatorHolder.java new file mode 100644 index 000000000..51658cd09 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/ArgbEvaluatorHolder.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins; + + +/** + * 实现颜色渐变,考虑到兼容性,不使用内置的ArgbEvaluator + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class ArgbEvaluatorHolder { + public static int eval(float fraction, int startValue, int endValue) { + int startA = (startValue >> 24) & 0xff; + int startR = (startValue >> 16) & 0xff; + int startG = (startValue >> 8) & 0xff; + int startB = startValue & 0xff; + + int endA = (endValue >> 24) & 0xff; + int endR = (endValue >> 16) & 0xff; + int endG = (endValue >> 8) & 0xff; + int endB = endValue & 0xff; + + int currentA = (startA + (int) (fraction * (endA - startA))) << 24; + int currentR = (startR + (int) (fraction * (endR - startR))) << 16; + int currentG = (startG + (int) (fraction * (endG - startG))) << 8; + int currentB = startB + (int) (fraction * (endB - startB)); + + return currentA | currentR | currentG | currentB; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/UIUtil.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/UIUtil.java new file mode 100644 index 000000000..dcdc925f5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/UIUtil.java @@ -0,0 +1,23 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins; + +import android.content.Context; + +/** + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public final class UIUtil { + + public static int dip2px(Context context, double dpValue) { + float density = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * density + 0.5); + } + + public static int getScreenWidth(Context context) { + return context.getResources().getDisplayMetrics().widthPixels; + } + + public static int getScreenHeight(Context context) { + return context.getResources().getDisplayMetrics().heightPixels; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/circlenavigator/CircleNavigator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/circlenavigator/CircleNavigator.java new file mode 100644 index 000000000..95eca6d59 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/circlenavigator/CircleNavigator.java @@ -0,0 +1,310 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.circlenavigator; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + + +import com.yizhuan.erban.ui.widget.magicindicator.abs.IPagerNavigator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 圆圈式的指示器 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class CircleNavigator extends View implements IPagerNavigator { + private int mRadius; + private int mCircleColor; + private int mStrokeWidth; + private int mCircleSpacing; + private int mCurrentIndex; + private int mTotalCount; + private Interpolator mStartInterpolator = new LinearInterpolator(); + + private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private List mCirclePoints = new ArrayList(); + private float mIndicatorX; + + // 事件回调 + private boolean mTouchable; + private OnCircleClickListener mCircleClickListener; + private float mDownX; + private float mDownY; + private int mTouchSlop; + + private boolean mFollowTouch = true; // 是否跟随手指滑动 + + public CircleNavigator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mRadius = UIUtil.dip2px(context, 3); + mCircleSpacing = UIUtil.dip2px(context, 8); + mStrokeWidth = UIUtil.dip2px(context, 1); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + private int measureWidth(int widthMeasureSpec) { + int mode = MeasureSpec.getMode(widthMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int result = 0; + switch (mode) { + case MeasureSpec.EXACTLY: + result = width; + break; + case MeasureSpec.AT_MOST: + case MeasureSpec.UNSPECIFIED: + result = mTotalCount * mRadius * 2 + (mTotalCount - 1) * mCircleSpacing + getPaddingLeft() + getPaddingRight() + mStrokeWidth * 2; + break; + default: + break; + } + return result; + } + + private int measureHeight(int heightMeasureSpec) { + int mode = MeasureSpec.getMode(heightMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + int result = 0; + switch (mode) { + case MeasureSpec.EXACTLY: + result = height; + break; + case MeasureSpec.AT_MOST: + case MeasureSpec.UNSPECIFIED: + result = mRadius * 2 + mStrokeWidth * 2 + getPaddingTop() + getPaddingBottom(); + break; + default: + break; + } + return result; + } + + @Override + protected void onDraw(Canvas canvas) { + mPaint.setColor(mCircleColor); + drawCircles(canvas); + drawIndicator(canvas); + } + + private void drawCircles(Canvas canvas) { + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(mStrokeWidth); + for (int i = 0, j = mCirclePoints.size(); i < j; i++) { + PointF pointF = mCirclePoints.get(i); + canvas.drawCircle(pointF.x, pointF.y, mRadius, mPaint); + } + } + + private void drawIndicator(Canvas canvas) { + mPaint.setStyle(Paint.Style.FILL); + if (mCirclePoints.size() > 0) { + canvas.drawCircle(mIndicatorX, (int) (getHeight() / 2.0f + 0.5f), mRadius, mPaint); + } + } + + private void prepareCirclePoints() { + mCirclePoints.clear(); + if (mTotalCount > 0) { + int y = (int) (getHeight() / 2.0f + 0.5f); + int centerSpacing = mRadius * 2 + mCircleSpacing; + int startX = mRadius + (int) (mStrokeWidth / 2.0f + 0.5f) + getPaddingLeft(); + for (int i = 0; i < mTotalCount; i++) { + PointF pointF = new PointF(startX, y); + mCirclePoints.add(pointF); + startX += centerSpacing; + } + mIndicatorX = mCirclePoints.get(mCurrentIndex).x; + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mFollowTouch) { + if (mCirclePoints.isEmpty()) { + return; + } + + int currentPosition = Math.min(mCirclePoints.size() - 1, position); + int nextPosition = Math.min(mCirclePoints.size() - 1, position + 1); + PointF current = mCirclePoints.get(currentPosition); + PointF next = mCirclePoints.get(nextPosition); + + mIndicatorX = current.x + (next.x - current.x) * mStartInterpolator.getInterpolation(positionOffset); + + invalidate(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (mTouchable) { + mDownX = x; + mDownY = y; + return true; + } + break; + case MotionEvent.ACTION_UP: + if (mCircleClickListener != null) { + if (Math.abs(x - mDownX) <= mTouchSlop && Math.abs(y - mDownY) <= mTouchSlop) { + float max = Float.MAX_VALUE; + int index = 0; + for (int i = 0; i < mCirclePoints.size(); i++) { + PointF pointF = mCirclePoints.get(i); + float offset = Math.abs(pointF.x - x); + if (offset < max) { + max = offset; + index = i; + } + } + mCircleClickListener.onClick(index); + } + } + break; + default: + break; + } + return super.onTouchEvent(event); + } + + @Override + public void onPageSelected(int position) { + mCurrentIndex = position; + if (!mFollowTouch) { + mIndicatorX = mCirclePoints.get(mCurrentIndex).x; + invalidate(); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + prepareCirclePoints(); + } + + @Override + public void onAttachToMagicIndicator() { + } + + @Override + public void notifyDataSetChanged() { + prepareCirclePoints(); + invalidate(); + } + + @Override + public void onDetachFromMagicIndicator() { + } + + public int getRadius() { + return mRadius; + } + + public void setRadius(int radius) { + mRadius = radius; + prepareCirclePoints(); + invalidate(); + } + + public int getCircleColor() { + return mCircleColor; + } + + public void setCircleColor(int circleColor) { + mCircleColor = circleColor; + invalidate(); + } + + public int getStrokeWidth() { + return mStrokeWidth; + } + + public void setStrokeWidth(int strokeWidth) { + mStrokeWidth = strokeWidth; + invalidate(); + } + + public int getCircleSpacing() { + return mCircleSpacing; + } + + public void setCircleSpacing(int circleSpacing) { + mCircleSpacing = circleSpacing; + prepareCirclePoints(); + invalidate(); + } + + public Interpolator getStartInterpolator() { + return mStartInterpolator; + } + + public void setStartInterpolator(Interpolator startInterpolator) { + mStartInterpolator = startInterpolator; + if (mStartInterpolator == null) { + mStartInterpolator = new LinearInterpolator(); + } + } + + public int getCircleCount() { + return mTotalCount; + } + + public void setCircleCount(int count) { + mTotalCount = count; // 此处不调用invalidate,让外部调用notifyDataSetChanged + } + + public boolean isTouchable() { + return mTouchable; + } + + public void setTouchable(boolean touchable) { + mTouchable = touchable; + } + + public boolean isFollowTouch() { + return mFollowTouch; + } + + public void setFollowTouch(boolean followTouch) { + mFollowTouch = followTouch; + } + + public OnCircleClickListener getCircleClickListener() { + return mCircleClickListener; + } + + public void setCircleClickListener(OnCircleClickListener circleClickListener) { + if (!mTouchable) { + mTouchable = true; + } + mCircleClickListener = circleClickListener; + } + + public interface OnCircleClickListener { + void onClick(int index); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/CommonNavigator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/CommonNavigator.java new file mode 100644 index 000000000..83615ce3c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/CommonNavigator.java @@ -0,0 +1,463 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator; + +import android.content.Context; +import android.database.DataSetObserver; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.NavigatorHelper; +import com.yizhuan.erban.ui.widget.magicindicator.ScrollState; +import com.yizhuan.erban.ui.widget.magicindicator.abs.IPagerNavigator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.ArrayList; +import java.util.List; + +/** + * 通用的ViewPager指示器,包含PagerTitle和PagerIndicator + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class CommonNavigator extends FrameLayout implements IPagerNavigator, NavigatorHelper.OnNavigatorScrollListener { + private HorizontalScrollView mScrollView; + private LinearLayout mTitleContainer; + private LinearLayout mIndicatorContainer; + private IPagerIndicator mIndicator; + + private CommonNavigatorAdapter mAdapter; + private NavigatorHelper mNavigatorHelper; + + + /** + * 提供给外部的参数配置 + */ + /****************************************************/ + private boolean mAdjustMode; // 自适应模式,适用于数目固定的、少量的title + private boolean mEnablePivotScroll; // 启动中心点滚动 + private float mScrollPivotX = 0.5f; // 滚动中心点 0.0f - 1.0f + private boolean mSmoothScroll = true; // 是否平滑滚动,适用于 !mAdjustMode && !mFollowTouch + private boolean mFollowTouch = true; // 是否手指跟随滚动 + private int mRightPadding; + private int mLeftPadding; + private boolean mIndicatorOnTop; // 指示器是否在title上层,默认为下层 + private boolean mSkimOver; // 跨多页切换时,中间页是否显示 "掠过" 效果 + private boolean mReselectWhenLayout = true; // PositionData准备好时,是否重新选中当前页,为true可保证在极端情况下指示器状态正确 + /****************************************************/ + + // 保存每个title的位置信息,为扩展indicator提供保障 + private List mPositionDataList = new ArrayList<>(); + + private DataSetObserver mObserver = new DataSetObserver() { + + @Override + public void onChanged() { + mNavigatorHelper.setTotalCount(mAdapter.getCount()); // 如果使用helper,应始终保证helper中的totalCount为最新 + init(); + } + + @Override + public void onInvalidated() { + // 没什么用,暂不做处理 + } + }; + + public CommonNavigator(Context context) { + this(context, 0); + } + + private int fadingLength; + + public CommonNavigator(Context context, int fadingLength) { + super(context); + mNavigatorHelper = new NavigatorHelper(); + mNavigatorHelper.setNavigatorScrollListener(this); + this.fadingLength = fadingLength; + } + + @Override + public void notifyDataSetChanged() { + if (mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + + public boolean isAdjustMode() { + return mAdjustMode; + } + + public void setAdjustMode(boolean is) { + mAdjustMode = is; + } + + public CommonNavigatorAdapter getAdapter() { + return mAdapter; + } + + public void setAdapter(CommonNavigatorAdapter adapter) { + if (mAdapter == adapter) { + return; + } + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + } + mAdapter = adapter; + if (mAdapter != null) { + mAdapter.registerDataSetObserver(mObserver); + mNavigatorHelper.setTotalCount(mAdapter.getCount()); + if (mTitleContainer != null) { // adapter改变时,应该重新init,但是第一次设置adapter不用,onAttachToMagicIndicator中有init + mAdapter.notifyDataSetChanged(); + } + } else { + mNavigatorHelper.setTotalCount(0); + init(); + } + } + + private void init() { + removeAllViews(); + + View root; + if (mAdjustMode) { + root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout_no_scroll, this); + } else { + root = LayoutInflater.from(getContext()).inflate(R.layout.pager_navigator_layout, this); + } + + mScrollView = (HorizontalScrollView) root.findViewById(R.id.scroll_view); + // mAdjustMode为true时,mScrollView为null + setFadingEdge(); + + mTitleContainer = (LinearLayout) root.findViewById(R.id.title_container); + mTitleContainer.setPadding(mLeftPadding, 0, mRightPadding, 0); + + mIndicatorContainer = (LinearLayout) root.findViewById(R.id.indicator_container); + if (mIndicatorOnTop) { + mIndicatorContainer.getParent().bringChildToFront(mIndicatorContainer); + } + + initTitlesAndIndicator(); + } + + /** + * 初始化title和indicator + */ + private void initTitlesAndIndicator() { + for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) { + IPagerTitleView v = mAdapter.getTitleView(getContext(), i); + if (v instanceof View) { + View view = (View) v; + LinearLayout.LayoutParams lp; + if (mAdjustMode) { + lp = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT); + lp.weight = mAdapter.getTitleWeight(getContext(), i); + } else { + lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + } + mTitleContainer.addView(view, lp); + } + } + if (mAdapter != null) { + mIndicator = mAdapter.getIndicator(getContext()); + if (mIndicator instanceof View) { + LayoutParams lp = (LayoutParams) ((View) mIndicator).getLayoutParams(); + if (lp == null) { + lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + } + mIndicatorContainer.addView((View) mIndicator, lp); + } + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (mAdapter != null) { + preparePositionData(); + if (mIndicator != null) { + mIndicator.onPositionDataProvide(mPositionDataList); + } + if (mReselectWhenLayout && mNavigatorHelper.getScrollState() == ScrollState.SCROLL_STATE_IDLE) { + onPageSelected(mNavigatorHelper.getCurrentIndex()); + onPageScrolled(mNavigatorHelper.getCurrentIndex(), 0.0f, 0); + } + } + } + + /** + * 获取title的位置信息,为打造不同的指示器、各种效果提供可能 + */ + private void preparePositionData() { + mPositionDataList.clear(); + for (int i = 0, j = mNavigatorHelper.getTotalCount(); i < j; i++) { + PositionData data = new PositionData(); + View v = mTitleContainer.getChildAt(i); + if (v != null) { + data.mLeft = v.getLeft(); + data.mTop = v.getTop(); + data.mRight = v.getRight(); + data.mBottom = v.getBottom(); + if (v instanceof IMeasurablePagerTitleView) { + IMeasurablePagerTitleView view = (IMeasurablePagerTitleView) v; + data.mContentLeft = view.getContentLeft(); + data.mContentTop = view.getContentTop(); + data.mContentRight = view.getContentRight(); + data.mContentBottom = view.getContentBottom(); + } else { + data.mContentLeft = data.mLeft; + data.mContentTop = data.mTop; + data.mContentRight = data.mRight; + data.mContentBottom = data.mBottom; + } + } + mPositionDataList.add(data); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mAdapter != null) { + + mNavigatorHelper.onPageScrolled(position, positionOffset, positionOffsetPixels); + if (mIndicator != null) { + mIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + + // 手指跟随滚动 + if (mScrollView != null && mPositionDataList.size() > 0 && position >= 0 && position < mPositionDataList.size()) { + if (mFollowTouch) { + int currentPosition = Math.min(mPositionDataList.size() - 1, position); + int nextPosition = Math.min(mPositionDataList.size() - 1, position + 1); + PositionData current = mPositionDataList.get(currentPosition); + PositionData next = mPositionDataList.get(nextPosition); + float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX; + float nextScrollTo = next.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX; + mScrollView.scrollTo((int) (scrollTo + (nextScrollTo - scrollTo) * positionOffset), 0); + } else if (!mEnablePivotScroll) { + // TODO 实现待选中项完全显示出来 + } + } + } + } + + public float getScrollPivotX() { + return mScrollPivotX; + } + + public void setScrollPivotX(float scrollPivotX) { + mScrollPivotX = scrollPivotX; + } + + @Override + public void onPageSelected(int position) { + if (mAdapter != null) { + mNavigatorHelper.onPageSelected(position); + if (mIndicator != null) { + mIndicator.onPageSelected(position); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + if (mAdapter != null) { + mNavigatorHelper.onPageScrollStateChanged(state); + if (mIndicator != null) { + mIndicator.onPageScrollStateChanged(state); + } + } + } + + @Override + public void onAttachToMagicIndicator() { + init(); // 将初始化延迟到这里 + } + + @Override + public void onDetachFromMagicIndicator() { + } + + public IPagerIndicator getPagerIndicator() { + return mIndicator; + } + + public boolean isEnablePivotScroll() { + return mEnablePivotScroll; + } + + public void setEnablePivotScroll(boolean is) { + mEnablePivotScroll = is; + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + if (mTitleContainer == null) { + return; + } + View v = mTitleContainer.getChildAt(index); + if (v instanceof IPagerTitleView) { + ((IPagerTitleView) v).onEnter(index, totalCount, enterPercent, leftToRight); + } + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + if (mTitleContainer == null) { + return; + } + View v = mTitleContainer.getChildAt(index); + if (v instanceof IPagerTitleView) { + ((IPagerTitleView) v).onLeave(index, totalCount, leavePercent, leftToRight); + } + } + + public boolean isSmoothScroll() { + return mSmoothScroll; + } + + public void setSmoothScroll(boolean smoothScroll) { + mSmoothScroll = smoothScroll; + } + + public boolean isFollowTouch() { + return mFollowTouch; + } + + public void setFollowTouch(boolean followTouch) { + mFollowTouch = followTouch; + } + + public boolean isSkimOver() { + return mSkimOver; + } + + public void setSkimOver(boolean skimOver) { + mSkimOver = skimOver; + mNavigatorHelper.setSkimOver(skimOver); + } + + @Override + public void onSelected(int index, int totalCount) { + if (mTitleContainer == null) { + return; + } + View v = mTitleContainer.getChildAt(index); + if (v instanceof IPagerTitleView) { + ((IPagerTitleView) v).onSelected(index, totalCount); + } + + // 外部监听 + if (mNavigatorSelectedListener != null) + mNavigatorSelectedListener.navigatorSelected(index); + + if (!mAdjustMode && !mFollowTouch && mScrollView != null && mPositionDataList.size() > 0) { + int currentIndex = Math.min(mPositionDataList.size() - 1, index); + PositionData current = mPositionDataList.get(currentIndex); + if (mEnablePivotScroll) { + float scrollTo = current.horizontalCenter() - mScrollView.getWidth() * mScrollPivotX; + if (mSmoothScroll) { + mScrollView.smoothScrollTo((int) (scrollTo), 0); + } else { + mScrollView.scrollTo((int) (scrollTo), 0); + } + } else { + // 如果当前项被部分遮挡,则滚动显示完全 + if (mScrollView.getScrollX() > current.mLeft) { + if (mSmoothScroll) { + mScrollView.smoothScrollTo(current.mLeft, 0); + } else { + mScrollView.scrollTo(current.mLeft, 0); + } + } else if (mScrollView.getScrollX() + getWidth() < current.mRight) { + if (mSmoothScroll) { + mScrollView.smoothScrollTo(current.mRight - getWidth(), 0); + } else { + mScrollView.scrollTo(current.mRight - getWidth(), 0); + } + } + } + } + } + + @Override + public void onDeselected(int index, int totalCount) { + if (mTitleContainer == null) { + return; + } + View v = mTitleContainer.getChildAt(index); + if (v instanceof IPagerTitleView) { + ((IPagerTitleView) v).onDeselected(index, totalCount); + } + } + + public IPagerTitleView getPagerTitleView(int index) { + if (mTitleContainer == null) { + return null; + } + return (IPagerTitleView) mTitleContainer.getChildAt(index); + } + + public LinearLayout getTitleContainer() { + return mTitleContainer; + } + + public int getRightPadding() { + return mRightPadding; + } + + public void setRightPadding(int rightPadding) { + mRightPadding = rightPadding; + } + + public int getLeftPadding() { + return mLeftPadding; + } + + public void setLeftPadding(int leftPadding) { + mLeftPadding = leftPadding; + } + + public boolean isIndicatorOnTop() { + return mIndicatorOnTop; + } + + public void setIndicatorOnTop(boolean indicatorOnTop) { + mIndicatorOnTop = indicatorOnTop; + } + + public boolean isReselectWhenLayout() { + return mReselectWhenLayout; + } + + public void setReselectWhenLayout(boolean reselectWhenLayout) { + mReselectWhenLayout = reselectWhenLayout; + } + + private NavigatorSelectedListener mNavigatorSelectedListener; + public void setmNavigatorSelectedListener(NavigatorSelectedListener navigatorSelectedListener) { + this.mNavigatorSelectedListener = navigatorSelectedListener; + } + + public interface NavigatorSelectedListener { + void navigatorSelected(int position); + } + + public void setFadingEdge() { + if (mScrollView == null) { + return; + } + if (fadingLength <= 0) { + return; + } + mScrollView.setHorizontalFadingEdgeEnabled(true); + mScrollView.setFadingEdgeLength(fadingLength); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/CommonNavigatorAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/CommonNavigatorAdapter.java new file mode 100644 index 000000000..ccc18761c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/CommonNavigatorAdapter.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs; + +import android.content.Context; +import android.database.DataSetObservable; +import android.database.DataSetObserver; + +/** + * CommonNavigator适配器,通过它可轻松切换不同的指示器样式 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public abstract class CommonNavigatorAdapter { + + private final DataSetObservable mDataSetObservable = new DataSetObservable(); + + public abstract int getCount(); + + public abstract IPagerTitleView getTitleView(Context context, int index); + + public abstract IPagerIndicator getIndicator(Context context); + + public float getTitleWeight(Context context, int index) { + return 1; + } + + public final void registerDataSetObserver(DataSetObserver observer) { + mDataSetObservable.registerObserver(observer); + } + + public final void unregisterDataSetObserver(DataSetObserver observer) { + mDataSetObservable.unregisterObserver(observer); + } + + public final void notifyDataSetChanged() { + mDataSetObservable.notifyChanged(); + } + + public final void notifyDataSetInvalidated() { + mDataSetObservable.notifyInvalidated(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IMeasurablePagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IMeasurablePagerTitleView.java new file mode 100644 index 000000000..bc15f4608 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IMeasurablePagerTitleView.java @@ -0,0 +1,17 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs; + + +/** + * 可测量内容区域的指示器标题 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public interface IMeasurablePagerTitleView extends IPagerTitleView { + int getContentLeft(); + + int getContentTop(); + + int getContentRight(); + + int getContentBottom(); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerIndicator.java new file mode 100644 index 000000000..98fbbb17d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerIndicator.java @@ -0,0 +1,21 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs; + + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.List; + +/** + * 抽象的viewpager指示器,适用于CommonNavigator + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public interface IPagerIndicator { + void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + void onPageSelected(int position); + + void onPageScrollStateChanged(int state); + + void onPositionDataProvide(List dataList); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerTitleView.java new file mode 100644 index 000000000..6e0abe9d6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/abs/IPagerTitleView.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs; + +/** + * 抽象的指示器标题,适用于CommonNavigator + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public interface IPagerTitleView { + /** + * 被选中 + */ + void onSelected(int index, int totalCount); + + /** + * 未被选中 + */ + void onDeselected(int index, int totalCount); + + /** + * 离开 + * + * @param leavePercent 离开的百分比, 0.0f - 1.0f + * @param leftToRight 从左至右离开 + */ + void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight); + + /** + * 进入 + * + * @param enterPercent 进入的百分比, 0.0f - 1.0f + * @param leftToRight 从左至右离开 + */ + void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight); +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/BezierPagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/BezierPagerIndicator.java new file mode 100644 index 000000000..8e86be720 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/BezierPagerIndicator.java @@ -0,0 +1,166 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + + +import com.yizhuan.erban.ui.widget.magicindicator.FragmentContainerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.ArgbEvaluatorHolder; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.Arrays; +import java.util.List; + +/** + * 贝塞尔曲线ViewPager指示器,带颜色渐变 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class BezierPagerIndicator extends View implements IPagerIndicator { + private List mPositionDataList; + + private float mLeftCircleRadius; + private float mLeftCircleX; + private float mRightCircleRadius; + private float mRightCircleX; + + private float mYOffset; + private float mMaxCircleRadius; + private float mMinCircleRadius; + + private Paint mPaint; + private Path mPath = new Path(); + + private List mColors; + private Interpolator mStartInterpolator = new AccelerateInterpolator(); + private Interpolator mEndInterpolator = new DecelerateInterpolator(); + + public BezierPagerIndicator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mMaxCircleRadius = UIUtil.dip2px(context, 3.5); + mMinCircleRadius = UIUtil.dip2px(context, 2); + mYOffset = UIUtil.dip2px(context, 1.5); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawCircle(mLeftCircleX, getHeight() - mYOffset - mMaxCircleRadius, mLeftCircleRadius, mPaint); + canvas.drawCircle(mRightCircleX, getHeight() - mYOffset - mMaxCircleRadius, mRightCircleRadius, mPaint); + drawBezierCurve(canvas); + } + + /** + * 绘制贝塞尔曲线 + * + * @param canvas + */ + private void drawBezierCurve(Canvas canvas) { + mPath.reset(); + float y = getHeight() - mYOffset - mMaxCircleRadius; + mPath.moveTo(mRightCircleX, y); + mPath.lineTo(mRightCircleX, y - mRightCircleRadius); + mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f, y, mLeftCircleX, y - mLeftCircleRadius); + mPath.lineTo(mLeftCircleX, y + mLeftCircleRadius); + mPath.quadTo(mRightCircleX + (mLeftCircleX - mRightCircleX) / 2.0f, y, mRightCircleX, y + mRightCircleRadius); + mPath.close(); // 闭合 + canvas.drawPath(mPath, mPaint); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mPositionDataList == null || mPositionDataList.isEmpty()) { + return; + } + + // 计算颜色 + if (mColors != null && mColors.size() > 0) { + int currentColor = mColors.get(Math.abs(position) % mColors.size()); + int nextColor = mColors.get(Math.abs(position + 1) % mColors.size()); + int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor); + mPaint.setColor(color); + } + + // 计算锚点位置 + PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position); + PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1); + + float leftX = current.mLeft + (current.mRight - current.mLeft) / 2; + float rightX = next.mLeft + (next.mRight - next.mLeft) / 2; + + mLeftCircleX = leftX + (rightX - leftX) * mStartInterpolator.getInterpolation(positionOffset); + mRightCircleX = leftX + (rightX - leftX) * mEndInterpolator.getInterpolation(positionOffset); + mLeftCircleRadius = mMaxCircleRadius + (mMinCircleRadius - mMaxCircleRadius) * mEndInterpolator.getInterpolation(positionOffset); + mRightCircleRadius = mMinCircleRadius + (mMaxCircleRadius - mMinCircleRadius) * mStartInterpolator.getInterpolation(positionOffset); + + invalidate(); + } + + @Override + public void onPageSelected(int position) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPositionDataProvide(List dataList) { + mPositionDataList = dataList; + } + + public float getMaxCircleRadius() { + return mMaxCircleRadius; + } + + public void setMaxCircleRadius(float maxCircleRadius) { + mMaxCircleRadius = maxCircleRadius; + } + + public float getMinCircleRadius() { + return mMinCircleRadius; + } + + public void setMinCircleRadius(float minCircleRadius) { + mMinCircleRadius = minCircleRadius; + } + + public float getYOffset() { + return mYOffset; + } + + public void setYOffset(float yOffset) { + mYOffset = yOffset; + } + + public void setColors(Integer... colors) { + mColors = Arrays.asList(colors); + } + + public void setStartInterpolator(Interpolator startInterpolator) { + mStartInterpolator = startInterpolator; + if (mStartInterpolator == null) { + mStartInterpolator = new AccelerateInterpolator(); + } + } + + public void setEndInterpolator(Interpolator endInterpolator) { + mEndInterpolator = endInterpolator; + if (mEndInterpolator == null) { + mEndInterpolator = new DecelerateInterpolator(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/LinePagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/LinePagerIndicator.java new file mode 100644 index 000000000..3a4022bee --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/LinePagerIndicator.java @@ -0,0 +1,211 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.View; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + + +import com.yizhuan.erban.ui.widget.magicindicator.FragmentContainerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.ArgbEvaluatorHolder; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.Arrays; +import java.util.List; + +/** + * 直线viewpager指示器,带颜色渐变 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class LinePagerIndicator extends View implements IPagerIndicator { + public static final int MODE_MATCH_EDGE = 0; // 直线宽度 == title宽度 - 2 * mXOffset + public static final int MODE_WRAP_CONTENT = 1; // 直线宽度 == title内容宽度 - 2 * mXOffset + public static final int MODE_EXACTLY = 2; // 直线宽度 == mLineWidth + + private int mMode; // 默认为MODE_MATCH_EDGE模式 + + // 控制动画 + private Interpolator mStartInterpolator = new LinearInterpolator(); + private Interpolator mEndInterpolator = new LinearInterpolator(); + + private float mYOffset; // 相对于底部的偏移量,如果你想让直线位于title上方,设置它即可 + private float mLineHeight; + private float mXOffset; + private float mLineWidth; + private float mRoundRadius; + + private Paint mPaint; + private List mPositionDataList; + private List mColors; + + private RectF mLineRect = new RectF(); + + public LinePagerIndicator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mLineHeight = UIUtil.dip2px(context, 3); + mLineWidth = UIUtil.dip2px(context, 10); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.drawRoundRect(mLineRect, mRoundRadius, mRoundRadius, mPaint); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mPositionDataList == null || mPositionDataList.isEmpty()) { + return; + } + + // 计算颜色 + if (mColors != null && mColors.size() > 0) { + int currentColor = mColors.get(Math.abs(position) % mColors.size()); + int nextColor = mColors.get(Math.abs(position + 1) % mColors.size()); + int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor); + mPaint.setColor(color); + } + + // 计算锚点位置 + PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position); + PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1); + + float leftX; + float nextLeftX; + float rightX; + float nextRightX; + if (mMode == MODE_MATCH_EDGE) { + leftX = current.mLeft + mXOffset; + nextLeftX = next.mLeft + mXOffset; + rightX = current.mRight - mXOffset; + nextRightX = next.mRight - mXOffset; + } else if (mMode == MODE_WRAP_CONTENT) { + leftX = current.mContentLeft + mXOffset; + nextLeftX = next.mContentLeft + mXOffset; + rightX = current.mContentRight - mXOffset; + nextRightX = next.mContentRight - mXOffset; + } else { // MODE_EXACTLY + leftX = current.mLeft + (current.width() - mLineWidth) / 2; + nextLeftX = next.mLeft + (next.width() - mLineWidth) / 2; + rightX = current.mLeft + (current.width() + mLineWidth) / 2; + nextRightX = next.mLeft + (next.width() + mLineWidth) / 2; + } + + mLineRect.left = leftX + (nextLeftX - leftX) * mStartInterpolator.getInterpolation(positionOffset); + mLineRect.right = rightX + (nextRightX - rightX) * mEndInterpolator.getInterpolation(positionOffset); + mLineRect.top = getHeight() - mLineHeight - mYOffset; + mLineRect.bottom = getHeight() - mYOffset; + + invalidate(); + } + + @Override + public void onPageSelected(int position) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPositionDataProvide(List dataList) { + mPositionDataList = dataList; + } + + public float getYOffset() { + return mYOffset; + } + + public void setYOffset(float yOffset) { + mYOffset = yOffset; + } + + public float getXOffset() { + return mXOffset; + } + + public void setXOffset(float xOffset) { + mXOffset = xOffset; + } + + public float getLineHeight() { + return mLineHeight; + } + + public void setLineHeight(float lineHeight) { + mLineHeight = lineHeight; + } + + public float getLineWidth() { + return mLineWidth; + } + + public void setLineWidth(float lineWidth) { + mLineWidth = lineWidth; + } + + public float getRoundRadius() { + return mRoundRadius; + } + + public void setRoundRadius(float roundRadius) { + mRoundRadius = roundRadius; + } + + public int getMode() { + return mMode; + } + + public void setMode(int mode) { + if (mode == MODE_EXACTLY || mode == MODE_MATCH_EDGE || mode == MODE_WRAP_CONTENT) { + mMode = mode; + } else { + throw new IllegalArgumentException("mode " + mode + " not supported."); + } + } + + public Paint getPaint() { + return mPaint; + } + + public List getColors() { + return mColors; + } + + public void setColors(Integer... colors) { + mColors = Arrays.asList(colors); + } + + public Interpolator getStartInterpolator() { + return mStartInterpolator; + } + + public void setStartInterpolator(Interpolator startInterpolator) { + mStartInterpolator = startInterpolator; + if (mStartInterpolator == null) { + mStartInterpolator = new LinearInterpolator(); + } + } + + public Interpolator getEndInterpolator() { + return mEndInterpolator; + } + + public void setEndInterpolator(Interpolator endInterpolator) { + mEndInterpolator = endInterpolator; + if (mEndInterpolator == null) { + mEndInterpolator = new LinearInterpolator(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TestPagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TestPagerIndicator.java new file mode 100644 index 000000000..29aba0c5d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TestPagerIndicator.java @@ -0,0 +1,103 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.View; + + +import com.yizhuan.erban.ui.widget.magicindicator.FragmentContainerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.List; + + +/** + * 用于测试的指示器,可用来检测自定义的IMeasurablePagerTitleView是否正确测量内容区域 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class TestPagerIndicator extends View implements IPagerIndicator { + private Paint mPaint; + private int mOutRectColor; + private int mInnerRectColor; + private RectF mOutRect = new RectF(); + private RectF mInnerRect = new RectF(); + + private List mPositionDataList; + + public TestPagerIndicator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.STROKE); + mOutRectColor = Color.RED; + mInnerRectColor = Color.GREEN; + } + + @Override + protected void onDraw(Canvas canvas) { + mPaint.setColor(mOutRectColor); + canvas.drawRect(mOutRect, mPaint); + mPaint.setColor(mInnerRectColor); + canvas.drawRect(mInnerRect, mPaint); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mPositionDataList == null || mPositionDataList.isEmpty()) { + return; + } + + // 计算锚点位置 + PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position); + PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1); + + mOutRect.left = current.mLeft + (next.mLeft - current.mLeft) * positionOffset; + mOutRect.top = current.mTop + (next.mTop - current.mTop) * positionOffset; + mOutRect.right = current.mRight + (next.mRight - current.mRight) * positionOffset; + mOutRect.bottom = current.mBottom + (next.mBottom - current.mBottom) * positionOffset; + + mInnerRect.left = current.mContentLeft + (next.mContentLeft - current.mContentLeft) * positionOffset; + mInnerRect.top = current.mContentTop + (next.mContentTop - current.mContentTop) * positionOffset; + mInnerRect.right = current.mContentRight + (next.mContentRight - current.mContentRight) * positionOffset; + mInnerRect.bottom = current.mContentBottom + (next.mContentBottom - current.mContentBottom) * positionOffset; + + invalidate(); + } + + @Override + public void onPageSelected(int position) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPositionDataProvide(List dataList) { + mPositionDataList = dataList; + } + + public int getOutRectColor() { + return mOutRectColor; + } + + public void setOutRectColor(int outRectColor) { + mOutRectColor = outRectColor; + } + + public int getInnerRectColor() { + return mInnerRectColor; + } + + public void setInnerRectColor(int innerRectColor) { + mInnerRectColor = innerRectColor; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TriangularPagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TriangularPagerIndicator.java new file mode 100644 index 000000000..631c7a445 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/TriangularPagerIndicator.java @@ -0,0 +1,162 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.view.View; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + + +import com.yizhuan.erban.ui.widget.magicindicator.FragmentContainerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.List; + +/** + * 带有小尖角的直线指示器 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class TriangularPagerIndicator extends View implements IPagerIndicator { + private List mPositionDataList; + private Paint mPaint; + private int mLineHeight; + private int mLineColor; + private int mTriangleHeight; + private int mTriangleWidth; + private boolean mReverse; + private float mYOffset; + + private Path mPath = new Path(); + private Interpolator mStartInterpolator = new LinearInterpolator(); + private float mAnchorX; + + public TriangularPagerIndicator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mLineHeight = UIUtil.dip2px(context, 3); + mTriangleWidth = UIUtil.dip2px(context, 14); + mTriangleHeight = UIUtil.dip2px(context, 8); + } + + @Override + protected void onDraw(Canvas canvas) { + mPaint.setColor(mLineColor); + if (mReverse) { + canvas.drawRect(0, getHeight() - mYOffset - mTriangleHeight, getWidth(), getHeight() - mYOffset - mTriangleHeight + mLineHeight, mPaint); + } else { + canvas.drawRect(0, getHeight() - mLineHeight - mYOffset, getWidth(), getHeight() - mYOffset, mPaint); + } + mPath.reset(); + if (mReverse) { + mPath.moveTo(mAnchorX - mTriangleWidth / 2, getHeight() - mYOffset - mTriangleHeight); + mPath.lineTo(mAnchorX, getHeight() - mYOffset); + mPath.lineTo(mAnchorX + mTriangleWidth / 2, getHeight() - mYOffset - mTriangleHeight); + } else { + mPath.moveTo(mAnchorX - mTriangleWidth / 2, getHeight() - mYOffset); + mPath.lineTo(mAnchorX, getHeight() - mTriangleHeight - mYOffset); + mPath.lineTo(mAnchorX + mTriangleWidth / 2, getHeight() - mYOffset); + } + mPath.close(); + canvas.drawPath(mPath, mPaint); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mPositionDataList == null || mPositionDataList.isEmpty()) { + return; + } + + // 计算锚点位置 + PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position); + PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1); + + float leftX = current.mLeft + (current.mRight - current.mLeft) / 2; + float rightX = next.mLeft + (next.mRight - next.mLeft) / 2; + + mAnchorX = leftX + (rightX - leftX) * mStartInterpolator.getInterpolation(positionOffset); + + invalidate(); + } + + @Override + public void onPageSelected(int position) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPositionDataProvide(List dataList) { + mPositionDataList = dataList; + } + + public int getLineHeight() { + return mLineHeight; + } + + public void setLineHeight(int lineHeight) { + mLineHeight = lineHeight; + } + + public int getLineColor() { + return mLineColor; + } + + public void setLineColor(int lineColor) { + mLineColor = lineColor; + } + + public int getTriangleHeight() { + return mTriangleHeight; + } + + public void setTriangleHeight(int triangleHeight) { + mTriangleHeight = triangleHeight; + } + + public int getTriangleWidth() { + return mTriangleWidth; + } + + public void setTriangleWidth(int triangleWidth) { + mTriangleWidth = triangleWidth; + } + + public Interpolator getStartInterpolator() { + return mStartInterpolator; + } + + public void setStartInterpolator(Interpolator startInterpolator) { + mStartInterpolator = startInterpolator; + if (mStartInterpolator == null) { + mStartInterpolator = new LinearInterpolator(); + } + } + + public boolean isReverse() { + return mReverse; + } + + public void setReverse(boolean reverse) { + mReverse = reverse; + } + + public float getYOffset() { + return mYOffset; + } + + public void setYOffset(float yOffset) { + mYOffset = yOffset; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/WrapPagerIndicator.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/WrapPagerIndicator.java new file mode 100644 index 000000000..aaf66b093 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/indicators/WrapPagerIndicator.java @@ -0,0 +1,149 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.indicators; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.View; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +import com.yizhuan.erban.ui.widget.magicindicator.FragmentContainerHelper; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model.PositionData; + +import java.util.List; + + +/** + * 包裹住内容区域的指示器,类似天天快报的切换效果,需要和IMeasurablePagerTitleView配合使用 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class WrapPagerIndicator extends View implements IPagerIndicator { + private int mVerticalPadding; + private int mHorizontalPadding; + private int mFillColor; + private float mRoundRadius; + private Interpolator mStartInterpolator = new LinearInterpolator(); + private Interpolator mEndInterpolator = new LinearInterpolator(); + + private List mPositionDataList; + private Paint mPaint; + + private RectF mRect = new RectF(); + private boolean mRoundRadiusSet; + + public WrapPagerIndicator(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mVerticalPadding = UIUtil.dip2px(context, 6); + mHorizontalPadding = UIUtil.dip2px(context, 10); + } + + @Override + protected void onDraw(Canvas canvas) { + mPaint.setColor(mFillColor); + canvas.drawRoundRect(mRect, mRoundRadius, mRoundRadius, mPaint); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (mPositionDataList == null || mPositionDataList.isEmpty()) { + return; + } + + // 计算锚点位置 + PositionData current = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position); + PositionData next = FragmentContainerHelper.getImitativePositionData(mPositionDataList, position + 1); + + mRect.left = current.mContentLeft - mHorizontalPadding + (next.mContentLeft - current.mContentLeft) * mEndInterpolator.getInterpolation(positionOffset); + mRect.top = current.mContentTop - mVerticalPadding; + mRect.right = current.mContentRight + mHorizontalPadding + (next.mContentRight - current.mContentRight) * mStartInterpolator.getInterpolation(positionOffset); + mRect.bottom = current.mContentBottom + mVerticalPadding; + + if (!mRoundRadiusSet) { + mRoundRadius = mRect.height() / 2; + } + + invalidate(); + } + + @Override + public void onPageSelected(int position) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPositionDataProvide(List dataList) { + mPositionDataList = dataList; + } + + public Paint getPaint() { + return mPaint; + } + + public int getVerticalPadding() { + return mVerticalPadding; + } + + public void setVerticalPadding(int verticalPadding) { + mVerticalPadding = verticalPadding; + } + + public int getHorizontalPadding() { + return mHorizontalPadding; + } + + public void setHorizontalPadding(int horizontalPadding) { + mHorizontalPadding = horizontalPadding; + } + + public int getFillColor() { + return mFillColor; + } + + public void setFillColor(int fillColor) { + mFillColor = fillColor; + } + + public float getRoundRadius() { + return mRoundRadius; + } + + public void setRoundRadius(float roundRadius) { + mRoundRadius = roundRadius; + mRoundRadiusSet = true; + } + + public Interpolator getStartInterpolator() { + return mStartInterpolator; + } + + public void setStartInterpolator(Interpolator startInterpolator) { + mStartInterpolator = startInterpolator; + if (mStartInterpolator == null) { + mStartInterpolator = new LinearInterpolator(); + } + } + + public Interpolator getEndInterpolator() { + return mEndInterpolator; + } + + public void setEndInterpolator(Interpolator endInterpolator) { + mEndInterpolator = endInterpolator; + if (mEndInterpolator == null) { + mEndInterpolator = new LinearInterpolator(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/model/PositionData.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/model/PositionData.java new file mode 100644 index 000000000..2d5a40071 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/model/PositionData.java @@ -0,0 +1,41 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.model; + +/** + * 保存指示器标题的坐标 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class PositionData { + public int mLeft; + public int mTop; + public int mRight; + public int mBottom; + public int mContentLeft; + public int mContentTop; + public int mContentRight; + public int mContentBottom; + + public int width() { + return mRight - mLeft; + } + + public int height() { + return mBottom - mTop; + } + + public int contentWidth() { + return mContentRight - mContentLeft; + } + + public int contentHeight() { + return mContentBottom - mContentTop; + } + + public int horizontalCenter() { + return mLeft + width() / 2; + } + + public int verticalCenter() { + return mTop + height() / 2; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ClipPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ClipPagerTitleView.java new file mode 100644 index 000000000..b71935c31 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ClipPagerTitleView.java @@ -0,0 +1,192 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.view.View; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; + + +/** + * 类似今日头条切换效果的指示器标题 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class ClipPagerTitleView extends View implements IMeasurablePagerTitleView { + private String mText; + private int mTextColor; + private int mClipColor; + private boolean mLeftToRight; + private float mClipPercent; + + private Paint mPaint; + private Rect mTextBounds = new Rect(); + + public ClipPagerTitleView(Context context) { + super(context); + init(context); + } + + private void init(Context context) { + int textSize = UIUtil.dip2px(context, 16); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setTextSize(textSize); + int padding = UIUtil.dip2px(context, 10); + setPadding(padding, 0, padding, 0); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureTextBounds(); + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + private int measureWidth(int widthMeasureSpec) { + int mode = MeasureSpec.getMode(widthMeasureSpec); + int size = MeasureSpec.getSize(widthMeasureSpec); + int result = size; + switch (mode) { + case MeasureSpec.AT_MOST: + int width = mTextBounds.width() + getPaddingLeft() + getPaddingRight(); + result = Math.min(width, size); + break; + case MeasureSpec.UNSPECIFIED: + result = mTextBounds.width() + getPaddingLeft() + getPaddingRight(); + break; + default: + break; + } + return result; + } + + private int measureHeight(int heightMeasureSpec) { + int mode = MeasureSpec.getMode(heightMeasureSpec); + int size = MeasureSpec.getSize(heightMeasureSpec); + int result = size; + switch (mode) { + case MeasureSpec.AT_MOST: + int height = mTextBounds.height() + getPaddingTop() + getPaddingBottom(); + result = Math.min(height, size); + break; + case MeasureSpec.UNSPECIFIED: + result = mTextBounds.height() + getPaddingTop() + getPaddingBottom(); + break; + default: + break; + } + return result; + } + + @Override + protected void onDraw(Canvas canvas) { + int x = (getWidth() - mTextBounds.width()) / 2; + Paint.FontMetrics fontMetrics = mPaint.getFontMetrics(); + int y = (int) ((getHeight() - fontMetrics.bottom - fontMetrics.top) / 2); + + // 画底层 + mPaint.setColor(mTextColor); + canvas.drawText(mText, x, y, mPaint); + + // 画clip层 + canvas.save(Canvas.CLIP_SAVE_FLAG); + if (mLeftToRight) { + canvas.clipRect(0, 0, getWidth() * mClipPercent, getHeight()); + } else { + canvas.clipRect(getWidth() * (1 - mClipPercent), 0, getWidth(), getHeight()); + } + mPaint.setColor(mClipColor); + canvas.drawText(mText, x, y, mPaint); + canvas.restore(); + } + + @Override + public void onSelected(int index, int totalCount) { + } + + @Override + public void onDeselected(int index, int totalCount) { + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + mLeftToRight = !leftToRight; + mClipPercent = 1.0f - leavePercent; + invalidate(); + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + mLeftToRight = leftToRight; + mClipPercent = enterPercent; + invalidate(); + } + + private void measureTextBounds() { + mPaint.getTextBounds(mText, 0, mText == null ? 0 : mText.length(), mTextBounds); + } + + public String getText() { + return mText; + } + + public void setText(String text) { + mText = text; + requestLayout(); + } + + public float getTextSize() { + return mPaint.getTextSize(); + } + + public void setTextSize(float textSize) { + mPaint.setTextSize(textSize); + requestLayout(); + } + + public int getTextColor() { + return mTextColor; + } + + public void setTextColor(int textColor) { + mTextColor = textColor; + invalidate(); + } + + public int getClipColor() { + return mClipColor; + } + + public void setClipColor(int clipColor) { + mClipColor = clipColor; + invalidate(); + } + + @Override + public int getContentLeft() { + int contentWidth = mTextBounds.width(); + return getLeft() + getWidth() / 2 - contentWidth / 2; + } + + @Override + public int getContentTop() { + Paint.FontMetrics metrics = mPaint.getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 - contentHeight / 2); + } + + @Override + public int getContentRight() { + int contentWidth = mTextBounds.width(); + return getLeft() + getWidth() / 2 + contentWidth / 2; + } + + @Override + public int getContentBottom() { + Paint.FontMetrics metrics = mPaint.getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 + contentHeight / 2); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ColorTransitionPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ColorTransitionPagerTitleView.java new file mode 100644 index 000000000..e1bd3c9ed --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/ColorTransitionPagerTitleView.java @@ -0,0 +1,38 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles; + +import android.content.Context; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.ArgbEvaluatorHolder; + + +/** + * 两种颜色过渡的指示器标题 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class ColorTransitionPagerTitleView extends SimplePagerTitleView { + + public ColorTransitionPagerTitleView(Context context) { + super(context); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + int color = ArgbEvaluatorHolder.eval(leavePercent, mSelectedColor, mNormalColor); + setTextColor(color); + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + int color = ArgbEvaluatorHolder.eval(enterPercent, mNormalColor, mSelectedColor); + setTextColor(color); + } + + @Override + public void onSelected(int index, int totalCount) { + } + + @Override + public void onDeselected(int index, int totalCount) { + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/CommonPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/CommonPagerTitleView.java new file mode 100644 index 000000000..2a0d11453 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/CommonPagerTitleView.java @@ -0,0 +1,144 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; + + +/** + * 通用的指示器标题,子元素内容由外部提供,事件回传给外部 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/7/3. + */ +public class CommonPagerTitleView extends FrameLayout implements IMeasurablePagerTitleView { + private OnPagerTitleChangeListener mOnPagerTitleChangeListener; + private ContentPositionDataProvider mContentPositionDataProvider; + + public CommonPagerTitleView(Context context) { + super(context); + } + + @Override + public void onSelected(int index, int totalCount) { + if (mOnPagerTitleChangeListener != null) { + mOnPagerTitleChangeListener.onSelected(index, totalCount); + } + } + + @Override + public void onDeselected(int index, int totalCount) { + if (mOnPagerTitleChangeListener != null) { + mOnPagerTitleChangeListener.onDeselected(index, totalCount); + } + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + if (mOnPagerTitleChangeListener != null) { + mOnPagerTitleChangeListener.onLeave(index, totalCount, leavePercent, leftToRight); + } + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + if (mOnPagerTitleChangeListener != null) { + mOnPagerTitleChangeListener.onEnter(index, totalCount, enterPercent, leftToRight); + } + } + + @Override + public int getContentLeft() { + if (mContentPositionDataProvider != null) { + return mContentPositionDataProvider.getContentLeft(); + } + return getLeft(); + } + + @Override + public int getContentTop() { + if (mContentPositionDataProvider != null) { + return mContentPositionDataProvider.getContentTop(); + } + return getTop(); + } + + @Override + public int getContentRight() { + if (mContentPositionDataProvider != null) { + return mContentPositionDataProvider.getContentRight(); + } + return getRight(); + } + + @Override + public int getContentBottom() { + if (mContentPositionDataProvider != null) { + return mContentPositionDataProvider.getContentBottom(); + } + return getBottom(); + } + + /** + * 外部直接将布局设置进来 + * + * @param contentView + */ + public void setContentView(View contentView) { + setContentView(contentView, null); + } + + public void setContentView(View contentView, LayoutParams lp) { + removeAllViews(); + if (contentView != null) { + if (lp == null) { + lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + } + addView(contentView, lp); + } + } + + public void setContentView(int layoutId) { + View child = LayoutInflater.from(getContext()).inflate(layoutId, null); + setContentView(child, null); + } + + public OnPagerTitleChangeListener getOnPagerTitleChangeListener() { + return mOnPagerTitleChangeListener; + } + + public void setOnPagerTitleChangeListener(OnPagerTitleChangeListener onPagerTitleChangeListener) { + mOnPagerTitleChangeListener = onPagerTitleChangeListener; + } + + public ContentPositionDataProvider getContentPositionDataProvider() { + return mContentPositionDataProvider; + } + + public void setContentPositionDataProvider(ContentPositionDataProvider contentPositionDataProvider) { + mContentPositionDataProvider = contentPositionDataProvider; + } + + public interface OnPagerTitleChangeListener { + void onSelected(int index, int totalCount); + + void onDeselected(int index, int totalCount); + + void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight); + + void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight); + } + + public interface ContentPositionDataProvider { + int getContentLeft(); + + int getContentTop(); + + int getContentRight(); + + int getContentBottom(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/DummyPagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/DummyPagerTitleView.java new file mode 100644 index 000000000..1228fbfaf --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/DummyPagerTitleView.java @@ -0,0 +1,34 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles; + +import android.content.Context; +import android.view.View; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + +/** + * 空指示器标题,用于只需要指示器而不需要title的需求 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class DummyPagerTitleView extends View implements IPagerTitleView { + + public DummyPagerTitleView(Context context) { + super(context); + } + + @Override + public void onSelected(int index, int totalCount) { + } + + @Override + public void onDeselected(int index, int totalCount) { + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/SimplePagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/SimplePagerTitleView.java new file mode 100644 index 000000000..35b99b26d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/SimplePagerTitleView.java @@ -0,0 +1,99 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.TextUtils; +import android.view.Gravity; +import android.widget.TextView; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; + + +/** + * 带文本的指示器标题 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/6/26. + */ +public class SimplePagerTitleView extends TextView implements IMeasurablePagerTitleView { + protected int mSelectedColor; + protected int mNormalColor; + + public SimplePagerTitleView(Context context) { + super(context, null); + init(context); + } + + private void init(Context context) { + setGravity(Gravity.CENTER); + int padding = UIUtil.dip2px(context, 10); + setPadding(padding, 0, padding, 0); + setSingleLine(); + setEllipsize(TextUtils.TruncateAt.END); + } + + @Override + public void onSelected(int index, int totalCount) { + setTextColor(mSelectedColor); + } + + @Override + public void onDeselected(int index, int totalCount) { + setTextColor(mNormalColor); + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + } + + @Override + public int getContentLeft() { + Rect bound = new Rect(); + getPaint().getTextBounds(getText().toString(), 0, getText().length(), bound); + int contentWidth = bound.width(); + return getLeft() + getWidth() / 2 - contentWidth / 2; + } + + @Override + public int getContentTop() { + Paint.FontMetrics metrics = getPaint().getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 - contentHeight / 2); + } + + @Override + public int getContentRight() { + Rect bound = new Rect(); + getPaint().getTextBounds(getText().toString(), 0, getText().length(), bound); + int contentWidth = bound.width(); + return getLeft() + getWidth() / 2 + contentWidth / 2; + } + + @Override + public int getContentBottom() { + Paint.FontMetrics metrics = getPaint().getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 + contentHeight / 2); + } + + public int getSelectedColor() { + return mSelectedColor; + } + + public void setSelectedColor(int selectedColor) { + mSelectedColor = selectedColor; + } + + public int getNormalColor() { + return mNormalColor; + } + + public void setNormalColor(int normalColor) { + mNormalColor = normalColor; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeAnchor.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeAnchor.java new file mode 100644 index 000000000..5b1ee24a6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeAnchor.java @@ -0,0 +1,22 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles.badge; + +/** + * 角标的锚点 + * Created by hackware on 2016/7/19. + */ +public enum BadgeAnchor { + LEFT, + TOP, + RIGHT, + BOTTOM, + CONTENT_LEFT, + CONTENT_TOP, + CONTENT_RIGHT, + CONTENT_BOTTOM, + CENTER_X, + CENTER_Y, + LEFT_EDGE_CENTER_X, + TOP_EDGE_CENTER_Y, + RIGHT_EDGE_CENTER_X, + BOTTOM_EDGE_CENTER_Y +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgePagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgePagerTitleView.java new file mode 100644 index 000000000..70d0574ef --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgePagerTitleView.java @@ -0,0 +1,222 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles.badge; + +import android.content.Context; +import android.view.View; +import android.widget.FrameLayout; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + + +/** + * 支持显示角标的title,角标布局可自定义 + * 博客: http://hackware.lucode.net + * Created by hackware on 2016/7/18. + */ +public class BadgePagerTitleView extends FrameLayout implements IMeasurablePagerTitleView { + private IPagerTitleView mInnerPagerTitleView; + private View mBadgeView; + private boolean mAutoCancelBadge = true; + + private BadgeRule mXBadgeRule; + private BadgeRule mYBadgeRule; + + public BadgePagerTitleView(Context context) { + super(context); + } + + @Override + public void onSelected(int index, int totalCount) { + if (mInnerPagerTitleView != null) { + mInnerPagerTitleView.onSelected(index, totalCount); + } + if (mAutoCancelBadge) { + setBadgeView(null); + } + } + + @Override + public void onDeselected(int index, int totalCount) { + if (mInnerPagerTitleView != null) { + mInnerPagerTitleView.onDeselected(index, totalCount); + } + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + if (mInnerPagerTitleView != null) { + mInnerPagerTitleView.onLeave(index, totalCount, leavePercent, leftToRight); + } + } + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + if (mInnerPagerTitleView != null) { + mInnerPagerTitleView.onEnter(index, totalCount, enterPercent, leftToRight); + } + } + + public IPagerTitleView getInnerPagerTitleView() { + return mInnerPagerTitleView; + } + + public void setInnerPagerTitleView(IPagerTitleView innerPagerTitleView) { + if (mInnerPagerTitleView == innerPagerTitleView) { + return; + } + mInnerPagerTitleView = innerPagerTitleView; + removeAllViews(); + if (mInnerPagerTitleView instanceof View) { + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + addView((View) mInnerPagerTitleView, lp); + } + if (mBadgeView != null) { + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + addView(mBadgeView, lp); + } + } + + public View getBadgeView() { + return mBadgeView; + } + + public void setBadgeView(View badgeView) { + if (mBadgeView == badgeView) { + return; + } + mBadgeView = badgeView; + removeAllViews(); + if (mInnerPagerTitleView instanceof View) { + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + addView((View) mInnerPagerTitleView, lp); + } + if (mBadgeView != null) { + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + addView(mBadgeView, lp); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (mInnerPagerTitleView instanceof View && mBadgeView != null) { + int[] position = new int[14]; // 14种角标定位方式 + View v = (View) mInnerPagerTitleView; + position[0] = v.getLeft(); + position[1] = v.getTop(); + position[2] = v.getRight(); + position[3] = v.getBottom(); + if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) { + IMeasurablePagerTitleView view = (IMeasurablePagerTitleView) mInnerPagerTitleView; + position[4] = view.getContentLeft(); + position[5] = view.getContentTop(); + position[6] = view.getContentRight(); + position[7] = view.getContentBottom(); + } else { + for (int i = 4; i < 8; i++) { + position[i] = position[i - 4]; + } + } + position[8] = v.getWidth() / 2; + position[9] = v.getHeight() / 2; + position[10] = position[4] / 2; + position[11] = position[5] / 2; + position[12] = position[6] + (position[2] - position[6]) / 2; + position[13] = position[7] + (position[3] - position[7]) / 2; + + // 根据设置的BadgeRule调整角标的位置 + if (mXBadgeRule != null) { + int x = position[mXBadgeRule.getAnchor().ordinal()]; + int offset = mXBadgeRule.getOffset(); + int newLeft = x + offset; + mBadgeView.offsetLeftAndRight(newLeft - mBadgeView.getLeft()); + } + if (mYBadgeRule != null) { + int y = position[mYBadgeRule.getAnchor().ordinal()]; + int offset = mYBadgeRule.getOffset(); + int newTop = y + offset; + mBadgeView.offsetTopAndBottom(newTop - mBadgeView.getTop()); + } + } + } + + @Override + public int getContentLeft() { + if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) { + return getLeft() + ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentLeft(); + } + return getLeft(); + } + + @Override + public int getContentTop() { + if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) { + return ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentTop(); + } + return getTop(); + } + + @Override + public int getContentRight() { + if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) { + return getLeft() + ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentRight(); + } + return getRight(); + } + + @Override + public int getContentBottom() { + if (mInnerPagerTitleView instanceof IMeasurablePagerTitleView) { + return ((IMeasurablePagerTitleView) mInnerPagerTitleView).getContentBottom(); + } + return getBottom(); + } + + public BadgeRule getXBadgeRule() { + return mXBadgeRule; + } + + public void setXBadgeRule(BadgeRule badgeRule) { + if (badgeRule != null) { + BadgeAnchor anchor = badgeRule.getAnchor(); + if (anchor != BadgeAnchor.LEFT + && anchor != BadgeAnchor.RIGHT + && anchor != BadgeAnchor.CONTENT_LEFT + && anchor != BadgeAnchor.CONTENT_RIGHT + && anchor != BadgeAnchor.CENTER_X + && anchor != BadgeAnchor.LEFT_EDGE_CENTER_X + && anchor != BadgeAnchor.RIGHT_EDGE_CENTER_X) { + throw new IllegalArgumentException("x badge rule is wrong."); + } + } + mXBadgeRule = badgeRule; + } + + public BadgeRule getYBadgeRule() { + return mYBadgeRule; + } + + public void setYBadgeRule(BadgeRule badgeRule) { + if (badgeRule != null) { + BadgeAnchor anchor = badgeRule.getAnchor(); + if (anchor != BadgeAnchor.TOP + && anchor != BadgeAnchor.BOTTOM + && anchor != BadgeAnchor.CONTENT_TOP + && anchor != BadgeAnchor.CONTENT_BOTTOM + && anchor != BadgeAnchor.CENTER_Y + && anchor != BadgeAnchor.TOP_EDGE_CENTER_Y + && anchor != BadgeAnchor.BOTTOM_EDGE_CENTER_Y) { + throw new IllegalArgumentException("y badge rule is wrong."); + } + } + mYBadgeRule = badgeRule; + } + + public boolean isAutoCancelBadge() { + return mAutoCancelBadge; + } + + public void setAutoCancelBadge(boolean autoCancelBadge) { + mAutoCancelBadge = autoCancelBadge; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeRule.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeRule.java new file mode 100644 index 000000000..4de0297f2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/buildins/commonnavigator/titles/badge/BadgeRule.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.titles.badge; + + +/** + * 角标的定位规则 + * Created by hackware on 2016/7/19. + */ +public class BadgeRule { + private BadgeAnchor mAnchor; + private int mOffset; + + public BadgeRule(BadgeAnchor anchor, int offset) { + mAnchor = anchor; + mOffset = offset; + } + + public BadgeAnchor getAnchor() { + return mAnchor; + } + + public void setAnchor(BadgeAnchor anchor) { + mAnchor = anchor; + } + + public int getOffset() { + return mOffset; + } + + public void setOffset(int offset) { + mOffset = offset; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/FontChangePagerTitleView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/FontChangePagerTitleView.java new file mode 100644 index 000000000..fb88ee8a3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/FontChangePagerTitleView.java @@ -0,0 +1,181 @@ +package com.yizhuan.erban.ui.widget.magicindicator.ext; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.TextPaint; +import android.view.Gravity; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IMeasurablePagerTitleView; + +/** + * create by lvzebiao @2019/5/5 + */ +public class FontChangePagerTitleView extends LinearLayout implements IMeasurablePagerTitleView { + + protected int mSelectedColor; + protected int mNormalColor; + + protected TextView textView; + + private int padding; + + public FontChangePagerTitleView(Context context) { + this(context, true, 0); + } + + public FontChangePagerTitleView(Context context, boolean selectedBold, float translationY) { + super(context); + this.selectedBold = selectedBold; + this.mTranslationY = translationY; + setGravity(Gravity.CENTER); + padding = UIUtil.dip2px(context, 10); + textView = new TextView(context); + setPadding(padding, 0, padding, 0); + addView(textView); + } + + private float mMinScale = 0.75f; + /** + * 选中是否加粗 + */ + private boolean selectedBold = true; + + /** + * 往y方向平移,设置每个tab文字底部对齐, 0.0不平移 + */ + private float mTranslationY = 0.0f; + + @Override + public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) { + if (textView == null) { + return; + } + try { + float scale = mMinScale + (1.0f - mMinScale) * enterPercent;//范围是mMinScale~1.0f + textView.setScaleX(scale); + textView.setScaleY(scale); + textView.setTranslationY(1.0f + (1 - enterPercent) * mTranslationY); + + //缩放后导致视觉padding变大,加上padding的兼容 + float floatPadding = (padding - textView.getWidth() * (1.0f - scale) / 2); + int newPadding = Math.round(floatPadding); + setPadding(newPadding, 0, newPadding, 0); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + @Override + public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) { + if (textView == null) { + return; + } + try { + float scale = 1.0f + (mMinScale - 1.0f) * leavePercent;//范围是1.0f~mMinScale + textView.setScaleX(scale); + textView.setScaleY(scale); + textView.setTranslationY(1.0f + mTranslationY * leavePercent); + + //缩放后导致视觉padding变大,加上padding的兼容 + float floatPadding = (padding - textView.getWidth() * (1.0f - scale) / 2); + int newPadding = Math.round(floatPadding); + setPadding(newPadding, 0, newPadding, 0); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + @Override + public void onSelected(int index, int totalCount) { + if (textView == null) { + return; + } + textView.setTextColor(mSelectedColor); + TextPaint paint = textView.getPaint(); + paint.setFakeBoldText(selectedBold); + textView.invalidate(); + } + + @Override + public void onDeselected(int index, int totalCount) { + if (textView == null) { + return; + } + textView.setTextColor(mNormalColor); + TextPaint paint = textView.getPaint(); + paint.setFakeBoldText(false); + textView.invalidate(); + } + + public float getMinScale() { + return mMinScale; + } + + public void setMinScale(float minScale) { + mMinScale = minScale; + } + + @Override + public int getContentLeft() { + if (textView == null) { + return getLeft(); + } + Rect bound = new Rect(); + textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bound); + int contentWidth = bound.width(); + return getLeft() + getWidth() / 2 - contentWidth / 2; + } + + @Override + public int getContentTop() { + if (textView == null) { + return 0; + } + Paint.FontMetrics metrics = textView.getPaint().getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 - contentHeight / 2); + } + + @Override + public int getContentRight() { + if (textView == null) { + return getRight(); + } + Rect bound = new Rect(); + textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bound); + int contentWidth = bound.width(); + return getLeft() + getWidth() / 2 + contentWidth / 2; + } + + @Override + public int getContentBottom() { + if (textView == null) { + return getHeight(); + } + Paint.FontMetrics metrics = textView.getPaint().getFontMetrics(); + float contentHeight = metrics.bottom - metrics.top; + return (int) (getHeight() / 2 + contentHeight / 2); + } + + public int getSelectedColor() { + return mSelectedColor; + } + + public void setSelectedColor(int selectedColor) { + mSelectedColor = selectedColor; + } + + public int getNormalColor() { + return mNormalColor; + } + + public void setNormalColor(int normalColor) { + mNormalColor = normalColor; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/MainCommonNavigatorAdapter.java b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/MainCommonNavigatorAdapter.java new file mode 100644 index 000000000..5298bebaa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/magicindicator/ext/MainCommonNavigatorAdapter.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.ui.widget.magicindicator.ext; + +import android.content.Context; +import android.support.v4.content.ContextCompat; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; + +import java.util.ArrayList; +import java.util.List; + +/** + * create by lvzebiao @2019/5/5 + */ +public class MainCommonNavigatorAdapter extends CommonNavigatorAdapter { + + private Context context; + + private List titleList; + + private OnTabClickListener onTabClickListener; + + public MainCommonNavigatorAdapter(Context context, List titleList) { + this.context = context; + if (titleList == null) { + titleList = new ArrayList<>(); + } + this.titleList = titleList; + } + + @Override + public int getCount() { + return titleList.size(); + } + + @Override + public IPagerTitleView getTitleView(Context context, int index) { + FontChangePagerTitleView commonPagerTitleView = new FontChangePagerTitleView(context, true, 5); + commonPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.color_333333)); + commonPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.color_333333)); + commonPagerTitleView.setMinScale(0.8f); + commonPagerTitleView.textView.setTextSize(20); + commonPagerTitleView.textView.setText(titleList.get(index)); + commonPagerTitleView.setOnClickListener(v -> { + if (onTabClickListener != null) { + onTabClickListener.onTabClick(index); + } + }); + return commonPagerTitleView; + } + + @Override + public IPagerIndicator getIndicator(Context context) { + return null; + } + + public interface OnTabClickListener { + void onTabClick(int index); + } + + public void setOnTabClickListener(OnTabClickListener onTabClickListener) { + this.onTabClickListener = onTabClickListener; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/AvRoomNobleWelcomeView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/AvRoomNobleWelcomeView.java new file mode 100644 index 000000000..25a8008c3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/AvRoomNobleWelcomeView.java @@ -0,0 +1,130 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.support.v7.widget.AppCompatImageView; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.LinearInterpolator; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.netease.nim.uikit.common.util.sys.ScreenUtil; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_library.utils.ScreenUtils; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.xchat_android_core.noble.NobleInfo; +import com.yizhuan.xchat_android_core.noble.NobleUtil; + +/** + *

贵族进入房间欢迎界面 + *

+ * + * @author jiahui + * @date 2018/1/19 + */ +public class AvRoomNobleWelcomeView extends RelativeLayout { + private View mNobleBg; + private AppCompatImageView mIvNobleLevel; + private TextView mTvNobleWelcome; + private Context mContext; + + private AnimatorSet mAnimatorSet; + private int mScreenWidth; + private int mWelcomeViewWidth; + private int mLeftWidth; + + public AvRoomNobleWelcomeView(Context context) { + this(context, null); + } + + public AvRoomNobleWelcomeView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public AvRoomNobleWelcomeView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + inflate(context, R.layout.avroom_menber_in_room_float_layout, this); + mWelcomeViewWidth = SizeUtils.dp2px(context, 259); + + setHorizontalScrollBarEnabled(false); + mScreenWidth = ScreenUtils.getScreenWidth(context); + mLeftWidth = SizeUtils.dp2px(context, 69); + + mNobleBg = findViewById(R.id.bg_noble_welcome); + mIvNobleLevel = findViewById(R.id.iv_noble_level); + mTvNobleWelcome = findViewById(R.id.tv_noble_welcome); + } + + + public void setData(NobleInfo nobleInfo, String nick) { + if (nobleInfo == null || TextUtils.isEmpty(nick) || + !NobleUtil.canShowEnterRoomWelcome(nobleInfo.getLevel())) return; + setVisibility(VISIBLE); + mTvNobleWelcome.setText(mContext.getString(R.string.noble_welcome_text, nick)); + + NobleUtil.loadResource(NobleUtil.getSmallBadgeByLevel(nobleInfo.getLevel()), mIvNobleLevel); + mNobleBg.setBackground(NobleUtil.getDrawable(mContext, NobleUtil.getBannerByLevel(nobleInfo.getLevel()))); + + TextPaint paint = mTvNobleWelcome.getPaint(); + int len = (int) paint.measureText(mTvNobleWelcome.getText().toString()); + + cancelAnim(); + this.setAlpha(1); + + mAnimatorSet = new AnimatorSet(); + ObjectAnimator inAnimator = ObjectAnimator.ofFloat(this, + "translationX", -mScreenWidth, 0); + inAnimator.setDuration(500); + inAnimator.setInterpolator(new LinearInterpolator()); + + int dis = len - (mWelcomeViewWidth - mLeftWidth); + ObjectAnimator scroll = null; + mTvNobleWelcome.setTranslationX(0); + if (dis > 0) { + scroll = ObjectAnimator.ofFloat(mTvNobleWelcome, "translationX", 0, -dis); + scroll.setStartDelay(800); + scroll.setDuration((long) (len * 0.4) + 2000); + } + + ObjectAnimator alpha = ObjectAnimator.ofFloat(this, "alpha", 1, 0); + long duration = 500; + alpha.setStartDelay(duration); + alpha.setDuration(800); + + if (scroll == null) { + mAnimatorSet.playSequentially(inAnimator, alpha); + } else { + mAnimatorSet.playSequentially(inAnimator, scroll, alpha); + } + + mAnimatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + setVisibility(GONE); + } + }); + mAnimatorSet.start(); + } + + + @Override + protected void onDetachedFromWindow() { + cancelAnim(); + mAnimatorSet = null; + super.onDetachedFromWindow(); + } + + private void cancelAnim() { + if (mAnimatorSet != null && mAnimatorSet.isRunning()) { + mAnimatorSet.cancel(); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/BetterMarqueeView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/BetterMarqueeView.java new file mode 100644 index 000000000..996fd4034 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/BetterMarqueeView.java @@ -0,0 +1,146 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; + +/** + * @author jack + * @Description + * @Date 2018/5/3 + */ + +public class BetterMarqueeView extends MarqueeView { + private Adapter adapter; + + private final int reuseViewSize = 2; + private boolean isFlipping = false; + + public BetterMarqueeView(Context context) { + this(context, null); + } + + public BetterMarqueeView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(); + } + + private void initView() { + setInAndOutAnimation(inAnimResId, outAnimResId); + getInAnimation().setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + position++; + if (position >= adapter.getSize()) { + position = 0; + } + View view = getChildAt((getDisplayedChild() + 1) % reuseViewSize); + if (view != null) { + adapter.onBindViewHolder((ViewHolder) view.getTag(), position); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + } + + public void start(){ + if (adapter != null && adapter.getSize() > 1) { + setAutoStart(true); + startFlipping(); + } + isFlipping = true; + } + + public void stop(){ + stopFlipping(); + isFlipping = false; + } + + /** + * 设置适配器 + * @param adapter + */ + public void setAdapter(Adapter adapter){ + this.adapter = adapter; + this.adapter.setBetterMarqueeView(this); + notifyDataSetChange(); + } + + /** + * 刷新 + */ + private void notifyDataSetChange(){ + removeAllViews(); + clearAnimation(); + if (this.adapter.getSize() > 1){ + if (isFlipping) { + startFlipping(); + }else{ + stopFlipping(); + } + for (int i = 0; i < reuseViewSize; i++) { + ViewHolder viewHolder = adapter.onCreateView(this); + viewHolder.itemView.setTag(viewHolder); + addView(viewHolder.itemView); + adapter.onBindViewHolder(viewHolder,i); + position = i; + } + }else if (this.adapter.getSize() > 0){ + stopFlipping(); + ViewHolder viewHolder = adapter.onCreateView(this); + viewHolder.itemView.setTag(viewHolder); + addView(viewHolder.itemView); + adapter.onBindViewHolder(viewHolder,0); + position = 0; + }else{ + stopFlipping(); + } + + } + + + /** + * 适配器,暂时单一类型 子view,之后可以扩展成支持多类型 + * @param + */ + public abstract static class Adapter{ + private BetterMarqueeView betterMarqueeView; + + private void setBetterMarqueeView(BetterMarqueeView view){ + this.betterMarqueeView = view; + } + + public final void notifyDateSetChange(){ + betterMarqueeView.notifyDataSetChange(); + } + + public abstract VH onCreateView(ViewGroup parent); + + public abstract void onBindViewHolder(VH holder, int position); + + public abstract int getSize(); + } + + /** + * View Holder + */ + public static abstract class ViewHolder{ + public View itemView; + + public ViewHolder(View itemView) { + if (itemView == null) { + throw new IllegalArgumentException("itemView may not be null"); + } + this.itemView = itemView; + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/ExToast.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/ExToast.java new file mode 100644 index 000000000..8fa48c6e4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/ExToast.java @@ -0,0 +1,212 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Resources; +import android.os.Build; +import android.os.Handler; +import android.os.IBinder; +import android.view.View; +import android.view.WindowManager; +import android.widget.Toast; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class ExToast { + private static final String TAG = "ExToast"; + + public static final int LENGTH_ALWAYS = 0; + public static final int LENGTH_SHORT = 2; + public static final int LENGTH_LONG = 4; + + private Toast toast; + private Context mContext; + private int mDuration = LENGTH_SHORT; + private int animations = -1; + private boolean isShow = false; + + private Object mTN; + private Object mGetService; + private Method mAsBinder; + private Method show; + private Method hide; + + private Handler handler = new Handler(); + + public ExToast(Context context) { + this.mContext = context; + if (toast == null) { + toast = new Toast(mContext); + } + } + + private Runnable hideRunnable = this::hide; + + /** + * Show the view for the specified duration. + */ + public void show() { + if (isShow) return; + + initTN(); + try { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { + show.invoke(mTN); + } else { + show.invoke(mTN, toast.getView().getWindowToken()/*mAsBinder.invoke(mGetService)*/); + } + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + isShow = true; + //判断duration,如果大于#LENGTH_ALWAYS 则设置消失时间 + if (mDuration > LENGTH_ALWAYS) { + handler.postDelayed(hideRunnable, mDuration * 1000); + } + } + + /** + * Close the view if it's showing, or don't show it if it isn't showing yet. + * You do not normally have to call this. Normally view will disappear on its own + * after the appropriate duration. + */ + public void hide() { + if (!isShow) return; + try { + hide.invoke(mTN); + } catch (InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + isShow = false; + } + + public void setView(View view) { + toast.setView(view); + } + + public View getView() { + return toast.getView(); + } + + /** + * Set how long to show the view for. + * + * @see #LENGTH_SHORT + * @see #LENGTH_LONG + * @see #LENGTH_ALWAYS + */ + public void setDuration(int duration) { + mDuration = duration; + } + + public int getDuration() { + return mDuration; + } + + public void setMargin(float horizontalMargin, float verticalMargin) { + toast.setMargin(horizontalMargin, verticalMargin); + } + + public float getHorizontalMargin() { + return toast.getHorizontalMargin(); + } + + public float getVerticalMargin() { + return toast.getVerticalMargin(); + } + + public void setGravity(int gravity, int xOffset, int yOffset) { + toast.setGravity(gravity, xOffset, yOffset); + } + + public int getGravity() { + return toast.getGravity(); + } + + public int getXOffset() { + return toast.getXOffset(); + } + + public int getYOffset() { + return toast.getYOffset(); + } + + public static ExToast makeText(Context context, CharSequence text, int duration) { + Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT); + ExToast exToast = new ExToast(context); + exToast.toast = toast; + exToast.mDuration = duration; + + return exToast; + } + + public static ExToast makeText(Context context, int resId, int duration) + throws Resources.NotFoundException { + return makeText(context, context.getResources().getText(resId), duration); + } + + public void setText(int resId) { + setText(mContext.getText(resId)); + } + + public void setText(CharSequence s) { + toast.setText(s); + } + + public int getAnimations() { + return animations; + } + + public void setAnimations(int animations) { + this.animations = animations; + } + + @SuppressLint("PrivateApi") + private void initTN() { + try { + Field tnField = toast.getClass().getDeclaredField("mTN"); + tnField.setAccessible(true); + mTN = tnField.get(toast); + + Method getService = toast.getClass().getDeclaredMethod("getService"); + getService.setAccessible(true); + mGetService = getService.invoke(toast); + + Method[] methods = mGetService.getClass().getMethods(); + for (Method method : methods) { + if ("asBinder".equals(method.getName())) { + //public android.os.IBinder android.app.INotificationManager$Stub$Proxy.asBinder() + mAsBinder = method; + } + } + + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { + show = mTN.getClass().getMethod("show"); + } else { + show = mTN.getClass().getMethod("show", IBinder.class); + } + hide = mTN.getClass().getMethod("hide"); + + + /*设置动画*/ + if (animations != -1) { + Field tnParamsField = mTN.getClass().getDeclaredField("mParams"); + tnParamsField.setAccessible(true); + WindowManager.LayoutParams params = (WindowManager.LayoutParams) tnParamsField.get(mTN); + params.windowAnimations = animations; + } + + /*调用tn.show()之前一定要先设置mNextView*/ + Field tnNextViewField = mTN.getClass().getDeclaredField("mNextView"); + tnNextViewField.setAccessible(true); + tnNextViewField.set(mTN, toast.getView()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/HomeRankingView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/HomeRankingView.java new file mode 100644 index 000000000..3eae76f75 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/HomeRankingView.java @@ -0,0 +1,194 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.content.Context; +import android.support.annotation.AnimRes; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.Animation; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.load.resource.bitmap.CircleCrop; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.yizhuan.erban.R; +import com.yizhuan.xchat_android_core.home.bean.RankingInfo; + +import java.util.List; + +/** + * 首页排行榜 + * Created by ${Seven} on 2017/11/2. + */ +public class HomeRankingView extends MarqueeView { + + private SparseArray> mListMap; + private Context mContext; + + public HomeRankingView(Context context) { + this(context, null); + } + + public HomeRankingView(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + public void setHomeNoticeInfoList(RankingInfo rankingInfo) { + if (rankingInfo == null) return; + initData(rankingInfo); + } + + private void initData(RankingInfo rankingInfo) { + if (mListMap == null) + mListMap = new SparseArray<>(); + mListMap.put(0, rankingInfo.starList); + mListMap.put(1, rankingInfo.nobleList); + mListMap.put(2, rankingInfo.roomList); + } + + + /** + * 根据通知列表,启动翻页公告 + * + * @param rankingInfo 字符串列表 + */ + public void startWithLists(RankingInfo rankingInfo) { + startWithLists(rankingInfo, inAnimResId, outAnimResId); + } + + /** + * 根据通知列表,启动翻页公告 + * + * @param rankingInfo 通知列表 + * @param inAnimResId 进入动画的resID + * @param outAnimResID 离开动画的resID + */ + public void startWithLists(RankingInfo rankingInfo, @AnimRes int inAnimResId, @AnimRes int outAnimResID) { + setHomeNoticeInfoList(rankingInfo); + start(inAnimResId, outAnimResID); + } + + @Override + protected boolean start(int inAnimResId, int outAnimResID) { + removeAllViews(); + clearAnimation(); + + position = 0; + addView(createView(mListMap.get(position))); + + if (mListMap.size() > 1) { + setInAndOutAnimation(inAnimResId, outAnimResID); + startFlipping(); + } + + if (getInAnimation() != null) { + getInAnimation().setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + position++; + if (position >= mListMap.size()) { + position = 0; + } + if (position < mListMap.size()) { + View view = createView(mListMap.get(position)); + if (view.getParent() == null) { + addView(view); + } + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + } + return true; + } + + private View createView(final List rankingList) { + int index = (getDisplayedChild() + 1) % 3; + View view = getChildAt(index); + if (view == null) { + view = LayoutInflater.from(getContext()).inflate(R.layout.layout_home_notice, null); +// textView.setGravity(gravity); +// textView.setTextColor(textColor); +// textView.setTextSize(textSize); +// textView.setSingleLine(singleLine); + } + +// textView.setText(text); + TextView noticeTitle = (TextView) view.findViewById(R.id.tv_notice_title); + ImageView noticeCover1 = (ImageView) view.findViewById(R.id.iv_cover_1); + ImageView noticeCover2 = (ImageView) view.findViewById(R.id.iv_cover_2); + ImageView noticeCover3 = (ImageView) view.findViewById(R.id.iv_cover_3); + ImageView arrowRight = (ImageView) view.findViewById(R.id.iv_arrow_right); + + if (position == 0) { + noticeTitle.setText(R.string.star_list_title); + bindAvater(rankingList, noticeCover1, noticeCover2, noticeCover3); + } else if (position == 1) { + noticeTitle.setText(R.string.noble_list_title); + bindAvater(rankingList, noticeCover1, noticeCover2, noticeCover3); + } else if (position == 2) { + noticeTitle.setText(R.string.room_list_title); + bindAvater(rankingList, noticeCover1, noticeCover2, noticeCover3); + } + + setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (noticeClickListener != null) { + noticeClickListener.onNoticeClick(getPosition(), rankingList); + } + } + }); + + view.setTag(this.position); + return view; + } + + private void bindAvater(List rankingList, ImageView noticeCover1, ImageView noticeCover2, ImageView noticeCover3) { + if (rankingList != null) { + int size = rankingList.size(); + if (size > 0) { + bindAvater(noticeCover3, rankingList.get(0)); + } + if (size > 1) { + bindAvater(noticeCover2, rankingList.get(1)); + } + if (size > 2) { + bindAvater(noticeCover1, rankingList.get(2)); + } + } + } + + private void bindAvater(ImageView imageView, RankingInfo.Ranking ranking) { + if (ranking != null) { + GlideApp.with(mContext) + .load(ranking.getAvatar()) +// .transform(new GlideCircleTransform(mContext)) + .transform(new CircleCrop()) + .placeholder(R.drawable.default_user_head) + .error(R.drawable.default_user_head) + .into(imageView); + } else { + imageView.setImageResource(R.drawable.default_user_head); + } + } + + private NoticeClickListener noticeClickListener; + + public void setNoticeClickListener(NoticeClickListener noticeClickListener) { + this.noticeClickListener = noticeClickListener; + } + + public interface NoticeClickListener { + void onNoticeClick(int position, List rankingList); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/MarqueeView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/MarqueeView.java new file mode 100644 index 000000000..859e08f5f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/MarqueeView.java @@ -0,0 +1,302 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.support.annotation.AnimRes; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.TextView; +import android.widget.ViewFlipper; + +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by sunfusheng on 16/5/31. + */ +public class MarqueeView extends ViewFlipper { + + private int interval = 3000; + private boolean hasSetAnimDuration = false; + private int animDuration = 1000; + private int textSize = 14; + private int textColor = 0xffffffff; + private boolean singleLine = false; + + private int gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; + private static final int GRAVITY_LEFT = 0; + private static final int GRAVITY_CENTER = 1; + private static final int GRAVITY_RIGHT = 2; + + private boolean hasSetDirection = false; + private int direction = DIRECTION_BOTTOM_TO_TOP; + private static final int DIRECTION_BOTTOM_TO_TOP = 0; + private static final int DIRECTION_TOP_TO_BOTTOM = 1; + private static final int DIRECTION_RIGHT_TO_LEFT = 2; + private static final int DIRECTION_LEFT_TO_RIGHT = 3; + + @AnimRes + protected int inAnimResId = R.anim.anim_bottom_in; + @AnimRes + protected int outAnimResId = R.anim.anim_top_out; + + protected int position; + private List notices = new ArrayList<>(); + private OnItemClickListener onItemClickListener; + + public MarqueeView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MarqueeViewStyle, defStyleAttr, 0); + + interval = typedArray.getInteger(R.styleable.MarqueeViewStyle_mvInterval, interval); + hasSetAnimDuration = typedArray.hasValue(R.styleable.MarqueeViewStyle_mvAnimDuration); + animDuration = typedArray.getInteger(R.styleable.MarqueeViewStyle_mvAnimDuration, animDuration); + singleLine = typedArray.getBoolean(R.styleable.MarqueeViewStyle_mvSingleLine, false); + if (typedArray.hasValue(R.styleable.MarqueeViewStyle_mvTextSize)) { + textSize = (int) typedArray.getDimension(R.styleable.MarqueeViewStyle_mvTextSize, textSize); + textSize = Utils.px2sp(context, textSize); + } + textColor = typedArray.getColor(R.styleable.MarqueeViewStyle_mvTextColor, textColor); + + int gravityType = typedArray.getInt(R.styleable.MarqueeViewStyle_mvGravity, GRAVITY_LEFT); + switch (gravityType) { + case GRAVITY_LEFT: + gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL; + break; + case GRAVITY_CENTER: + gravity = Gravity.CENTER; + break; + case GRAVITY_RIGHT: + gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL; + break; + } + + hasSetDirection = typedArray.hasValue(R.styleable.MarqueeViewStyle_mvDirection); + direction = typedArray.getInt(R.styleable.MarqueeViewStyle_mvDirection, direction); + if (hasSetDirection) { + switch (direction) { + case DIRECTION_BOTTOM_TO_TOP: + inAnimResId = R.anim.anim_bottom_in; + outAnimResId = R.anim.anim_top_out; + break; + case DIRECTION_TOP_TO_BOTTOM: + inAnimResId = R.anim.anim_top_in; + outAnimResId = R.anim.anim_bottom_out; + break; + case DIRECTION_RIGHT_TO_LEFT: + inAnimResId = R.anim.anim_right_in; + outAnimResId = R.anim.anim_left_out; + break; + case DIRECTION_LEFT_TO_RIGHT: + inAnimResId = R.anim.anim_left_in; + outAnimResId = R.anim.anim_right_out; + break; + } + } else { + inAnimResId = R.anim.anim_bottom_in; + outAnimResId = R.anim.anim_top_out; + } + + typedArray.recycle(); + setFlipInterval(interval); + } + + /** + * 根据字符串,启动翻页公告 + * + * @param notice 字符串 + */ + public void startWithText(String notice) { + startWithText(notice, inAnimResId, outAnimResId); + } + + /** + * 根据字符串,启动翻页公告 + * + * @param notice 字符串 + * @param inAnimResId 进入动画的resID + * @param outAnimResID 离开动画的resID + */ + @SuppressWarnings("deprecation") + public void startWithText(final String notice, final @AnimRes int inAnimResId, final @AnimRes int outAnimResID) { + if (TextUtils.isEmpty(notice)) return; + getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else { + getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + startWithFixedWidth(notice, inAnimResId, outAnimResID); + } + }); + } + + /** + * 根据字符串和宽度,启动翻页公告 + * + * @param notice 字符串 + */ + private void startWithFixedWidth(String notice, @AnimRes int inAnimResId, @AnimRes int outAnimResID) { + int noticeLength = notice.length(); + int width = Utils.px2dip(getContext(), getWidth()); + if (width == 0) { + throw new RuntimeException("Please set the width of MarqueeView !"); + } + int limit = width / textSize; + List list = new ArrayList(); + + if (noticeLength <= limit) { + list.add(notice); + } else { + int size = noticeLength / limit + (noticeLength % limit != 0 ? 1 : 0); + for (int i = 0; i < size; i++) { + int startIndex = i * limit; + int endIndex = ((i + 1) * limit >= noticeLength ? noticeLength : (i + 1) * limit); + list.add(notice.substring(startIndex, endIndex)); + } + } + + if (notices == null) notices = new ArrayList<>(); + notices.clear(); + notices.addAll(list); + start(inAnimResId, outAnimResID); + } + + /** + * 根据字符串列表,启动翻页公告 + * + * @param notices 字符串列表 + */ + public void startWithList(List notices) { + startWithList(notices, inAnimResId, outAnimResId); + } + + /** + * 根据字符串列表,启动翻页公告 + * + * @param notices 字符串列表 + * @param inAnimResId 进入动画的resID + * @param outAnimResID 离开动画的resID + */ + public void startWithList(List notices, @AnimRes int inAnimResId, @AnimRes int outAnimResID) { + if (Utils.isEmpty(notices)) return; + setNotices(notices); + start(inAnimResId, outAnimResID); + } + + protected boolean start(@AnimRes int inAnimResId, @AnimRes int outAnimResID) { + removeAllViews(); + clearAnimation(); + + position = 0; + addView(createTextView(notices.get(position))); + + if (notices.size() > 1) { + setInAndOutAnimation(inAnimResId, outAnimResID); + startFlipping(); + } + + if (getInAnimation() != null) { + getInAnimation().setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + position++; + if (position >= notices.size()) { + position = 0; + } + View view = createTextView(notices.get(position)); + if (view.getParent() == null) { + addView(view); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + } + return true; + } + + private TextView createTextView(CharSequence text) { + TextView textView = (TextView) getChildAt((getDisplayedChild() + 1) % 3); + if (textView == null) { + textView = new TextView(getContext()); + textView.setGravity(gravity); + textView.setTextColor(textColor); + textView.setTextSize(textSize); + textView.setSingleLine(singleLine); + if (singleLine) { + textView.setEllipsize(TextUtils.TruncateAt.END); + } + } + textView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (onItemClickListener != null) { + onItemClickListener.onItemClick(getPosition(), (TextView) v); + } + } + }); + textView.setText(text); + textView.setTag(position); + return textView; + } + + + + public int getPosition() { + return (int) getCurrentView().getTag(); + } + + public List getNotices() { + return notices; + } + + public void setNotices(List notices) { + this.notices = notices; + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + } + + public interface OnItemClickListener { + void onItemClick(int position, TextView textView); + } + + /** + * 设置进入动画和离开动画 + * + * @param inAnimResId 进入动画的resID + * @param outAnimResID 离开动画的resID + */ + protected void setInAndOutAnimation(@AnimRes int inAnimResId, @AnimRes int outAnimResID) { + Animation inAnim = AnimationUtils.loadAnimation(getContext(), inAnimResId); + if (hasSetAnimDuration) inAnim.setDuration(animDuration); + setInAnimation(inAnim); + + Animation outAnim = AnimationUtils.loadAnimation(getContext(), outAnimResID); + if (hasSetAnimDuration) outAnim.setDuration(animDuration); + setOutAnimation(outAnim); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/Utils.java b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/Utils.java new file mode 100644 index 000000000..68b4438e5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/marqueeview/Utils.java @@ -0,0 +1,128 @@ +package com.yizhuan.erban.ui.widget.marqueeview; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.WindowManager; + +import java.util.List; + +/** + * Created by sunfusheng on 17/8/8. + */ +public class Utils { + + public static boolean notEmpty(List list) { + return !isEmpty(list); + } + + public static boolean isEmpty(List list) { + if (list == null || list.size() == 0) { + return true; + } + return false; + } + + public static int getNavigationBarHeight(Context context) { + int statusBarHeight = 0; + int resourceId = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android"); + if (resourceId != 0) { + resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); + //根据资源ID获取响应的尺寸值 + statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); + } + return statusBarHeight; + } + + + /** + * 判断底部navigator是否已经显示 + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + public static boolean hasSoftKeys(Context context) { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display d = windowManager.getDefaultDisplay(); + + + DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + d.getRealMetrics(realDisplayMetrics); + + + int realHeight = realDisplayMetrics.heightPixels; + int realWidth = realDisplayMetrics.widthPixels; + + + DisplayMetrics displayMetrics = new DisplayMetrics(); + d.getMetrics(displayMetrics); + + + int displayHeight = displayMetrics.heightPixels; + int displayWidth = displayMetrics.widthPixels; + + + return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0; + } + + // 将px值转换为dip或dp值 + public static int px2dip(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } + + // 将dip或dp值转换为px值 + public static int dip2px(Context context, float dipValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dipValue * scale + 0.5f); + } + + // 将px值转换为sp值 + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } + + // 将sp值转换为px值 + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + // 屏幕宽度(像素) + public static int getWindowWidth(Context context) { + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + return dm.widthPixels; + } + + // 屏幕高度(像素) + public static int getWindowHeight(Context context) { + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + return dm.heightPixels; + } + + // 根据Unicode编码判断中文汉字和符号 + private static boolean isChinese(char c) { + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) { + return true; + } + return false; + } + + // 判断中文汉字和符号 + public static boolean isChinese(String strName) { + char[] ch = strName.toCharArray(); + for (int i = 0; i < ch.length; i++) { + char c = ch[i]; + if (isChinese(c)) { + return true; + } + } + return false; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/password/PassWordFragment.java b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PassWordFragment.java new file mode 100644 index 000000000..8e50bad1b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PassWordFragment.java @@ -0,0 +1,190 @@ +package com.yizhuan.erban.ui.widget.password; + + +import android.app.Activity; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentManager; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import com.jungly.gridpasswordview.GridPasswordView; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.R; +import com.yizhuan.erban.ui.setting.VerifyPhoneActivity; +import com.yizhuan.erban.ui.wallet.ExchangeGoldActivity; +import com.yizhuan.erban.ui.wallet.RedPacketWithdrawActivity; +import com.yizhuan.erban.ui.withdraw.WithdrawActivity; +import com.yizhuan.xchat_android_library.utils.codec.DESUtils; + +import org.greenrobot.eventbus.EventBus; + +//也可继承design中的BottomSheetDialogFragment +public class PassWordFragment extends DialogFragment { + + private static final String TAG = "PassWordFragment"; + + public final static int TYPE_DEFALUT = 0; + /** + * 金币转赠 + */ + public final static int TYPE_SEND_GOLD = 1; + + public final static String EXTRA_TYPE = "extra_type"; + + private PasswordView mPassword; + private boolean isFullScreen; + private ExchangeGoldActivity goldActivity; + private WithdrawActivity withdrawActivity; + private RedPacketWithdrawActivity redPacketWithdrawActivity; + private long value; + private int hammerNum; + /**用于标识密码类型*/ + private int type = TYPE_DEFALUT; + + public static PassWordFragment newInstace(long value) { + PassWordFragment passWordFragment = new PassWordFragment(); + Bundle bundle = new Bundle(); + bundle.putLong("values", value); + passWordFragment.setArguments(bundle); + return passWordFragment; + } + + public static PassWordFragment newInstace(long value, int hammerNum) { + PassWordFragment passWordFragment = new PassWordFragment(); + Bundle bundle = new Bundle(); + bundle.putLong("values", value); + bundle.putInt("hammerNum", hammerNum); + passWordFragment.setArguments(bundle); + return passWordFragment; + } + + public static PassWordFragment newInstance(int type) { + PassWordFragment passWordFragment = new PassWordFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(EXTRA_TYPE, type); + passWordFragment.setArguments(bundle); + return passWordFragment; + } + + public static PassWordFragment newInstance() { + return new PassWordFragment(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (activity instanceof ExchangeGoldActivity) { + goldActivity = (ExchangeGoldActivity) activity; + } else if (activity instanceof WithdrawActivity) { + withdrawActivity = (WithdrawActivity) activity; + } else if (activity instanceof RedPacketWithdrawActivity) { + redPacketWithdrawActivity = (RedPacketWithdrawActivity) activity; + } + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + public void show(FragmentManager fragmentManager) { + this.show(fragmentManager, TAG); + } + + @Override + public void show(FragmentManager manager, String tag) { + if (manager.findFragmentByTag(tag) == null) { + manager.beginTransaction() + .add(this, tag) + .commitAllowingStateLoss(); + } + } + + //继承BottomSheetDialogFragment时onStart()可注释掉 + @Override + public void onStart() { + super.onStart(); + + Window win = getDialog().getWindow(); + win.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.transparent))); + WindowManager.LayoutParams layoutParams = getDialog().getWindow().getAttributes(); + + DisplayMetrics dm = new DisplayMetrics(); + Display d = win.getWindowManager().getDefaultDisplay(); + d.getRealMetrics(dm); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + layoutParams.width = (int) (dm.widthPixels); +// layoutParams.height = (isFullScreen ? getContext().getResources().getDisplayMetrics().heightPixels : dm.heightPixels) - +// (Utils.hasSoftKeys(getContext()) ? Utils.getNavigationBarHeight(getContext()) : 0); + win.setAttributes(layoutParams); + + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_password, container); + init(view); + return view; + } + + private void init(View view) { + if (getArguments() != null) { + value = getArguments().getLong("values"); + hammerNum = getArguments().getInt("hammerNum"); + type = getArguments().getInt(EXTRA_TYPE, TYPE_DEFALUT); + } + mPassword = (PasswordView) view.findViewById(R.id.view_password); + mPassword.getCloseImageView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dismiss(); + } + }); + + mPassword.getForgetTextView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + VerifyPhoneActivity.start(getActivity(), true); + dismiss(); + } + }); + + mPassword.getPswView().setOnPasswordChangedListener(new GridPasswordView.OnPasswordChangedListener() { + @Override + public void onTextChanged(String psw) { + if (mPassword.getPassword().length() == 6) { + dismiss(); + if (goldActivity != null) { + goldActivity.commit(value, hammerNum, mPassword.getPassword()); + } else if (withdrawActivity != null) { + withdrawActivity.commit(mPassword.getPassword()); + } else if (redPacketWithdrawActivity != null) { + redPacketWithdrawActivity.commit(mPassword.getPassword()); + } + try { + EventBus.getDefault().post(new PasswordEvent().setType(type) + .setPassword( + DESUtils.DESAndBase64Encrypt(mPassword.getPassword()))); + } catch (Exception e) { + e.printStackTrace(); + LogUtil.e(TAG, "onInputFinish: payment password encrypt error", e); + } + } + } + + @Override + public void onInputFinish(String psw) { + + } + }); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordEvent.java b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordEvent.java new file mode 100644 index 000000000..82be8e39e --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordEvent.java @@ -0,0 +1,25 @@ +package com.yizhuan.erban.ui.widget.password; + +import lombok.Data; + +/** + * Created by MadisonRong on 2019-08-19 + */ +@Data +public class PasswordEvent { + + private String password; + + private int type; + + public PasswordEvent setPassword(String password) { + this.password = password; + return this; + } + + public PasswordEvent setType(int type) { + this.type = type; + return this; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordKeyboardView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordKeyboardView.java new file mode 100644 index 000000000..40b6b1d3c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordKeyboardView.java @@ -0,0 +1,230 @@ +package com.yizhuan.erban.ui.widget.password; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.KeyboardView; +import android.util.AttributeSet; + +import com.yizhuan.erban.R; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Created by lcw on 2016/11/28. + */ + +public class PasswordKeyboardView extends KeyboardView implements KeyboardView.OnKeyboardActionListener{ + + // 用于区分左下角空白的按键 + private static final int KEYCODE_EMPTY = -10; + + private int mDeleteBackgroundColor; + private Rect mDeleteDrawRect; + private Drawable mDeleteDrawable; + + private IOnKeyboardListener mOnKeyboardListener; + + // 0-9 的数字 + private final List keyCodes = Arrays.asList( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); + + public PasswordKeyboardView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0); + } + + public PasswordKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, + int defStyleAttr) { + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.PasswordKeyboardView, defStyleAttr, 0); + mDeleteDrawable = a.getDrawable( + R.styleable.PasswordKeyboardView_pkvDeleteDrawable); + mDeleteBackgroundColor = a.getColor( + R.styleable.PasswordKeyboardView_pkvDeleteBackgroundColor, + Color.parseColor("#f0f0f0")); + a.recycle(); + + // 设置软键盘按键的布局 + Keyboard keyboard = new Keyboard(context, + R.xml.keyboard_number_password); + setKeyboard(keyboard); + + setEnabled(true); + setPreviewEnabled(false); + setOnKeyboardActionListener(this); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // 遍历所有的按键 + List keys = getKeyboard().getKeys(); + for (Keyboard.Key key : keys) { + // 如果是左下角空白的按键,重画按键的背景 + if (key.codes[0] == KEYCODE_EMPTY) { + drawKeyBackground(key, canvas, mDeleteBackgroundColor); + } + // 如果是右下角的删除按键,重画背景,并且绘制删除的图标 + else if (key.codes[0] == Keyboard.KEYCODE_DELETE) { + drawKeyBackground(key, canvas, mDeleteBackgroundColor); + drawDeleteButton(key, canvas); + } + } + } + + // 绘制按键的背景 + private void drawKeyBackground(Keyboard.Key key, Canvas canvas, + int color) { + ColorDrawable drawable = new ColorDrawable(color); + drawable.setBounds(key.x, key.y, + key.x + key.width, key.y + key.height); + drawable.draw(canvas); + } + + // 绘制删除按键 + private void drawDeleteButton(Keyboard.Key key, Canvas canvas) { + if (mDeleteDrawable == null) + return; + + // 计算删除图标绘制的坐标 + if (mDeleteDrawRect == null || mDeleteDrawRect.isEmpty()) { + int intrinsicWidth = mDeleteDrawable.getIntrinsicWidth(); + int intrinsicHeight = mDeleteDrawable.getIntrinsicHeight(); + int drawWidth = intrinsicWidth; + int drawHeight = intrinsicHeight; + + // 限制图标的大小,防止图标超出按键 + if (drawWidth > key.width) { + drawWidth = key.width; + drawHeight = drawWidth * intrinsicHeight / intrinsicWidth; + } + if (drawHeight > key.height) { + drawHeight = key.height; + drawWidth = drawHeight * intrinsicWidth / intrinsicHeight; + } + + // 获取删除图标绘制的坐标 + int left = key.x + (key.width - drawWidth) / 2; + int top = key.y + (key.height - drawHeight) / 2; + mDeleteDrawRect = new Rect(left, top, + left + drawWidth, top + drawHeight); + } + + // 绘制删除的图标 + if (mDeleteDrawRect != null && !mDeleteDrawRect.isEmpty()) { + mDeleteDrawable.setBounds(mDeleteDrawRect.left, + mDeleteDrawRect.top, mDeleteDrawRect.right, + mDeleteDrawRect.bottom); + mDeleteDrawable.draw(canvas); + } + } + + + @Override + public void onPress(int i) { + + } + + @Override + public void onRelease(int i) { + + } + + @Override + public void onKey(int i, int[] ints) { + // 处理按键的点击事件 + // 点击删除按键 + if (i == Keyboard.KEYCODE_DELETE) { + if (mOnKeyboardListener != null) { + mOnKeyboardListener.onDeleteKeyEvent(); + } + } + // 点击了非左下角按键的其他按键 + else if (i != KEYCODE_EMPTY) { + if (mOnKeyboardListener != null) { + mOnKeyboardListener.onInsertKeyEvent( + Character.toString((char) i)); + } + } + } + + @Override + public void onText(CharSequence charSequence) { + + } + + @Override + public void swipeLeft() { + } + + @Override + public void swipeUp() { + } + + @Override + public void swipeRight() { + } + + @Override + public void swipeDown() { + } + + /** + * 设置键盘的监听事件。 + * + * @param listener + * 监听事件 + */ + public void setIOnKeyboardListener(IOnKeyboardListener listener) { + this.mOnKeyboardListener = listener; + } + + public interface IOnKeyboardListener { + + void onInsertKeyEvent(String text); + + void onDeleteKeyEvent(); + } + + /** + * 随机打乱数字键盘上显示的数字顺序。 + */ + public void shuffleKeyboard() { + Keyboard keyboard = getKeyboard(); + if (keyboard != null && keyboard.getKeys() != null + && keyboard.getKeys().size() > 0) { + // 随机排序数字 + Collections.shuffle(keyCodes); + + // 遍历所有的按键 + List keys = getKeyboard().getKeys(); + int index = 0; + for (Keyboard.Key key : keys) { + // 如果按键是数字 + if (key.codes[0] != KEYCODE_EMPTY + && key.codes[0] != Keyboard.KEYCODE_DELETE) { + char code = keyCodes.get(index++); + key.codes[0] = code; + key.label = Character.toString(code); + } + } + // 更新键盘 + setKeyboard(keyboard); + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordView.java b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordView.java new file mode 100644 index 000000000..bbc4541c4 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/password/PasswordView.java @@ -0,0 +1,113 @@ +package com.yizhuan.erban.ui.widget.password; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.jungly.gridpasswordview.GridPasswordView; +import com.yizhuan.erban.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by lcw on 2016/11/28. + */ + +public class PasswordView extends RelativeLayout { + + private View mView; + private ImageView mClose; + private TextView mTitle; + private TextView mForgetPwd; + private GridPasswordView mPassword; + private PasswordKeyboardView mKeyboard; + private List passwordList;//记录键盘输入的值 + private StringBuilder mValue;//最后保存的密码 + + public PasswordView(Context context) { + this(context, null); + } + + public PasswordView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PasswordView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mView = View.inflate(context, R.layout.view_password, null); + + initView(); + initEvent(); + + addView(mView); + } + + private void initView(){ + mPassword = (GridPasswordView) mView.findViewById(R.id.view_password); + mClose = (ImageView) mView.findViewById(R.id.img_close); + mTitle = (TextView) mView.findViewById(R.id.tv_title); + mForgetPwd = (TextView) mView.findViewById(R.id.tv_forgetPwd); + mKeyboard = (PasswordKeyboardView) mView.findViewById(R.id.view_keyboard); + //打乱数字的位置 + //mKeyboard.shuffleKeyboard(); + } + + private void initEvent(){ + mValue = new StringBuilder(); + passwordList = new ArrayList<>(); + mKeyboard.setIOnKeyboardListener(new PasswordKeyboardView.IOnKeyboardListener() { + + @Override + public void onInsertKeyEvent(String text) { + mValue.setLength(0); + passwordList.add(text); + for (int i = 0; i < passwordList.size(); i++) { + mValue.append(passwordList.get(i)); + } + mPassword.setPassword(mValue.toString()); + } + + @Override + public void onDeleteKeyEvent() { + mValue.setLength(0); + if(passwordList.size() != 0){ + passwordList.remove(passwordList.size()-1); + for (int i = 0; i < passwordList.size(); i++) { + mValue.append(passwordList.get(i)); + } + mPassword.setPassword(mValue.toString()); + } + } + }); + } + + //获取输入的密码 + public String getPassword(){ + return mValue.toString(); + } + + //取消 + public ImageView getCloseImageView(){ + return mClose; + } + + //标题 + public TextView getTitleTextView(){ + return mTitle; + } + + //忘记密码 + public TextView getForgetTextView() { + return mForgetPwd; + } + + //输入密码控件 + public GridPasswordView getPswView(){ + return mPassword; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/ColorDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/ColorDecoration.java new file mode 100644 index 000000000..b6670ac49 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/ColorDecoration.java @@ -0,0 +1,228 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.view.View; + +/** + * @author jack + * @Description + * @Date 2018/4/19 + */ +public class ColorDecoration extends RecyclerView.ItemDecoration { + private int mHorizontalSpacing; + private int mVerticalSpacing; + private boolean mIncludeEdge; + private int mColor; + private int ignoreBottomCount = 0; + + private int mMarginStart; + private int mMarginEnd; + private boolean isCusStartAndEnd; + + public ColorDecoration(int color, int hSpacing, int vSpacing, boolean includeEdge) { + mHorizontalSpacing = hSpacing; + mVerticalSpacing = vSpacing; + mIncludeEdge = includeEdge; + this.mColor = color; + } + + /** + * + * @param marginStart + * px + * @param marginEnd + * px + */ + public ColorDecoration(int color, int hSpacing, int vSpacing, boolean includeEdge, int marginStart, int marginEnd) { + mHorizontalSpacing = hSpacing; + mVerticalSpacing = vSpacing; + mIncludeEdge = includeEdge; + this.mColor = color; + + isCusStartAndEnd = true; + mMarginStart = marginStart; + mMarginEnd = marginEnd; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + // Only handle the vertical situation + int position = parent.getChildAdapterPosition(view); + if (parent.getLayoutManager() instanceof GridLayoutManager) { + GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + int column = position % spanCount; + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + int column = lp.getSpanIndex(); + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { + if (((LinearLayoutManager) parent.getLayoutManager()).getOrientation() == LinearLayoutManager.VERTICAL) { + if (mIncludeEdge) { + if (position == 0) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + if (position > 0) { + outRect.top = mVerticalSpacing; + } + } + } else { + if (mIncludeEdge) { + if (position == 0) { + outRect.left = mHorizontalSpacing; + } + outRect.right = mHorizontalSpacing; + } else { + if (position > 0) { + outRect.left = mHorizontalSpacing; + } + } + } + } + + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + super.onDraw(c, parent, state); + if (parent.getLayoutManager() instanceof LinearLayoutManager) { + if (((LinearLayoutManager) parent.getLayoutManager()).getOrientation() == LinearLayoutManager.VERTICAL) { + drawVertical(c, parent); + } else { + drawHorizontal(c, parent); + } + }else{ + c.drawColor(mColor); + } + + } + + + + private void getGridItemOffsets(Rect outRect, int position, int column, int spanCount) { + if (mIncludeEdge) { + outRect.left = mHorizontalSpacing * (spanCount - column) / spanCount; + outRect.right = mHorizontalSpacing * (column + 1) / spanCount; + if (position < spanCount) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + outRect.left = mHorizontalSpacing * column / spanCount; + outRect.right = mHorizontalSpacing * (spanCount - 1 - column) / spanCount; + if (position >= spanCount) { + outRect.top = mVerticalSpacing; + } + } + } + + private final Rect mBounds = new Rect(); + + private void drawVertical(Canvas canvas, RecyclerView parent) { + canvas.save(); + final int left; + final int right; + + if (parent.getClipToPadding()) { + + left = isCusStartAndEnd ? mMarginStart : parent.getPaddingLeft(); + right = parent.getWidth() - (isCusStartAndEnd ? mMarginEnd : parent.getPaddingRight()); + canvas.clipRect(left, parent.getPaddingTop(), right, + parent.getHeight() - parent.getPaddingBottom()); + } else { + left = 0; + right = parent.getWidth(); + } + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + parent.getDecoratedBoundsWithMargins(child, mBounds); + if (mIncludeEdge){ + if (i == 0){ + int top = mBounds.top; + int bottom = mVerticalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + } + int bottom = mBounds.bottom + Math.round(child.getTranslationY()); + int top = bottom - mVerticalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + }else{ + if (i > 0) { + int top = mBounds.top + Math.round(child.getTranslationY()); + int bottom = top + mVerticalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + } + } + + } + canvas.restore(); + } + + private void drawHorizontal(Canvas canvas, RecyclerView parent) { + canvas.save(); + final int top; + final int bottom; + if (parent.getClipToPadding()) { + top = parent.getPaddingTop(); + bottom = parent.getHeight() - parent.getPaddingBottom(); + canvas.clipRect(parent.getPaddingLeft(), top, + parent.getWidth() - parent.getPaddingRight(), bottom); + } else { + top = 0; + bottom = parent.getHeight(); + } + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds); + if(mIncludeEdge){ + if (i == 0){ + int left = mBounds.left; + int right = mHorizontalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + } + int right = mBounds.right + Math.round(child.getTranslationX()); + int left = right - mHorizontalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + }else { + if (i > 0) { + int left = mBounds.left + Math.round(child.getTranslationX()); + int right = left + mHorizontalSpacing; + canvas.save(); + canvas.clipRect(left, top, right, bottom); + canvas.drawColor(mColor); + canvas.restore(); + } + } + } + canvas.restore(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/DividerItemDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/DividerItemDecoration.java new file mode 100644 index 000000000..aa0d45d9c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/DividerItemDecoration.java @@ -0,0 +1,114 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import io.reactivex.annotations.NonNull; + +/** + * Created by hzchenkang on 2016/12/2. + */ + +public class DividerItemDecoration extends RecyclerView.ItemDecoration { + private static final int[] ATTRS = new int[]{ + android.R.attr.listDivider + }; + + public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; + + public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; + + private Drawable mDivider; + + private int mOrientation; + + public DividerItemDecoration(Context context, int orientation) { + final TypedArray a = context.obtainStyledAttributes(ATTRS); + mDivider = a.getDrawable(0); + a.recycle(); + setOrientation(orientation); + } + + public void setOrientation(int orientation) { + if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { + throw new IllegalArgumentException("invalid orientation"); + } + mOrientation = orientation; + } + + public void setDrawable(@NonNull Drawable mDivider) { + this.mDivider = mDivider; + } + + @Override + public void onDraw(Canvas c, RecyclerView parent) { + + if (mOrientation == VERTICAL_LIST) { + drawVertical(c, parent); + } else { + drawHorizontal(c, parent); + } + } + + + protected boolean needDrawDecoration(RecyclerView parent, int position) { + return true; + } + + public void drawVertical(Canvas c, RecyclerView parent) { + final int left = parent.getPaddingLeft(); + final int right = parent.getWidth() - parent.getPaddingRight(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (!needDrawDecoration(parent, i)) { + continue; + } + final View child = parent.getChildAt(i); + RecyclerView v = new RecyclerView(parent.getContext()); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int top = child.getBottom() + params.bottomMargin; + final int bottom = top + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + public void drawHorizontal(Canvas c, RecyclerView parent) { + final int top = parent.getPaddingTop(); + final int bottom = parent.getHeight() - parent.getPaddingBottom(); + + final int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (!needDrawDecoration(parent, i)) { + continue; + } + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child + .getLayoutParams(); + final int left = child.getRight() + params.rightMargin; + final int right = left + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + @Override + public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { + if (!needDrawDecoration(parent, itemPosition)) { + return; + } + if (mOrientation == VERTICAL_LIST) { + outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); + } else { + outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridSpacingItemDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridSpacingItemDecoration.java new file mode 100644 index 000000000..a6149e8ce --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridSpacingItemDecoration.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.content.Context; +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.util.TypedValue; +import android.view.View; + +/** + * 自适应任意列的 GridLayoutManager 的分割块 ItemDecoration + * + */ +public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration { + + private int spanCount; + private int dividerWidth; + private int dividerWidthTop; + private int dividerWidthBottom; + + /** + * @param spanCount gridLayoutManager 列数 + * @param dividerWidthDp 分割块宽高,单位:dp + */ + public GridSpacingItemDecoration(Context context, int spanCount, int dividerWidthDp) { + this.spanCount = spanCount; + this.dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidthDp, context.getResources().getDisplayMetrics()); + this.dividerWidthTop = dividerWidth / 2; + this.dividerWidthBottom = dividerWidth - dividerWidthTop; + } + + @Override + public void getItemOffsets(Rect outRect, View child, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, child, parent, state); + + int pos = parent.getChildAdapterPosition(child); + int column = (pos) % spanCount;// 计算这个child 处于第几列 + + outRect.top = dividerWidthTop; + outRect.bottom = dividerWidthBottom; + + outRect.left = (column * dividerWidth / spanCount); + outRect.right = dividerWidth - (column + 1) * dividerWidth / spanCount; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridVItemDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridVItemDecoration.java new file mode 100644 index 000000000..6344deaff --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/GridVItemDecoration.java @@ -0,0 +1,158 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.content.Context; +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; + +import lombok.Setter; + +/** + * 垂直方向下的格子布局,通用的间隔设置 + * 只适合垂直布局 + * 单位均为dp + * create by lvzebiao @2020/1/2 + */ +public class GridVItemDecoration extends RecyclerView.ItemDecoration { + + private Context context; + + /** + * 水平的分割线 + */ + private int hDivider; + /** + * 垂直的分割线 + */ + private int vDivider; + + private int topDivider; + + private int bottomDivider; + + @Setter + private boolean needLeft; + + @Setter + private boolean needRight; + + @Setter + private boolean needTop; + + @Setter + private boolean needBottom; + + private int spanCount; + + public GridVItemDecoration(Context context, int divider, int spanCount) { + this.context = context; + setDivider(divider); + this.spanCount = spanCount; + } + + @Override + public void getItemOffsets(Rect outRect, View child, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, child, parent, state); + + if (spanCount == 0) { + return; + } + + int pos = parent.getChildAdapterPosition(child); + + outRect.top = 0; + if (isLastRow(parent, pos)) { + outRect.bottom = 0; + } else { + outRect.bottom = hDivider; + } + + if (needTop && pos < spanCount) { + //给第0行添加分割线 + outRect.top = topDivider; + } + + if (needBottom && isLastRow(parent, pos)) { + //给最后一行添加分割线 + outRect.bottom = bottomDivider; + } + + int column = (pos) % spanCount;// 计算这个child 处于第几列 + + if (needLeft) { + if (needRight) { + outRect.left = vDivider - column * vDivider / spanCount; + outRect.right = vDivider / spanCount * (column + 1); + } else { + //这种情况就比较简单 + outRect.left = vDivider; + outRect.right = 0; + } + + } else { + if (needRight) { + outRect.left = 0; + outRect.right = vDivider; + } else { + outRect.left = (column * vDivider / spanCount); + outRect.right = vDivider - (column + 1) * vDivider / spanCount; + } + } + + } + + /** + * 判断是否是最后一行 + */ + private boolean isLastRow(RecyclerView parent, int pos) { + int size = parent.getAdapter().getItemCount(); + + int remainder = size % spanCount; + + LogUtil.print("remainder=" + remainder); + + int temp; + if (remainder == 0) { + temp = size - spanCount; + } else { + temp = size - remainder; + } + LogUtil.print("temp=" + temp); + return pos >= temp; + } + + private void setDivider(int divider) { + this.vDivider = UIUtil.dip2px(context, divider); + setHDivider(divider); + } + + public void setNeedMargin(boolean needMargin) { + needLeft = needTop = needRight = needBottom = needMargin; + } + + /** + * 此方法必须在 {@link #setDivider(int)} 之后调用 + */ + public void setHDivider(int hDivider) { + int px = UIUtil.dip2px(context, hDivider); + this.hDivider = px; + this.topDivider = px; + this.bottomDivider = px; + } + + public void setVDivider(int vDivider) { + this.vDivider = UIUtil.dip2px(context, vDivider); + } + + public void setTopDivider(int topDivider) { + this.topDivider = UIUtil.dip2px(context, topDivider); + } + + public void setBottomDivider(int bottomDivider) { + this.bottomDivider = UIUtil.dip2px(context, bottomDivider); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/HorizontalDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/HorizontalDecoration.java new file mode 100644 index 000000000..4bd3e7b5d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/HorizontalDecoration.java @@ -0,0 +1,55 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import lombok.Setter; + +/** + * 水平的间隔 + * Created by lvzebiao on 2019/1/31. + */ + +public class HorizontalDecoration extends RecyclerView.ItemDecoration { + private int px; + /** + * 如果头需要则为ture + */ + private boolean first; + /** + * 如果尾需要则为ture + */ + private boolean last; + private int side = 0; + + @Setter + private int bottomPx; + + public HorizontalDecoration(int px, boolean first, boolean last) { + this.px = px; + this.first = first; + this.last = last; + this.bottomPx = px; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + int top = 0, bottom = 0; + if (position == 0) { + if (first) { + top = px; + } + bottom = px; + } else if (position == parent.getAdapter().getItemCount() - 1) { + if (last) { + bottom = bottomPx; + } + } else { + bottom = px; + } + outRect.set(0, top, 0, bottom); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/SpacingDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/SpacingDecoration.java new file mode 100644 index 000000000..d430a056a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/SpacingDecoration.java @@ -0,0 +1,72 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.graphics.Rect; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.view.View; + +/** + * Created by huangjun on 2016/12/9. + */ +public class SpacingDecoration extends RecyclerView.ItemDecoration { + private int mHorizontalSpacing = 0; + private int mVerticalSpacing = 0; + private boolean mIncludeEdge = false; + + public SpacingDecoration(int hSpacing, int vSpacing, boolean includeEdge) { + mHorizontalSpacing = hSpacing; + mVerticalSpacing = vSpacing; + mIncludeEdge = includeEdge; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + // Only handle the vertical situation + int position = parent.getChildAdapterPosition(view); + if (parent.getLayoutManager() instanceof GridLayoutManager) { + GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + int column = position % spanCount; + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { + StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager(); + int spanCount = layoutManager.getSpanCount(); + StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + int column = lp.getSpanIndex(); + getGridItemOffsets(outRect, position, column, spanCount); + } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { + outRect.left = mHorizontalSpacing; + outRect.right = mHorizontalSpacing; + if (mIncludeEdge) { + if (position == 0) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + if (position > 0) { + outRect.top = mVerticalSpacing; + } + } + } + } + + private void getGridItemOffsets(Rect outRect, int position, int column, int spanCount) { + if (mIncludeEdge) { + outRect.left = mHorizontalSpacing * (spanCount - column) / spanCount; + outRect.right = mHorizontalSpacing * (column + 1) / spanCount; + if (position < spanCount) { + outRect.top = mVerticalSpacing; + } + outRect.bottom = mVerticalSpacing; + } else { + outRect.left = mHorizontalSpacing * column / spanCount; + outRect.right = mHorizontalSpacing * (spanCount - 1 - column) / spanCount; + if (position >= spanCount) { + outRect.top = mVerticalSpacing; + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/VerticalDecoration.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/VerticalDecoration.java new file mode 100644 index 000000000..083200610 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/decoration/VerticalDecoration.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.ui.widget.recyclerview.decoration; + +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +/** + * Created by lvzebiao on 2018/9/27. + */ + +public class VerticalDecoration extends RecyclerView.ItemDecoration { + + private int px; + /**如果头需要则为ture*/ + private boolean first; + /**如果尾需要则为ture*/ + private boolean last; + + public VerticalDecoration(int px, boolean first, boolean last) { + this.px = px; + this.first = first; + this.last = last; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + int left = 0, right = 0; + if (position == 0) { + if (first) { + left = px; + } + right = px; + } else if (position == parent.getAdapter().getItemCount() - 1) { + if (last) { + right = px; + } + } else { + right = px; + } + outRect.set(left, 0, right, 0); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyGridLayoutManager.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyGridLayoutManager.java new file mode 100644 index 000000000..2553cbf89 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyGridLayoutManager.java @@ -0,0 +1,101 @@ +package com.yizhuan.erban.ui.widget.recyclerview.layoutmanager; + +import android.content.Context; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +/** + * Created by jack on 2018/4/16. + */ + +public class FullyGridLayoutManager extends GridLayoutManager { + public FullyGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public FullyGridLayoutManager(Context context, int spanCount) { + super(context, spanCount); + } + + public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { + super(context, spanCount, orientation, reverseLayout); + } + + private int[] mMeasuredDimension = new int[2]; + + @Override + public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { + final int widthMode = View.MeasureSpec.getMode(widthSpec); + final int heightMode = View.MeasureSpec.getMode(heightSpec); + final int widthSize = View.MeasureSpec.getSize(widthSpec); + final int heightSize = View.MeasureSpec.getSize(heightSpec); + + int width = 0; + int height = 0; + int count = getItemCount(); + int span = getSpanCount(); + for (int i = 0; i < count; i++) { + measureScrapChild(recycler, i, + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + mMeasuredDimension); + + if (getOrientation() == HORIZONTAL) { + if (i % span == 0) { + width = width + mMeasuredDimension[0]; + } + if (i == 0) { + height = mMeasuredDimension[1]; + } + } else { + if (i % span == 0) { + height = height + mMeasuredDimension[1]; + } + if (i == 0) { + width = mMeasuredDimension[0]; + } + } + } + + switch (widthMode) { + case View.MeasureSpec.EXACTLY: + width = widthSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + switch (heightMode) { + case View.MeasureSpec.EXACTLY: + height = heightSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + setMeasuredDimension(width, height); + } + + private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, + int heightSpec, int[] measuredDimension) { + if (getItemCount() > 0 && position < getItemCount()) { + try { + View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsException + if (view != null) { + RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, + getPaddingLeft() + getPaddingRight(), p.width); + int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, + getPaddingTop() + getPaddingBottom(), p.height); + view.measure(childWidthSpec, childHeightSpec); + measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; + measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; + recycler.recycleView(view); + } + } catch (Exception e) { +// e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyLinearLayoutManager.java b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyLinearLayoutManager.java new file mode 100644 index 000000000..607cb493f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/widget/recyclerview/layoutmanager/FullyLinearLayoutManager.java @@ -0,0 +1,98 @@ +package com.yizhuan.erban.ui.widget.recyclerview.layoutmanager; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + + +public class FullyLinearLayoutManager extends LinearLayoutManager { + public FullyLinearLayoutManager(Context context) { + super(context); + } + + public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public FullyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + private int[] mMeasuredDimension = new int[2]; + + @Override + public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, + int widthSpec, int heightSpec) { + + final int widthMode = View.MeasureSpec.getMode(widthSpec); + final int heightMode = View.MeasureSpec.getMode(heightSpec); + final int widthSize = View.MeasureSpec.getSize(widthSpec); + final int heightSize = View.MeasureSpec.getSize(heightSpec); + + int width = 0; + int height = 0; + for (int i = 0; i < getItemCount(); i++) { + measureScrapChild(recycler, i, + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), + mMeasuredDimension); + + if (getOrientation() == HORIZONTAL) { + width = width + mMeasuredDimension[0]; + if (i == 0) { + height = mMeasuredDimension[1]; + } + } else { + height = height + mMeasuredDimension[1]; + if (i == 0) { + width = mMeasuredDimension[0]; + } + } + } + switch (widthMode) { + case View.MeasureSpec.EXACTLY: + width = widthSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + switch (heightMode) { + case View.MeasureSpec.EXACTLY: + height = heightSize; + case View.MeasureSpec.AT_MOST: + case View.MeasureSpec.UNSPECIFIED: + } + + setMeasuredDimension(width, height); + } + + private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, + int heightSpec, int[] measuredDimension) { + if (getItemCount() > 0 && position < getItemCount()) { + try { + View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsException + if (view != null) { + RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); + + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, + getPaddingLeft() + getPaddingRight(), p.width); + + int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, + getPaddingTop() + getPaddingBottom(), p.height); + + view.measure(childWidthSpec, childHeightSpec); + measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; + measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; + recycler.recycleView(view); + } + } catch (Exception e) { +// e.printStackTrace(); + } finally { + } + } + + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/withdraw/BinderAlipayActivity.java b/app/src/main/java/com/yizhuan/erban/ui/withdraw/BinderAlipayActivity.java new file mode 100644 index 000000000..4f3f58cb3 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/withdraw/BinderAlipayActivity.java @@ -0,0 +1,233 @@ +package com.yizhuan.erban.ui.withdraw; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.ui.login.CodeDownTimer; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.redPacket.bean.RedPacketInfo; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrawInfo; +import com.yizhuan.xchat_android_library.utils.FormatUtils; + +import java.text.MessageFormat; + +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleSource; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; + +public class BinderAlipayActivity extends BaseActivity { + private EditText etAlipayAccount; + private EditText etAlipayName; + private EditText etSmsCode; + private ImageView ivNameDelete; + private ImageView ivCodeDelete; + private Button btnGetCode; + private Button btnBinder; + private Button btnBinderRquest; + private TextView tvSendSmsCodeResult; + + private CodeDownTimer timer; + + + private TextWatcher textWatcher; + + public static void start(Context context, WithdrawInfo withdrawInfo) { + Intent intent = new Intent(context, BinderAlipayActivity.class); + if (withdrawInfo != null) { + Bundle mBundle = new Bundle(); + mBundle.putSerializable("withdrawInfo", withdrawInfo); + intent.putExtras(mBundle); + } + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_binder_alipay); + initTitleBar("绑定支付宝"); + initView(); + initData(); + onSetListener(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stopCountDownTimer(); + } + + private void onSetListener() { + ivNameDelete.setOnClickListener(v -> etAlipayName.setText("")); + ivCodeDelete.setOnClickListener(v -> etSmsCode.setText("")); + //获取绑定支付宝验证码 + btnGetCode.setOnClickListener(v -> { + startCountDownTimer(); + StringBuffer phoneSB = new StringBuffer(); + + UserModel.get().getUserInfo(AuthModel.get().getCurrentUid()) + .flatMap(new Function>() { + @Override + public SingleSource apply(UserInfo userInfo) throws Exception { + if (userInfo.isBindPhone()){ + String phone = userInfo.getPhone(); + phoneSB.append(phone); + return CodeModel.get().sendCode(phone, CodeType.BIND_ALI); + }else { + return Single.error(new Throwable("没有绑定手机号。")); + } + + } + }) + .compose(bindToLifecycle()) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(String s) { + String phoneMod = FormatUtils.formatPhoneNumWithPrivacy(phoneSB.toString(),3,7); + String msg = MessageFormat.format(getResources().getString(R.string.tips_bind_alipay_sms_code), phoneMod); + onGetSmsCode(msg); + } + + @Override + public void onError(Throwable e) { + onGetSmsCodeFail(e.getMessage()); + } + }); + tvSendSmsCodeResult.setText(""); + }); + + //请求绑定支付宝 + btnBinderRquest.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// System.out.println("aliPayAccount"+aliPayAccount+"aliPayAccountName"+aliPayAccountName+"code"+code); + WithdrawModel.get().binderAlipay( + etAlipayAccount.getText().toString(), + etAlipayName.getText().toString(), + etSmsCode.getText().toString()) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + onBinderAlipayFail(error); + } + + @Override + public void onSuccess(String s) { + onBinderAlipay(); + } + }); + } + }); + //输入框监听改变 + textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (etAlipayAccount.getText() != null && etAlipayAccount.getText().length() > 0 + && etAlipayName.getText() != null && etAlipayName.getText().length() > 0 + && etSmsCode.getText() != null && etSmsCode.getText().length() > 0) { + btnBinder.setVisibility(View.GONE); + btnBinderRquest.setVisibility(View.VISIBLE); + } else { + btnBinder.setVisibility(View.VISIBLE); + btnBinderRquest.setVisibility(View.GONE); + } + } + }; + + etAlipayAccount.addTextChangedListener(textWatcher); + etAlipayName.addTextChangedListener(textWatcher); + etSmsCode.addTextChangedListener(textWatcher); + + } + + public void onGetSmsCode(String msg) { + tvSendSmsCodeResult.setText(msg); + } + + public void onGetSmsCodeFail(String error) { + toast(error); + } + + + public void onBinderAlipay() { + toast("绑定成功"); + finish(); + } + + public void onBinderAlipayFail(String error) { + toast(error); + } + + private void initData() { + WithdrawInfo info = (WithdrawInfo) getIntent().getSerializableExtra("withdrawInfo"); + RedPacketInfo redPacketInfos = (RedPacketInfo) getIntent().getSerializableExtra("redPacketInfo"); + if (info != null && info.isNotBoundPhone != null && !info.isNotBoundPhone) { + etAlipayAccount.setText(info.alipayAccount); + etAlipayName.setText(info.alipayAccountName); + } + } + + private void initView() { + etAlipayAccount = (EditText) findViewById(R.id.et_phone); + /* //不需要判断支付宝账号格式,布局里面也不要写type=phone + etAlipayAccount.addValidator(new AccountValidator("Only Integer Valid!", "\\d+")); + etAlipayAccount.setFilters(new InputFilter[]{new InputFilter.LengthFilter(11)});*/ + etAlipayName = (EditText) findViewById(R.id.et_name); + etSmsCode = (EditText) findViewById(R.id.et_smscode); + etSmsCode.setFilters(new InputFilter[]{new InputFilter.LengthFilter(5)}); + ivNameDelete = findViewById(R.id.iv_name_delete); + ivCodeDelete = findViewById(R.id.iv_code_delete); + btnGetCode = (Button) findViewById(R.id.btn_get_code); + btnBinder = (Button) findViewById(R.id.btn_binder); + btnBinderRquest = (Button) findViewById(R.id.btn_binder_request); + tvSendSmsCodeResult = (TextView) findViewById(R.id.tv_send_sms_code_result); + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(btnGetCode, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawActivity.java b/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawActivity.java new file mode 100644 index 000000000..969d1091a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawActivity.java @@ -0,0 +1,506 @@ +package com.yizhuan.erban.ui.withdraw; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.bills.activities.WithdrawBillsActivity; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.setting.ModifyPwdActivity; +import com.yizhuan.erban.ui.wallet.adapter.WithdrawJewelAdapter; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.erban.ui.widget.password.PassWordFragment; +import com.yizhuan.erban.ui.withdraw.bankcard.BindWithdrawBankCardActivity; +import com.yizhuan.erban.utils.SpannableBuilder; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.initial.bean.TaxInfo; +import com.yizhuan.xchat_android_core.pay.bean.NotRealNameYetException; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.BeanObserver; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; +import com.yizhuan.xchat_android_core.withdraw.bean.ExchangerInfo; +import com.yizhuan.xchat_android_core.withdraw.bean.RefreshInfo; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrawInfo; +import com.yizhuan.xchat_android_core.withdraw.bean.WithdrwaListInfo; +import com.yizhuan.xchat_android_library.utils.FormatUtils; +import com.yizhuan.xchat_android_library.utils.ListUtils; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; + +/** + * 钻石提现 + */ +public class WithdrawActivity extends BaseActivity { + + @BindView(R.id.tv_withdraw_type) + TextView tvWithdrawType; + @BindView(R.id.zhifubao) + ImageView zhifubao; + @BindView(R.id.tv_tax_money) + TextView tvTaxMoney; + @BindView(R.id.tv_income_money) + TextView tvIncomeMoney; + + private TitleBar mTitleBar; + private TextView alipayAccount; + private TextView alipayName; + private TextView diamondNumWithdraw; + private FrameLayout binder; + private RelativeLayout binderSucceed; + private RecyclerView mRecyclerView; + private Button btnWithdraw; + private Button unBtnWithdraw; + private WithdrawJewelAdapter mJewelAdapter; + public WithdrwaListInfo checkedPosition; + private WithdrawInfo withdrawInfos = new WithdrawInfo(); + private TextView tvTip; + private TextView tvWithdrawRule; + + private int withdrawAccountType = WithdrawInfo.ACCOUNT_TYPE_ALIPAY; + /** + * 如果成功加载提现信息,此字段才为true + */ + private boolean loadedWithdrawInfo = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_withdraw); + ButterKnife.bind(this); + EventBus.getDefault().register(this); + initTitleBar(getString(R.string.withdraw)); + initView(); + setListener(); + initData(); + } + + private void initData() { + mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3)); + mRecyclerView.setNestedScrollingEnabled(false); + mJewelAdapter = new WithdrawJewelAdapter(); + mJewelAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() { + @Override + public void onItemClick(BaseQuickAdapter baseQuickAdapter, View view, int position) { + List list = mJewelAdapter.getData(); + if (ListUtils.isListEmpty(list)) return; + int size = list.size(); + for (int i = 0; i < size; i++) { + list.get(i).isSelected = position == i; + } + mJewelAdapter.notifyDataSetChanged(); + checkedPosition = list.get(position); + + updateWithdrawView(); + updateIncomeMoney(); + if (isWithdraw()) { + btnWithdraw.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!loadedWithdrawInfo || withdrawInfos == null) { + toast("提现信息未加载成功,请关闭界面重试"); + return; + } + if (checkedPosition == null) { + toast("请先选择要提现的金额"); + return; + } + + if (!withdrawInfos.isBindAlipay()) { + getDialogManager().showOkCancelWithTitleDialog("请先绑定支付宝", "去绑定", + () -> BinderAlipayActivity.start(context, withdrawInfos)); + return; + } + + if (!withdrawInfos.isBindBankCard() + && checkedPosition.getCashNum() >= withdrawInfos.getBankCardMinAmount()) { + showBindBankCardDialog(); + return; + } + + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + if (userInfo.isBindPaymentPwd()) { + //发起兑换 + getDialogManager().showOkCancelDialog( + "您将要兑换" + checkedPosition.getCashProdName(), + true, new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + getDialogManager().dismissDialog(); + } + + @Override + public void onOk() { + getDialogManager().dismissDialog(); + if (checkedPosition != null) { + PassWordFragment.newInstace(0).show(getSupportFragmentManager()); + } else { + toast("兑换失败"); + } + } + }); + } else { + ModifyPwdActivity.start(WithdrawActivity.this, ModifyPwdActivity.FOGERT_PAY_PWD); + } + + } + } + }); + } + } + }); + mRecyclerView.setAdapter(mJewelAdapter); + loadAlipayInfo(); + loadRecyclerViewData(); + + //提示语 + TaxInfo texInfo = WithdrawModel.get().getTaxInfo(); + if (null != texInfo) { + tvTip.setVisibility(View.VISIBLE); + tvTip.setText(texInfo.getTips()); + } else { + tvTip.setVisibility(View.GONE); + } + } + + @SuppressLint("CheckResult") + public void commit(String pwd) { + //1 提现到支付宝 3-提现到银行卡 如果是大额提现,只能 提现到银行卡 + int paramType; + if (isBigMoneyWithdraw()) { + paramType = WithdrawInfo.ACCOUNT_TYPE_BANK_CARD; + } else { + paramType = withdrawAccountType; + } + WithdrawModel.get().requestExchange( + AuthModel.get().getCurrentUid(), + checkedPosition.cashProdId, DESAndBase64(pwd), paramType + ).subscribe((exchangerInfo, throwable) -> { + if (throwable == null) { + onRequestExchange(exchangerInfo); + } else { + if (throwable instanceof NotRealNameYetException) { + NotRealNameYetException exception = (NotRealNameYetException) throwable; + getDialogManager().showTipsDialog(getString(R.string.tips_need_to_certification), + getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(WithdrawActivity.this, + UriProvider.getTutuRealNamePage()); + } + }); + } else { + throwable.printStackTrace(); + toast(throwable.getMessage()); + } + } + }); + } + + private void loadAlipayInfo() { + WithdrawModel.get().getWithdrawUserInfo( + AuthModel.get().getCurrentUid() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SingleObserver() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(WithdrawInfo withdrawInfo) { + onGetWithdrawUserInfo(withdrawInfo); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + public void onGetWithdrawUserInfo(WithdrawInfo withdrawInfo) { + if (withdrawInfo == null) { + loadedWithdrawInfo = false; + return; + } + loadedWithdrawInfo = true; + withdrawInfos = withdrawInfo; + diamondNumWithdraw.setText(FormatUtils.formatBigDecimal(withdrawInfo.diamondNum)); + + withdrawAccountType = withdrawInfos.getDefaultWithdrawAccountType(); + + tvWithdrawType.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (withdrawAccountType == WithdrawInfo.ACCOUNT_TYPE_ALIPAY) { + //切到银行卡 + withdrawAccountType = WithdrawInfo.ACCOUNT_TYPE_BANK_CARD; + } else { + //切到支付宝 + withdrawAccountType = WithdrawInfo.ACCOUNT_TYPE_ALIPAY; + } + + updateWithdrawView(); + } + }); + + updateWithdrawView(); + } + + /** + * 更新提现信息 或者 选中提现item时 更新View显示 + */ + private void updateWithdrawView() { + if (withdrawInfos == null) { + return; + } + if (!loadedWithdrawInfo) { + return; + } + + if (withdrawAccountType == WithdrawInfo.ACCOUNT_TYPE_BANK_CARD) { + tvWithdrawType.setText(R.string.withdraw_type_alipay); + } else { + tvWithdrawType.setText(R.string.withdraw_type_bank_card); + } + + //切换按钮是否展示 + tvWithdrawType.setVisibility(View.VISIBLE); + //选中大额、没有绑卡、后台关闭 的情况下,不显示切换按钮 + if (isBigMoneyWithdraw() || !withdrawInfos.isBindBankCard() || !withdrawInfos.isSwitchButtonShow()) { + tvWithdrawType.setVisibility(View.INVISIBLE); + } + + binderSucceed.setOnClickListener(null); + if (!isBindAliAccount()) { + binder.setVisibility(View.VISIBLE); + binderSucceed.setVisibility(View.GONE); + } else { + binder.setVisibility(View.GONE); + binderSucceed.setVisibility(View.VISIBLE); + zhifubao.setImageResource(R.drawable.icon_zhifubao); + alipayAccount.setText(getString(R.string.withdraw_format_alipay_account, withdrawInfos.alipayAccount)); + alipayName.setText(getString(R.string.withdraw_format_alipay_name, withdrawInfos.alipayAccountName)); + + //用户点击修改支付宝信息 + binderSucceed.setOnClickListener(v -> BinderAlipayActivity.start(context, withdrawInfos)); + + //大额提现显示银行卡,后台配置默认是银行卡时,也显示银行卡 + if ((isBigMoneyWithdraw() || withdrawAccountType == WithdrawInfo.ACCOUNT_TYPE_BANK_CARD) + && withdrawInfos.isBindBankCard()) { + zhifubao.setImageResource(R.drawable.icon_withdraw_bank_card); + alipayAccount.setText(getString(R.string.withdraw_format_bank_card_account, withdrawInfos.getBankCardNum())); + alipayName.setText(getString(R.string.withdraw_format_bank_card_name, withdrawInfos.getBankCardName())); + //用户点击修改银行卡信息 + binderSucceed.setOnClickListener(v -> start(context, BindWithdrawBankCardActivity.class)); + } + } + } + + /** + * 更新手续费、收入金额 + */ + private void updateIncomeMoney() { + if (checkedPosition == null) { + return; + } + + tvTaxMoney.setText(getString(R.string.withdraw_format_tax_money, + String.valueOf(checkedPosition.getWithdrawalFee()))); + tvIncomeMoney.setText(getString(R.string.withdraw_format_income_money, + String.valueOf(checkedPosition.getActualArrival()))); + + } + + /** + * 判断是否大额提现 + */ + private boolean isBigMoneyWithdraw() { + return loadedWithdrawInfo && withdrawInfos != null && checkedPosition != null && + checkedPosition.getCashNum() >= withdrawInfos.getBankCardMinAmount(); + } + + /** + * 是否绑定支付宝 + */ + private boolean isBindAliAccount() { + return withdrawInfos != null && !TextUtils.isEmpty(withdrawInfos.alipayAccount) && !withdrawInfos.alipayAccount.equals("null"); + } + + private void loadRecyclerViewData() { + WithdrawModel.get().getWithdrawList() + .subscribe(new BeanObserver>() { + @Override + public void onSuccess(List withdrwaListInfos) { + onGetWithdrawList(withdrwaListInfos); + } + + @Override + public void onErrorMsg(String error) { + onGetWithdrawListFail(error); + } + }); + } + + public void onGetWithdrawList(List withdrwaListInfo) { + if (withdrwaListInfo != null && withdrwaListInfo.size() > 0) { + mJewelAdapter.setNewData(withdrwaListInfo); + } + } + + public void onGetWithdrawListFail(String error) { + toast("获取提现列表失败"); + } + + + private void setListener() { + //用户点击绑定支付宝 + binder.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //跳转绑定手机号码,绑定成功以后显示bindersucceed + BinderAlipayActivity.start(context, withdrawInfos); + } + }); + + tvWithdrawRule.setOnClickListener(v -> CommonWebViewActivity.start( + context, UriProvider.IM_SERVER_URL + "/modules/guide/output.html")); + + //切换类型 + tvWithdrawType.setVisibility(View.GONE); + tvWithdrawType.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + } + + private boolean isWithdraw() { + if (withdrawInfos == null || withdrawInfos.isNotBoundPhone == null) { + return false; + } + if (!withdrawInfos.isNotBoundPhone) { + if (checkedPosition != null) { + //用户的钻石余额 > 选中金额的钻石数时 + if (withdrawInfos.diamondNum >= checkedPosition.diamondNum) { + unBtnWithdraw.setVisibility(View.GONE); + btnWithdraw.setVisibility(View.VISIBLE); + return true; + } else { + unBtnWithdraw.setVisibility(View.VISIBLE); + btnWithdraw.setVisibility(View.GONE); + return true; + } + } + } else { + return false; + } + //如果选中position不为空的时候 + return false; + } + + private void onRequestExchange(ExchangerInfo exchangerInfo) { + if (exchangerInfo != null) { + diamondNumWithdraw.setText(FormatUtils.formatBigDecimal(exchangerInfo.diamondNum)); + toast("提现成功"); + } + } + + private void initView() { + diamondNumWithdraw = (TextView) findViewById(R.id.tv_diamondNums); + binder = (FrameLayout) findViewById(R.id.rly_binder); + binderSucceed = (RelativeLayout) findViewById(R.id.rly_binder_succeed); + alipayAccount = (TextView) findViewById(R.id.tv_user_zhifubao); + alipayName = (TextView) findViewById(R.id.tv_user_zhifubao_name); + mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); + btnWithdraw = (Button) findViewById(R.id.btn_withdraw); + unBtnWithdraw = (Button) findViewById(R.id.btn_withdraw_un); + tvTip = (TextView) findViewById(R.id.tv_tip); + tvWithdrawRule = findViewById(R.id.tv_withdraw_rule); + tvWithdrawType.setVisibility(View.INVISIBLE); + tvTaxMoney.setText(""); + tvIncomeMoney.setText(""); + } + + public void initTitleBar(String title) { + mTitleBar = (TitleBar) findViewById(R.id.title_bar); + if (mTitleBar != null) { + mTitleBar.setTitle(title); + mTitleBar.setImmersive(false); + mTitleBar.setTitleColor(getResources().getColor(R.color.black)); + mTitleBar.setLeftImageResource(R.drawable.arrow_left); + mTitleBar.setLeftClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } + mTitleBar.setActionTextColor(getResources().getColor(R.color.text_tertiary)); + mTitleBar.addAction(new TitleBar.TextAction("提现记录") { + @Override + public void performAction(View view) { + startActivity(new Intent(getApplicationContext(), WithdrawBillsActivity.class)); + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void refreshEvent(RefreshInfo refreshInfo) { + loadAlipayInfo(); + } + + private void showBindBankCardDialog() { + if (withdrawInfos == null) { + return; + } + SpannableBuilder builder = new SpannableBuilder(); + builder.append("为了保障你的资金安全\n单次提现金额") + .append("达到" + withdrawInfos.getBankCardMinAmount(), + new ForegroundColorSpan(getResources().getColor(R.color.color_FF3B30))) + .append("人民币\n仅支持提现到银行卡\n") + .append("请先绑定银行卡", + new ForegroundColorSpan(getResources().getColor(R.color.color_FF3B30))); + getDialogManager().showOkCancelWithTitleDialog(builder.build(), "去绑定", + () -> start(context, BindWithdrawBankCardActivity.class)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawRuleActivity.java b/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawRuleActivity.java new file mode 100644 index 000000000..d8ad882a5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/withdraw/WithdrawRuleActivity.java @@ -0,0 +1,20 @@ +package com.yizhuan.erban.ui.withdraw; + +import android.os.Bundle; +import android.webkit.WebView; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.xchat_android_core.UriProvider; + +public class WithdrawRuleActivity extends BaseActivity { + private WebView mWebView; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_withdraw_rule); + initTitleBar("提现规则"); + mWebView = (WebView) findViewById(R.id.wv_view); + mWebView.loadUrl(UriProvider.IM_SERVER_URL+"/modules/guide/withdraw.html"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/ui/withdraw/bankcard/BindWithdrawBankCardActivity.java b/app/src/main/java/com/yizhuan/erban/ui/withdraw/bankcard/BindWithdrawBankCardActivity.java new file mode 100644 index 000000000..7546d51e8 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/ui/withdraw/bankcard/BindWithdrawBankCardActivity.java @@ -0,0 +1,182 @@ +package com.yizhuan.erban.ui.withdraw.bankcard; + +import android.os.Bundle; +import android.support.design.widget.TextInputEditText; +import android.text.Editable; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import com.trello.rxlifecycle2.android.ActivityEvent; +import com.yizhuan.erban.R; +import com.yizhuan.erban.base.BaseActivity; +import com.yizhuan.erban.base.TitleBar; +import com.yizhuan.erban.ui.login.CodeDownTimer; +import com.yizhuan.erban.ui.widget.TextWatcherSimple; +import com.yizhuan.xchat_android_core.code.CodeModel; +import com.yizhuan.xchat_android_core.code.CodeType; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.withdraw.WithdrawModel; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * create by lvzebiao @2019/12/24 + */ +public class BindWithdrawBankCardActivity extends BaseActivity { + + @BindView(R.id.et_bank_card_number) + TextInputEditText etBankCardNumber; + @BindView(R.id.et_bank_card_bind_sms_code) + TextInputEditText etBankCardBindSmsCode; + @BindView(R.id.btn_get_code) + Button btnGetCode; + @BindView(R.id.tv_bind_bank_card) + TextView tvBindBankCard; + @BindView(R.id.tv_tips_withdraw_bank_card) + TextView tvTipsWithdrawBankCard; + @BindView(R.id.et_bank_card_name) + TextInputEditText etBankCardName; + @BindView(R.id.title_bar) + TitleBar titleBar; + @BindView(R.id.tv_code_tips) + TextView tvCodeTips; + + private CodeDownTimer timer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bind_withdraw_bank_card); + ButterKnife.bind(this); + initTitleBar(R.string.text_setting_bind_bank_card_account); + initView(); + initData(); + } + + private void initView() { + etBankCardNumber.addTextChangedListener(new CustomTextWather()); + etBankCardName.addTextChangedListener(new CustomTextWather()); + etBankCardBindSmsCode.addTextChangedListener(new CustomTextWather()); + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + String bankCardNumPlain = userInfo.getBankCardNumPlain(); + if (!TextUtils.isEmpty(bankCardNumPlain)) { + etBankCardNumber.setText(bankCardNumPlain); + etBankCardNumber.setSelection(bankCardNumPlain.length()); + } + String bankCardName = userInfo.getBankCardName(); + if (!TextUtils.isEmpty(bankCardName)) { + etBankCardName.setText(bankCardName); + etBankCardName.setSelection(bankCardName.length()); + } + } + + } + + private void initData() { + WithdrawModel.get().getBindBankCardTips() + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .doOnSuccess(s -> { + tvTipsWithdrawBankCard.setText(s); + }) + .subscribe(); + } + + @OnClick({R.id.btn_get_code, R.id.tv_bind_bank_card}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.btn_get_code: + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + return; + } + String phone = userInfo.getPhone(); + if (TextUtils.isEmpty(phone)) { + toast("请先绑定手机号"); + return; + } + getDialogManager().showProgressDialog(context, true); + CodeModel.get().sendCode(phone, CodeType.BIND_WITHDRAW_BANK_CARD) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + getDialogManager().dismissDialog(); + if (error != null) { + toast(error); + } else { + toast(s); + tvCodeTips.setText( + getString(R.string.withdraw_bank_card_code_tips, phone)); + startCountDownTimer(); + } + } + }); + break; + case R.id.tv_bind_bank_card: + getDialogManager().showProgressDialog(context, true); + WithdrawModel.get().bindBankCard( + etBankCardNumber.getText().toString(), + etBankCardName.getText().toString(), + etBankCardBindSmsCode.getText().toString() + ) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + getDialogManager().dismissDialog(); + if (error != null) { + toast(error); + } else { + toast("绑定提现银行卡成功"); + hideIME(); + finish(); + } + } + }); + break; + } + } + + private void updateViewStatus() { + boolean enable = !TextUtils.isEmpty(etBankCardNumber.getText().toString()) + && !TextUtils.isEmpty(etBankCardName.getText().toString()) + && !TextUtils.isEmpty(etBankCardBindSmsCode.getText().toString()); + tvBindBankCard.setEnabled(enable); + } + + private class CustomTextWather extends TextWatcherSimple { + + @Override + public void afterTextChanged(Editable s) { + updateViewStatus(); + } + } + + private void startCountDownTimer() { + stopCountDownTimer(); + timer = new CodeDownTimer(btnGetCode, 60000, 1000); + timer.start(); + } + + private void stopCountDownTimer() { + if (timer != null) { + timer.cancel(); + timer = null; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + stopCountDownTimer(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/ActWhiteListMrg.java b/app/src/main/java/com/yizhuan/erban/utils/ActWhiteListMrg.java new file mode 100644 index 000000000..a2f770669 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/ActWhiteListMrg.java @@ -0,0 +1,45 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.yizhuan.erban.MiddleActivity; +import com.yizhuan.erban.NimMiddleActivity; +import com.yizhuan.erban.other.activity.SplashActivity; +import com.yizhuan.erban.ui.login.ErbanQQMemberBindAndLoginActivity; +import com.yizhuan.xchat_android_core.pay.PaymentActivity; +import com.yizhuan.xchat_android_core.utils.ActivityUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 一些Activity的白名单管理,比如不需要弹升级窗 + * create by lvzebiao @2019/8/14 + */ +public class ActWhiteListMrg { + + /** + * 过滤掉一些中转的activity,不进行入栈管理 + */ + public static boolean isTempActivity(Context currContext) { + if (!ActivityUtil.isCanShowAppCompatDialog(currContext)) { + return true; + } + List acts = new ArrayList<>(); + acts.add(MiddleActivity.class); + acts.add(NimMiddleActivity.class); + acts.add(ErbanQQMemberBindAndLoginActivity.class); + acts.add(PaymentActivity.class); + acts.add(SplashActivity.class); + + for (Class act : acts) { + if (act.isInstance(currContext)) { + LogUtil.print("中转Activity:" + currContext.getClass().getSimpleName()); + return true; + } + } + return false; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/AppBarStateChangeListener.java b/app/src/main/java/com/yizhuan/erban/utils/AppBarStateChangeListener.java new file mode 100644 index 000000000..fae84a067 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/AppBarStateChangeListener.java @@ -0,0 +1,36 @@ +package com.yizhuan.erban.utils; + +import android.support.design.widget.AppBarLayout; + +public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener { + + public enum State { + EXPANDED, + COLLAPSED, + IDLE + } + + private State mCurrentState = State.IDLE; + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if (verticalOffset == 0) { + if (mCurrentState != State.EXPANDED) { + onStateChanged(appBarLayout, State.EXPANDED); + } + mCurrentState = State.EXPANDED; + } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) { + if (mCurrentState != State.COLLAPSED) { + onStateChanged(appBarLayout, State.COLLAPSED); + } + mCurrentState = State.COLLAPSED; + } else { + if (mCurrentState != State.IDLE) { + onStateChanged(appBarLayout, State.IDLE); + } + mCurrentState = State.IDLE; + } + } + + public abstract void onStateChanged(AppBarLayout appBarLayout, State state); +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/BlurTransformation.java b/app/src/main/java/com/yizhuan/erban/utils/BlurTransformation.java new file mode 100644 index 000000000..03811b337 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/BlurTransformation.java @@ -0,0 +1,94 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Build; +import android.renderscript.RSRuntimeException; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.Transformation; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapResource; + +import java.security.MessageDigest; + +public class BlurTransformation implements Transformation { + + private static int MAX_RADIUS = 25; + private static int DEFAULT_DOWN_SAMPLING = 1; + + private Context mContext; + private BitmapPool mBitmapPool; + + private int mRadius; + private int mSampling; + + public BlurTransformation(Context context) { + this(context, Glide.get(context).getBitmapPool(), MAX_RADIUS, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, BitmapPool pool) { + this(context, pool, MAX_RADIUS, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, BitmapPool pool, int radius) { + this(context, pool, radius, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, int radius) { + this(context, Glide.get(context).getBitmapPool(), radius, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, int radius, int sampling) { + this(context, Glide.get(context).getBitmapPool(), radius, sampling); + } + + public BlurTransformation(Context context, BitmapPool pool, int radius, int sampling) { + mContext = context.getApplicationContext(); + mBitmapPool = pool; + mRadius = radius; + mSampling = sampling; + } + + @Override + public Resource transform(Context context, Resource resource, int i, int i1) { + Bitmap source = resource.get(); + + int width = source.getWidth(); + int height = source.getHeight(); + int scaledWidth = width / mSampling; + int scaledHeight = height / mSampling; + + Bitmap bitmap = mBitmapPool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(bitmap); + canvas.scale(1 / (float) mSampling, 1 / (float) mSampling); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(source, 0, 0, paint); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + try { + bitmap = RSBlur.blur(mContext, bitmap, mRadius); + } catch (RSRuntimeException e) { + bitmap = FastBlur.blur(bitmap, mRadius, true); + } + } else { + bitmap = FastBlur.blur(bitmap, mRadius, true); + } + + return BitmapResource.obtain(bitmap, mBitmapPool); + } + + @Override + public void updateDiskCacheKey(MessageDigest messageDigest) { + String key = "BlurTransformation(radius=" + mRadius + ", sampling=" + mSampling + ")"; + messageDigest.update(key.getBytes()); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/BuglyFileProvider.java b/app/src/main/java/com/yizhuan/erban/utils/BuglyFileProvider.java new file mode 100644 index 000000000..7ad8b87d9 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/BuglyFileProvider.java @@ -0,0 +1,12 @@ +package com.yizhuan.erban.utils; + +import android.support.v4.content.FileProvider; + +/** + *

使用的第三方库也配置了同样的FileProvider, 可以通过继承FileProvider类来解决合并冲突的问题

+ * + * @author Administrator + * @date 2017/12/5 + */ +public class BuglyFileProvider extends FileProvider { +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/CertificateHelper.java b/app/src/main/java/com/yizhuan/erban/utils/CertificateHelper.java new file mode 100644 index 000000000..5d2fa01a5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/CertificateHelper.java @@ -0,0 +1,118 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; + +import com.yizhuan.erban.R; +import com.yizhuan.erban.common.widget.dialog.DialogManager; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.UriProvider; +import com.yizhuan.xchat_android_core.certification.CertificationModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_FORCE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_GUIDE; +import static com.yizhuan.xchat_android_core.certification.CertificationModel.CER_TYPE_NONE; + +/** + * 强制用户实名认证 + */ +public class CertificateHelper { + + private Context mContext; + private DialogManager mDialogManager; + private CertificateStatusListener mCertificateStatusListener; + + public CertificateHelper(Context mContext, CertificateStatusListener certificateStatusListener) { + this.mContext = mContext; + mDialogManager = new DialogManager(mContext); + mDialogManager.setCanceledOnClickOutside(false); + mCertificateStatusListener = certificateStatusListener; + } + + public void certificate(boolean isForce) { + + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo != null) { + + if (!userInfo.isCertified()) { + if (isForce) { + mDialogManager.showTipsDialog(getCertificationTips(), + mContext.getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(mContext, + UriProvider.getTutuRealNamePage()); + } + }); + + } else { + + switch (CertificationModel.get().getCertificationType()) { + default: + case CER_TYPE_NONE: + if (mCertificateStatusListener != null) + mCertificateStatusListener.certificated(); + break; + + case CER_TYPE_GUIDE: + mDialogManager.showTipsDialog(getCertificationTips(), + mContext.getString(R.string.go_to_certification), + new DialogManager.OkCancelDialogListener() { + @Override + public void onCancel() { + if (mCertificateStatusListener != null) + mCertificateStatusListener.certificated(); + } + + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(mContext, + UriProvider.getTutuRealNamePage()); + } + }); + break; + + case CER_TYPE_FORCE: + mDialogManager.showTipsDialog(getCertificationTips(), + mContext.getString(R.string.go_to_certification), + new DialogManager.AbsOkDialogListener() { + @Override + public void onOk() { + // 跳去实名认证页面 + CommonWebViewActivity.start(mContext, + UriProvider.getTutuRealNamePage()); + } + }); + break; + } + + } + + } else if (mCertificateStatusListener != null) + mCertificateStatusListener.certificated(); + } + + } + + @NonNull + private SpannableStringBuilder getCertificationTips () { + String tips = mContext.getString(R.string.tips_need_to_certification); + SpannableStringBuilder builder = new SpannableStringBuilder(tips); + builder.setSpan(new ForegroundColorSpan(ContextCompat.getColor(mContext, R.color.appColor)), + tips.length() - 4, tips.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + return builder; + } + + public interface CertificateStatusListener { + void certificated(); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/CleanLeakUtils.java b/app/src/main/java/com/yizhuan/erban/utils/CleanLeakUtils.java new file mode 100644 index 000000000..6d0a84932 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/CleanLeakUtils.java @@ -0,0 +1,59 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.os.Build; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +import java.lang.reflect.Field; + +/** + * + * 参考 https://blog.csdn.net/qq402164452/article/details/54378688 + * InputMethodManager的mNextServedView引用了MainActivity从而导致了内存泄漏。 + * @author jack + * @Description + * @Date 2018/5/16 + */ + +public class CleanLeakUtils { + public static void fixInputMethodManagerLeak(Context destContext) { + //在15<=API<=23中都存在 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + return; + } + + if (destContext == null) { + return; + } + + InputMethodManager inputMethodManager = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager == null) { + return; + } + + String [] viewArray = new String[]{"mCurRootView", "mServedView", "mNextServedView"}; + Field filed; + Object filedObject; + + for (String view:viewArray) { + try{ + filed = inputMethodManager.getClass().getDeclaredField(view); + if (!filed.isAccessible()) { + filed.setAccessible(true); + } + filedObject = filed.get(inputMethodManager); + if (filedObject != null && filedObject instanceof View) { + View fileView = (View) filedObject; + if (fileView.getContext() == destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的 + filed.set(inputMethodManager, null); // 置空,破坏掉path to gc节点 + } else { + break;// 不是想要目标销毁的,即为又进了另一层界面了,不要处理,避免影响原逻辑,也就不用继续for循环了 + } + } + }catch(Throwable t){ + t.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/CommonJumpHelper.java b/app/src/main/java/com/yizhuan/erban/utils/CommonJumpHelper.java new file mode 100644 index 000000000..9fb26df3d --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/CommonJumpHelper.java @@ -0,0 +1,68 @@ +package com.yizhuan.erban.utils; + + +import android.content.Context; +import android.content.Intent; +import android.text.TextUtils; + +import com.yizhuan.erban.avroom.activity.AVRoomActivity; +import com.yizhuan.erban.ui.im.RouterHandler; +import com.yizhuan.erban.ui.webview.CommonWebViewActivity; +import com.yizhuan.xchat_android_core.home.bean.BannerInfo; +import com.yizhuan.xchat_android_library.utils.JavaUtil; + +import static com.yizhuan.xchat_android_core.home.bean.BannerInfo.*; + +/** + * 用于banner做通用跳转 + * + * @author xj + */ +public class CommonJumpHelper { + /** + * 通用跳转 + * + * @param context + */ + public static void bannerJump(Context context, BannerInfo bannerInfo) { + + + if (null == context || null == bannerInfo) { + return; + } + int skipType = bannerInfo.getSkipType(); + String url = bannerInfo.getSkipUri(); + switch (skipType) { + case SKIP_TYP_APP: + if (TextUtils.isEmpty(url)) { + return; + } + RouterHandler.handle(context, JavaUtil.str2int(url), null); + break; + case SKIP_TYP_CHAT_ROOM: + if (TextUtils.isEmpty(url)) { + return; + } + AVRoomActivity.start(context, JavaUtil.str2long(url)); + + break; + case SKIP_TYP_H5: + if (TextUtils.isEmpty(url)) { + return; + } + Intent intent = new Intent(context, CommonWebViewActivity.class); + intent.putExtra("url", url); + context.startActivity(intent); + break; + case SKIP_TYPE_ROUTER: + RouterHandler.handle(context, JavaUtil.str2int(bannerInfo.getRouterType()), bannerInfo.getRouterValue()); + break; + default: + break; + + } + + + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/FastBlur.java b/app/src/main/java/com/yizhuan/erban/utils/FastBlur.java new file mode 100644 index 000000000..9ffab878f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/FastBlur.java @@ -0,0 +1,257 @@ +package com.yizhuan.erban.utils; + +import android.graphics.Bitmap; + +/** + * Copyright (C) 2017 Wasabeef + * + * 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. + */ + +public class FastBlur { + + public static Bitmap blur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { + + // Stack Blur v1.0 from + // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html + // + // Java Author: Mario Klingemann + // http://incubator.quasimondo.com + // created Feburary 29, 2004 + // Android port : Yahel Bouaziz + // http://www.kayenko.com + // ported april 5th, 2012 + + // This is a compromise between Gaussian Blur and Box blur + // It creates much better looking blurs than Box Blur, but is + // 7x faster than my Gaussian Blur implementation. + // + // I called it Stack Blur because this describes best how this + // filter works internally: it creates a kind of moving stack + // of colors whilst scanning through the image. Thereby it + // just has to add one new block of color to the right side + // of the stack and remove the leftmost color. The remaining + // colors on the topmost layer of the stack are either added on + // or reduced by one, depending on if they are on the right or + // on the left side of the stack. + // + // If you are using this algorithm in your code please add + // the following line: + // + // Stack Blur Algorithm by Mario Klingemann + + Bitmap bitmap; + if (canReuseInBitmap) { + bitmap = sentBitmap; + } else { + bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); + } + + if (radius < 1) { + return (null); + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return (bitmap); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/utils/FloatManager.java b/app/src/main/java/com/yizhuan/erban/utils/FloatManager.java new file mode 100644 index 000000000..eb40146bd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/FloatManager.java @@ -0,0 +1,71 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.os.Build; +import android.view.Gravity; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.yizhuan.erban.application.XChatApplication; +import com.yizhuan.xchat_android_library.utils.SizeUtils; +import com.yizhuan.erban.ui.widget.MarqueeLayout; + +/** + *

悬浮窗管理

+ * + * @author jiahui + * @date 2018/1/10 + */ +public class FloatManager { + private WindowManager mWindowManager; + private MarqueeLayout marqueeLayout; + + + private static class FloatManagerHelper { + private static volatile FloatManager INSTANCE = new FloatManager(); + } + + public static FloatManager get() { + return FloatManagerHelper.INSTANCE; + } + + private FloatManager() { + mWindowManager = (WindowManager) XChatApplication.instance().getSystemService(Context.WINDOW_SERVICE); + } + + /** + * 显示全局通知 + * @param context + * @param marqueeLayout -- + */ + public void showGlobalNotice(Context context, MarqueeLayout marqueeLayout) { + if (this.marqueeLayout != null && mWindowManager != null && marqueeLayout.isAttachedToWindow()) + mWindowManager.removeView(marqueeLayout); + this.marqueeLayout = marqueeLayout; + WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.gravity = Gravity.TOP | Gravity.START; + params.height = SizeUtils.dp2px(context, 30); + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.y = SizeUtils.dp2px(context, 62); + params.setTitle("Toast"); + params.x = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } else { + params.type = WindowManager.LayoutParams.TYPE_TOAST; + } + + params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; + params.format = PixelFormat.TRANSLUCENT; + if (mWindowManager != null && !marqueeLayout.isAttachedToWindow()) + mWindowManager.addView(marqueeLayout, params); + marqueeLayout.startMarquee(); + marqueeLayout.setOnAnimatorListener( + animation -> { + if (mWindowManager != null) + mWindowManager.removeView(marqueeLayout); + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/FontTextView.java b/app/src/main/java/com/yizhuan/erban/utils/FontTextView.java new file mode 100644 index 000000000..99f331dd5 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/FontTextView.java @@ -0,0 +1,32 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.content.res.AssetManager; +import android.graphics.Typeface; +import android.support.v7.widget.AppCompatTextView; +import android.util.AttributeSet; + +public class FontTextView extends AppCompatTextView { + public FontTextView(Context context) { + super(context); + init(context); + } + + public FontTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public FontTextView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + AssetManager mgr = context.getAssets(); + //根据路径得到Typeface + Typeface tf = Typeface.createFromAsset(mgr, "fonts/NimbusSanConLOT-Bla.otf"); + //设置字体 + setTypeface(tf); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/KeyBoardUtils.java b/app/src/main/java/com/yizhuan/erban/utils/KeyBoardUtils.java new file mode 100644 index 000000000..f50441afc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/KeyBoardUtils.java @@ -0,0 +1,44 @@ +package com.yizhuan.erban.utils; + +import android.app.Activity; +import android.content.Context; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +/** + * Created by MadisonRong on 07/03/2018. + */ + +public class KeyBoardUtils { + + public static void showKeyBoard(Context context, EditText editText) { + if (context==null) return; + InputMethodManager imm = (InputMethodManager) + context.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) return; + imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED); + } + + public static void hideKeyBoard(Context context, EditText editText) { + if (context==null) return; + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) return; + imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); + } + + public static void showDialogSoftInput(Context activity) { + InputMethodManager inputMethodManager = + (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager == null) return; + inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); + } + + public static void hideDialogSoftInput(Context activity) { + InputMethodManager inputMethodManager = + (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager == null) return; + inputMethodManager.hideSoftInputFromWindow( + ((Activity)activity).getWindow().getDecorView().getWindowToken(), 0); + } +} + diff --git a/app/src/main/java/com/yizhuan/erban/utils/LimitInputFliter.java b/app/src/main/java/com/yizhuan/erban/utils/LimitInputFliter.java new file mode 100644 index 000000000..6a798acbd --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/LimitInputFliter.java @@ -0,0 +1,19 @@ +package com.yizhuan.erban.utils; + +import android.text.InputFilter; +import android.text.Spanned; + +/** + * Created by lvzebiao on 2019/1/24. + */ + +public class LimitInputFliter implements InputFilter { + + @Override + public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { + if (source.equals(" ") || source.toString().contentEquals("\n")) { + return ""; + } + return null; + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/NumberFormatUtil.java b/app/src/main/java/com/yizhuan/erban/utils/NumberFormatUtil.java new file mode 100644 index 000000000..2f73b983c --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/NumberFormatUtil.java @@ -0,0 +1,37 @@ +package com.yizhuan.erban.utils; + +import android.text.TextUtils; + +/** + * create by lvzebiao @2019/3/15 + */ +public class NumberFormatUtil { + + /** + * 数字格式转化 如 1000 → 1,000 + */ + public static String formatCommaInt(long value) { + String string = String.valueOf(value); + if (TextUtils.isEmpty(string)) { + return "0"; + } + try { + char [] chars = string.toCharArray(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < chars.length; i++) { + int low = chars.length - 1 - i; + String lowString = String.valueOf(chars[low]); + builder.insert(0, lowString); + if (i > 0 && (i + 1) % 3 == 0 && i < chars.length - 1) { + String comma = ","; + builder.insert(0, comma); + } + } + return builder.toString(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return String.valueOf(value); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/RSBlur.java b/app/src/main/java/com/yizhuan/erban/utils/RSBlur.java new file mode 100644 index 000000000..11f8598fc --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/RSBlur.java @@ -0,0 +1,66 @@ +package com.yizhuan.erban.utils; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Build; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RSRuntimeException; +import android.renderscript.RenderScript; +import android.renderscript.ScriptIntrinsicBlur; + +/** + * Copyright (C) 2017 Wasabeef + * + * 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. + */ + +public class RSBlur { + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) + public static Bitmap blur(Context context, Bitmap bitmap, int radius) throws RSRuntimeException { + RenderScript rs = null; + Allocation input = null; + Allocation output = null; + ScriptIntrinsicBlur blur = null; + try { + rs = RenderScript.create(context); + rs.setMessageHandler(new RenderScript.RSMessageHandler()); + input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + output = Allocation.createTyped(rs, input.getType()); + blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + + blur.setInput(input); + blur.setRadius(radius); + blur.forEach(output); + output.copyTo(bitmap); + } finally { + if (rs != null) { + rs.destroy(); + } + if (input != null) { + input.destroy(); + } + if (output != null) { + output.destroy(); + } + if (blur != null) { + blur.destroy(); + } + } + + return bitmap; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/utils/RegexUtil.java b/app/src/main/java/com/yizhuan/erban/utils/RegexUtil.java new file mode 100644 index 000000000..c148448a6 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/RegexUtil.java @@ -0,0 +1,69 @@ +package com.yizhuan.erban.utils; + +import android.text.TextUtils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 正则表达式工具类 + * Created by yudi + * on 2018/3/26. + */ + +public class RegexUtil { + /** + * 这个遇到了的特殊字符再加上去 + * 否则可能引入其他问题 + */ + private static String INVISIBLE_CHARS = +// "" /* dummy empty string for homogeneity */ +// "\\u0009" // CHARACTER TABULATION +// + "\\u000A" // LINE FEED (LF) +// + "\\u000B" // LINE TABULATION +// + "\\u000C" // FORM FEED (FF) +// + "\\u000D" // CARRIAGE RETURN (CR) +//// + "\\u0020" // SPACE +// + "\\u0085" // NEXT LINE (NEL) +// + "\\u00A0" // NO-BREAK SPACE +// + "\\u1680" // OGHAM SPACE MARK +// + "\\u180E" // MONGOLIAN VOWEL SEPARATOR +// + "\\u2000" // EN QUAD +// + "\\u2001" // EM QUAD +// + "\\u2002" // EN SPACE +// + "\\u2003" // EM SPACE +// + "\\u2004" // THREE-PER-EM SPACE +// + "\\u2005" // FOUR-PER-EM SPACE +// + "\\u2006" // SIX-PER-EM SPACE +// + "\\u2007" // FIGURE SPACE +// + "\\u2008" // PUNCTUATION SPACE +// + "\\u2009" // THIN SPACE +// + "\\u200A" // HAIR SPACE +// + "\\u2028" // LINE SEPARATOR +// + "\\u2029" // PARAGRAPH SEPARATOR +// + "\\u202F" // NARROW NO-BREAK SPACE +// + "\\u205F" // MEDIUM MATHEMATICAL SPACE +// + "\\u2060" +// + "\\u2062" + "\\u2063" // INVISIBLE SEPARATOR +// + "\\u3000" // IDEOGRAPHIC SPACE + ; + /* A \s that actually works for Java’s native character set: Unicode */ + private static String VISIBLE_CHARS = "^[" + INVISIBLE_CHARS + "]"; + /* A \S that actually works for Java’s native character set: Unicode */ + private static String NOT_VISIBLE_CHARS = "[" + INVISIBLE_CHARS + "]"; + + public static String getPrintableStringReg() { + return VISIBLE_CHARS; + } + + public static String getNotPrintableStringReg() { + // bug-fixed java.lang.RuntimeException:Unable to resume activity {com.yizhuan.erban/com.yizhuan.erban.MainActivity}: kotlin.KotlinNullPointerException + return TextUtils.isEmpty(NOT_VISIBLE_CHARS) ? "" : NOT_VISIBLE_CHARS; + } + + public static String getPrintableString(String text) { + if (TextUtils.isEmpty(text)) return ""; + return text.replaceAll(getNotPrintableStringReg(), "?"); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/SpannableBuilder.java b/app/src/main/java/com/yizhuan/erban/utils/SpannableBuilder.java new file mode 100644 index 000000000..2e7acf9aa --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/SpannableBuilder.java @@ -0,0 +1,53 @@ +package com.yizhuan.erban.utils; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.widget.TextView; + + +/** + * 这里独立写一个不再引用公屏那个,怕万一公屏改动,影响范围太大 + * Created by lvzebiao on 2019/2/27. + */ + +public class SpannableBuilder { + private SpannableStringBuilder builder; + + public SpannableBuilder() { + builder = new SpannableStringBuilder(); + } + + /** + * @param text 文字 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(CharSequence text) { + if (TextUtils.isEmpty(text)) return this; + builder.append(text); + return this; + } + + /** + * @param text -文字 + * @param what -span类型 + * @return -返回一个spannableStringBuilder + */ + public SpannableBuilder append(CharSequence text, Object what) { + if (TextUtils.isEmpty(text)) return this; + int start = builder.length(); + builder.append(text); + builder.setSpan(what, start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + return this; + } + + public SpannableStringBuilder build() { + return builder; + } + + public static ForegroundColorSpan createColor(Context context, int color) { + return new ForegroundColorSpan(context.getResources().getColor(color)); + } +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/ThreadUtil.java b/app/src/main/java/com/yizhuan/erban/utils/ThreadUtil.java new file mode 100644 index 000000000..a52310cbe --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/ThreadUtil.java @@ -0,0 +1,133 @@ +package com.yizhuan.erban.utils; + +import android.os.Handler; +import android.os.Looper; + +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Created by xiongxuesong-pc on 2016/6/1. + */ +public class ThreadUtil { + private static ThreadUtil.ThreadPool mThreadPool = getThreadPool(); + private static Handler mHandler; + + private ThreadUtil() { + } + + /** + * 在子线程执行任务 + * + * @param task + */ + public static void runInThread(Runnable task) { + mThreadPool.execute(task); + } + + /** + * 清理线程中的问题; + * + * @param task + */ + public static void cancelThread(Runnable task) { + mThreadPool.cancel(task); + } + + // ///////////////判断当前是否在主线程运行/////////////////// + public static boolean isRunOnUiThread() { + // 获取当前线程id, 如果当前线程id等于主线程id, 那就说明当前是在主线程 + return android.os.Process.myTid() == getMainThreadId(); + } + + private static int getMainThreadId() { + return android.os.Process.myTid(); + } + + /** + * 在UI线程执行任务 + * + * @param task + */ + public static void runOnUiThread(Runnable task) { + // 判断当时是否是主线程,如果是,就直接运行 + if (isRunOnUiThread()) { + // 当前就是主线程 + task.run(); + } else { + // 不是主线程, 需要运行在主线程 + // handler处理发送Message之外,也可以发送一个Runnable对象,也是运行在主线程的 + mHandler.post(task); + } + } + + + /** + * 在UI线程延时执行任务 + * + * @param task + * @param delayMillis 延时时间,单位毫秒 + */ + public static void runInUIThread(Runnable task, long delayMillis) { + mHandler.postDelayed(task, delayMillis); + } + + + /** + * 获取单例的线程池对象 + * + * @return + */ + public static ThreadUtil.ThreadPool getThreadPool() { + + if (mThreadPool == null) { + synchronized (ThreadUtil.class) { + if (mThreadPool == null) { + // cpu个数 + int cpuNum = Runtime.getRuntime().availableProcessors(); + int count = cpuNum * 2 + 1; + System.out.println("cpu个数:" + cpuNum); + mThreadPool = new ThreadPool(count, count, 0L); + mHandler = new Handler(Looper.getMainLooper()); + } + } + } + + return mThreadPool; + } + + + public static class ThreadPool { + + private int corePoolSize;// 核心线程数 + private int maximumPoolSize;// 最大线程数 + private long keepAliveTime;// 保持活跃时间(休息时间) + + private ThreadPoolExecutor executor; + + private ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime) { + this.corePoolSize = corePoolSize; + this.maximumPoolSize = maximumPoolSize; + this.keepAliveTime = keepAliveTime; + } + + public void execute(Runnable r) { + + if (executor == null) { + executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque(), + Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); + } + executor.execute(r);// 将当前Runnable对象放在线程池中 + } + + // 移除任务 + public void cancel(Runnable r) { + if (executor != null) { + executor.getQueue().remove(r);// 从下载队列中移除下载任务 + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/utils/TimeUiUtils.java b/app/src/main/java/com/yizhuan/erban/utils/TimeUiUtils.java new file mode 100644 index 000000000..b50c4d48a --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/TimeUiUtils.java @@ -0,0 +1,33 @@ +package com.yizhuan.erban.utils; + +import com.yizhuan.xchat_android_library.utils.TimeUtils; + +/** + * create by lvzebiao @2019/11/21 + */ +public class TimeUiUtils { + + public static String getDynamicUi(long ms) { + try { + long currMs = System.currentTimeMillis(); + long distanceMs = currMs - ms; + if (distanceMs < TimeUtils.MILLIS_OF_A_MINUTE) { + return "刚刚"; + } + if (distanceMs < TimeUtils.MILLIS_OF_A_HOUR) { + return (int)(distanceMs / TimeUtils.MILLIS_OF_A_MINUTE) + "分钟前"; + } + if (TimeUtils.isToday(ms)) { + return TimeUtils.getDateTimeString(ms, "HH:mm"); + } + if (TimeUtils.isSameYear(ms)) { + return TimeUtils.getDateTimeString(ms, "MM-dd"); + } + return TimeUtils.getDateTimeString(ms, "yyyy-MM-dd"); + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/UserUtils.java b/app/src/main/java/com/yizhuan/erban/utils/UserUtils.java new file mode 100644 index 000000000..94e965300 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/UserUtils.java @@ -0,0 +1,30 @@ +package com.yizhuan.erban.utils; + +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.user.IUserModel; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; + + +public class UserUtils { + + public static UserInfo getUserInfo() { + return UserModel.get().getCacheLoginUserInfo(); + } + + public static long getUserUid() { + return AuthModel.get().getCurrentUid(); + } + + public static long getCurrentRoomUid() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) return 0; + return AvRoomDataManager.get().mCurrentRoomInfo.getUid(); + } + + public static long getCurrentRoomId() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null) return 0; + return AvRoomDataManager.get().mCurrentRoomInfo.getRoomId(); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/utils/WebViewUtils.java b/app/src/main/java/com/yizhuan/erban/utils/WebViewUtils.java new file mode 100644 index 000000000..da9542896 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/utils/WebViewUtils.java @@ -0,0 +1,28 @@ +package com.yizhuan.erban.utils; + +import android.view.ViewGroup; +import android.webkit.WebView; + +/** + * + * Created by lvzebiao on 2020/2/26. + */ + +public class WebViewUtils { + + public static void releaseWeb(WebView webView) { + try { + if (webView == null) { + return; + } + if (webView.getParent() != null) { + ((ViewGroup)webView.getParent()).removeView(webView); + } + webView.destroy(); + webView = null; + } catch (Exception ex) { + ex.printStackTrace(); + } + } + +} diff --git a/app/src/main/res/anim/alpha_in.xml b/app/src/main/res/anim/alpha_in.xml new file mode 100644 index 000000000..c371c5fe8 --- /dev/null +++ b/app/src/main/res/anim/alpha_in.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/anim/alpha_out.xml b/app/src/main/res/anim/alpha_out.xml new file mode 100644 index 000000000..1b35740f9 --- /dev/null +++ b/app/src/main/res/anim/alpha_out.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/anim/anim_bottom_in.xml b/app/src/main/res/anim/anim_bottom_in.xml new file mode 100644 index 000000000..035305dca --- /dev/null +++ b/app/src/main/res/anim/anim_bottom_in.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_bottom_out.xml b/app/src/main/res/anim/anim_bottom_out.xml new file mode 100644 index 000000000..067cfc1ba --- /dev/null +++ b/app/src/main/res/anim/anim_bottom_out.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_box_notify.xml b/app/src/main/res/anim/anim_box_notify.xml new file mode 100644 index 000000000..d7d43191f --- /dev/null +++ b/app/src/main/res/anim/anim_box_notify.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_common_bottom_dialog_in.xml b/app/src/main/res/anim/anim_common_bottom_dialog_in.xml new file mode 100644 index 000000000..245f2f5bc --- /dev/null +++ b/app/src/main/res/anim/anim_common_bottom_dialog_in.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_common_bottom_dialog_out.xml b/app/src/main/res/anim/anim_common_bottom_dialog_out.xml new file mode 100644 index 000000000..364abb67f --- /dev/null +++ b/app/src/main/res/anim/anim_common_bottom_dialog_out.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_dialog_push_down.xml b/app/src/main/res/anim/anim_dialog_push_down.xml new file mode 100644 index 000000000..509d09d6b --- /dev/null +++ b/app/src/main/res/anim/anim_dialog_push_down.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_dialog_push_up.xml b/app/src/main/res/anim/anim_dialog_push_up.xml new file mode 100644 index 000000000..2960d3758 --- /dev/null +++ b/app/src/main/res/anim/anim_dialog_push_up.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_face_bottom_dialog_in.xml b/app/src/main/res/anim/anim_face_bottom_dialog_in.xml new file mode 100644 index 000000000..63e0c107a --- /dev/null +++ b/app/src/main/res/anim/anim_face_bottom_dialog_in.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_face_bottom_dialog_out.xml b/app/src/main/res/anim/anim_face_bottom_dialog_out.xml new file mode 100644 index 000000000..b2e65abd6 --- /dev/null +++ b/app/src/main/res/anim/anim_face_bottom_dialog_out.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_left_in.xml b/app/src/main/res/anim/anim_left_in.xml new file mode 100644 index 000000000..3a6ca6bf4 --- /dev/null +++ b/app/src/main/res/anim/anim_left_in.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_left_out.xml b/app/src/main/res/anim/anim_left_out.xml new file mode 100644 index 000000000..211608f6e --- /dev/null +++ b/app/src/main/res/anim/anim_left_out.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_right_in.xml b/app/src/main/res/anim/anim_right_in.xml new file mode 100644 index 000000000..c3aab643f --- /dev/null +++ b/app/src/main/res/anim/anim_right_in.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_right_out.xml b/app/src/main/res/anim/anim_right_out.xml new file mode 100644 index 000000000..119d76755 --- /dev/null +++ b/app/src/main/res/anim/anim_right_out.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_sign_in_out.xml b/app/src/main/res/anim/anim_sign_in_out.xml new file mode 100644 index 000000000..cc510a9b0 --- /dev/null +++ b/app/src/main/res/anim/anim_sign_in_out.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_top_in.xml b/app/src/main/res/anim/anim_top_in.xml new file mode 100644 index 000000000..c4af4c3ca --- /dev/null +++ b/app/src/main/res/anim/anim_top_in.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_top_out.xml b/app/src/main/res/anim/anim_top_out.xml new file mode 100644 index 000000000..9ad4e598e --- /dev/null +++ b/app/src/main/res/anim/anim_top_out.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_user_info_dialog_in.xml b/app/src/main/res/anim/anim_user_info_dialog_in.xml new file mode 100644 index 000000000..36ef1acc8 --- /dev/null +++ b/app/src/main/res/anim/anim_user_info_dialog_in.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_user_info_dialog_out.xml b/app/src/main/res/anim/anim_user_info_dialog_out.xml new file mode 100644 index 000000000..827b5c106 --- /dev/null +++ b/app/src/main/res/anim/anim_user_info_dialog_out.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/comm_loading.xml b/app/src/main/res/anim/comm_loading.xml new file mode 100644 index 000000000..5eb67ebb9 --- /dev/null +++ b/app/src/main/res/anim/comm_loading.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/common_widget_push_in_animation.xml b/app/src/main/res/anim/common_widget_push_in_animation.xml new file mode 100644 index 000000000..ae5c377f6 --- /dev/null +++ b/app/src/main/res/anim/common_widget_push_in_animation.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/common_widget_push_out_animation.xml b/app/src/main/res/anim/common_widget_push_out_animation.xml new file mode 100644 index 000000000..e2ca1cad2 --- /dev/null +++ b/app/src/main/res/anim/common_widget_push_out_animation.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/in_left.xml b/app/src/main/res/anim/in_left.xml new file mode 100644 index 000000000..fe5b67ee2 --- /dev/null +++ b/app/src/main/res/anim/in_left.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/in_right.xml b/app/src/main/res/anim/in_right.xml new file mode 100644 index 000000000..4d7888f32 --- /dev/null +++ b/app/src/main/res/anim/in_right.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/light_bg_rotate_anim.xml b/app/src/main/res/anim/light_bg_rotate_anim.xml new file mode 100644 index 000000000..47c117d18 --- /dev/null +++ b/app/src/main/res/anim/light_bg_rotate_anim.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/monster_hunting_impact.xml b/app/src/main/res/anim/monster_hunting_impact.xml new file mode 100644 index 000000000..6bb7041ca --- /dev/null +++ b/app/src/main/res/anim/monster_hunting_impact.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/out_left.xml b/app/src/main/res/anim/out_left.xml new file mode 100644 index 000000000..68a2475a5 --- /dev/null +++ b/app/src/main/res/anim/out_left.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/out_right.xml b/app/src/main/res/anim/out_right.xml new file mode 100644 index 000000000..c97474080 --- /dev/null +++ b/app/src/main/res/anim/out_right.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/rotate_fast_anim.xml b/app/src/main/res/anim/rotate_fast_anim.xml new file mode 100644 index 000000000..47c117d18 --- /dev/null +++ b/app/src/main/res/anim/rotate_fast_anim.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/rotate_quick_anim.xml b/app/src/main/res/anim/rotate_quick_anim.xml new file mode 100644 index 000000000..17a0f8e0d --- /dev/null +++ b/app/src/main/res/anim/rotate_quick_anim.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/update_app_window_in.xml b/app/src/main/res/anim/update_app_window_in.xml new file mode 100644 index 000000000..e5ba19445 --- /dev/null +++ b/app/src/main/res/anim/update_app_window_in.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/anim/update_app_window_out.xml b/app/src/main/res/anim/update_app_window_out.xml new file mode 100644 index 000000000..9d0ebcc71 --- /dev/null +++ b/app/src/main/res/anim/update_app_window_out.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/main/res/animator/anim_reward_display.xml b/app/src/main/res/animator/anim_reward_display.xml new file mode 100644 index 000000000..fe152ca95 --- /dev/null +++ b/app/src/main/res/animator/anim_reward_display.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/bg_gift_tab_color_selector.xml b/app/src/main/res/color/bg_gift_tab_color_selector.xml new file mode 100644 index 000000000..6a636f8b8 --- /dev/null +++ b/app/src/main/res/color/bg_gift_tab_color_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/bg_selector_filtrate.xml b/app/src/main/res/color/bg_selector_filtrate.xml new file mode 100644 index 000000000..f5e4c770d --- /dev/null +++ b/app/src/main/res/color/bg_selector_filtrate.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_magic_dialog_selector.xml b/app/src/main/res/color/color_magic_dialog_selector.xml new file mode 100644 index 000000000..755d2ce03 --- /dev/null +++ b/app/src/main/res/color/color_magic_dialog_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_magic_dialog_text_selector.xml b/app/src/main/res/color/color_magic_dialog_text_selector.xml new file mode 100644 index 000000000..6a636f8b8 --- /dev/null +++ b/app/src/main/res/color/color_magic_dialog_text_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_selector_app_color_false_999999.xml b/app/src/main/res/color/color_selector_app_color_false_999999.xml new file mode 100644 index 000000000..143b48968 --- /dev/null +++ b/app/src/main/res/color/color_selector_app_color_false_999999.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/color/color_slt_btn_give.xml b/app/src/main/res/color/color_slt_btn_give.xml new file mode 100644 index 000000000..a25bde339 --- /dev/null +++ b/app/src/main/res/color/color_slt_btn_give.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_slt_rank_btn.xml b/app/src/main/res/color/color_slt_rank_btn.xml new file mode 100644 index 000000000..3e4f088d1 --- /dev/null +++ b/app/src/main/res/color/color_slt_rank_btn.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_voice_filter_gender.xml b/app/src/main/res/color/color_voice_filter_gender.xml new file mode 100644 index 000000000..a05b76207 --- /dev/null +++ b/app/src/main/res/color/color_voice_filter_gender.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/color_voice_im_msg_say_hi.xml b/app/src/main/res/color/color_voice_im_msg_say_hi.xml new file mode 100644 index 000000000..c294816ad --- /dev/null +++ b/app/src/main/res/color/color_voice_im_msg_say_hi.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/gender_select_text_color.xml b/app/src/main/res/color/gender_select_text_color.xml new file mode 100644 index 000000000..739634e3d --- /dev/null +++ b/app/src/main/res/color/gender_select_text_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/press_text_color_black50.xml b/app/src/main/res/color/press_text_color_black50.xml new file mode 100644 index 000000000..a3c5d5466 --- /dev/null +++ b/app/src/main/res/color/press_text_color_black50.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/text_color_new_user_task_button.xml b/app/src/main/res/color/text_color_new_user_task_button.xml new file mode 100644 index 000000000..275ff13d7 --- /dev/null +++ b/app/src/main/res/color/text_color_new_user_task_button.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_car_price.webp b/app/src/main/res/drawable-hdpi/ic_car_price.webp new file mode 100644 index 000000000..0b1502b31 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_car_price.webp differ diff --git a/app/src/main/res/drawable-hdpi/ic_car_selected.webp b/app/src/main/res/drawable-hdpi/ic_car_selected.webp new file mode 100644 index 000000000..996e66d39 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_car_selected.webp differ diff --git a/app/src/main/res/drawable-hdpi/ic_car_unselected.webp b/app/src/main/res/drawable-hdpi/ic_car_unselected.webp new file mode 100644 index 000000000..f2b916bd3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_car_unselected.webp differ diff --git a/app/src/main/res/drawable-v23/anim_list_common_loading.xml b/app/src/main/res/drawable-v23/anim_list_common_loading.xml new file mode 100644 index 000000000..1c86494c3 --- /dev/null +++ b/app/src/main/res/drawable-v23/anim_list_common_loading.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/about_logo.webp b/app/src/main/res/drawable-xhdpi/about_logo.webp new file mode 100644 index 000000000..e2f6a7f24 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/about_logo.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_one_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_one_background.webp new file mode 100644 index 000000000..bbbc46c36 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_one_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_three_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_three_background.webp new file mode 100644 index 000000000..03351ad49 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_three_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_two_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_two_background.webp new file mode 100644 index 000000000..9fdc36b16 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_avatar_level_two_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_1.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_1.webp new file mode 100644 index 000000000..49437c159 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_2.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_2.webp new file mode 100644 index 000000000..7b4d2602a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_3.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_3.webp new file mode 100644 index 000000000..2b1d83664 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_give_level_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_one_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_level_one_background.webp new file mode 100644 index 000000000..7b3028ae9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_one_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_background.webp new file mode 100644 index 000000000..de9d6031f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_close.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_close.webp new file mode 100644 index 000000000..bc234f644 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_go_to.9.png b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_go_to.9.png new file mode 100644 index 000000000..b194e9b43 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_three_go_to.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_background.webp b/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_background.webp new file mode 100644 index 000000000..b6f86ca60 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_go_to.9.png b/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_go_to.9.png new file mode 100644 index 000000000..d0082f122 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_level_two_go_to.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_message_background.9.png b/app/src/main/res/drawable-xhdpi/all_service_gift_message_background.9.png new file mode 100644 index 000000000..9c8875276 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_message_background.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_message_level_three_background.9.png b/app/src/main/res/drawable-xhdpi/all_service_gift_message_level_three_background.9.png new file mode 100644 index 000000000..249e6f006 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_message_level_three_background.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/all_service_gift_user_nick_background.9.png b/app/src/main/res/drawable-xhdpi/all_service_gift_user_nick_background.9.png new file mode 100644 index 000000000..40c508528 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/all_service_gift_user_nick_background.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/arrow_left.webp b/app/src/main/res/drawable-xhdpi/arrow_left.webp new file mode 100644 index 000000000..24514f1e3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/arrow_left.webp differ diff --git a/app/src/main/res/drawable-xhdpi/arrow_left_white.png b/app/src/main/res/drawable-xhdpi/arrow_left_white.png new file mode 100644 index 000000000..7297e478d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/arrow_left_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/arrow_right.webp b/app/src/main/res/drawable-xhdpi/arrow_right.webp new file mode 100644 index 000000000..e1e9e6d6d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/arrow_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/arrow_right_2.png b/app/src/main/res/drawable-xhdpi/arrow_right_2.png new file mode 100644 index 000000000..14193cae7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/arrow_right_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/banner_family_plaza.webp b/app/src/main/res/drawable-xhdpi/banner_family_plaza.webp new file mode 100644 index 000000000..575538f7d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/banner_family_plaza.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_btn_share_sign_prize.webp b/app/src/main/res/drawable-xhdpi/bg_btn_share_sign_prize.webp new file mode 100644 index 000000000..7ab3e0314 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_btn_share_sign_prize.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_button_buy.webp b/app/src/main/res/drawable-xhdpi/bg_button_buy.webp new file mode 100644 index 000000000..0124fc884 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_button_buy.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_button_remain.png b/app/src/main/res/drawable-xhdpi/bg_button_remain.png new file mode 100644 index 000000000..98a95eb33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_button_remain.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_common_loading_dialog.webp b/app/src/main/res/drawable-xhdpi/bg_common_loading_dialog.webp new file mode 100644 index 000000000..5b149f9d5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_common_loading_dialog.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_confirm_payment_select_way.webp b/app/src/main/res/drawable-xhdpi/bg_confirm_payment_select_way.webp new file mode 100644 index 000000000..538de373c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_confirm_payment_select_way.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_decoration_store.webp b/app/src/main/res/drawable-xhdpi/bg_decoration_store.webp new file mode 100644 index 000000000..6997664cc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_decoration_store.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_dialog_room_title.webp b/app/src/main/res/drawable-xhdpi/bg_dialog_room_title.webp new file mode 100644 index 000000000..1807fc6bf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_dialog_room_title.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_draw_gold.webp b/app/src/main/res/drawable-xhdpi/bg_draw_gold.webp new file mode 100644 index 000000000..c38c9c41d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_draw_gold.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_home_top_big_tab.png b/app/src/main/res/drawable-xhdpi/bg_home_top_big_tab.png new file mode 100644 index 000000000..5eef9ca10 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_home_top_big_tab.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_home_top_small_wave.png b/app/src/main/res/drawable-xhdpi/bg_home_top_small_wave.png new file mode 100644 index 000000000..ca2a4f34a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_home_top_small_wave.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_home_top_tab.webp b/app/src/main/res/drawable-xhdpi/bg_home_top_tab.webp new file mode 100644 index 000000000..8748200cd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_home_top_tab.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_king_micro.webp b/app/src/main/res/drawable-xhdpi/bg_king_micro.webp new file mode 100644 index 000000000..682a4d1df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_king_micro.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_left_button_buy.webp b/app/src/main/res/drawable-xhdpi/bg_left_button_buy.webp new file mode 100644 index 000000000..c1b12d010 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_left_button_buy.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_left_button_remain.webp b/app/src/main/res/drawable-xhdpi/bg_left_button_remain.webp new file mode 100644 index 000000000..fadd44edd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_left_button_remain.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_micro_8.webp b/app/src/main/res/drawable-xhdpi/bg_micro_8.webp new file mode 100644 index 000000000..1e21304c9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_micro_8.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_pk_record_blue_team.webp b/app/src/main/res/drawable-xhdpi/bg_pk_record_blue_team.webp new file mode 100644 index 000000000..31ecf2e7f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_pk_record_blue_team.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_pk_record_loser.webp b/app/src/main/res/drawable-xhdpi/bg_pk_record_loser.webp new file mode 100644 index 000000000..b58f97ecc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_pk_record_loser.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_pk_record_red_team.webp b/app/src/main/res/drawable-xhdpi/bg_pk_record_red_team.webp new file mode 100644 index 000000000..b59bc5950 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_pk_record_red_team.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_radish_record.webp b/app/src/main/res/drawable-xhdpi/bg_radish_record.webp new file mode 100644 index 000000000..46772048e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_radish_record.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_recommend_card_invaild.9.png b/app/src/main/res/drawable-xhdpi/bg_recommend_card_invaild.9.png new file mode 100644 index 000000000..a6e96ee4f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_recommend_card_invaild.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_recommend_card_vaild.9.png b/app/src/main/res/drawable-xhdpi/bg_recommend_card_vaild.9.png new file mode 100644 index 000000000..c915adddc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_recommend_card_vaild.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_recording_voice_card.9.png b/app/src/main/res/drawable-xhdpi/bg_recording_voice_card.9.png new file mode 100644 index 000000000..440a2c1e2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_recording_voice_card.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_cp.webp b/app/src/main/res/drawable-xhdpi/bg_room_cp.webp new file mode 100644 index 000000000..628c1f181 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_cp.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_main_entrance.webp b/app/src/main/res/drawable-xhdpi/bg_room_main_entrance.webp new file mode 100644 index 000000000..72a136314 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_main_entrance.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_msg_input.webp b/app/src/main/res/drawable-xhdpi/bg_room_msg_input.webp new file mode 100644 index 000000000..8c6823375 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_msg_input.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_normal_default_pic.webp b/app/src/main/res/drawable-xhdpi/bg_room_normal_default_pic.webp new file mode 100644 index 000000000..624a4bf7d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_normal_default_pic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_pk.webp b/app/src/main/res/drawable-xhdpi/bg_room_pk.webp new file mode 100644 index 000000000..7f0e7837e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_pk.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room.webp new file mode 100644 index 000000000..6b8079549 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_bottom.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_bottom.webp new file mode 100644 index 000000000..3fa9b673b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_bottom.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_middle.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_middle.webp new file mode 100644 index 000000000..6ddd2d1d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_in_room_middle.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_top_default_big_pink.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_default_big_pink.webp new file mode 100644 index 000000000..b8affb9fd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_default_big_pink.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple.webp new file mode 100644 index 000000000..e06f29813 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_1.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_1.webp new file mode 100644 index 000000000..ee06ba3b9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_2.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_2.webp new file mode 100644 index 000000000..f20c406a9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_3.webp b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_3.webp new file mode 100644 index 000000000..0aca7c464 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_room_rank_top_purple_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_sign_in_content.webp b/app/src/main/res/drawable-xhdpi/bg_sign_in_content.webp new file mode 100644 index 000000000..9f3b8911a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_sign_in_content.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_sign_in_dialog.webp b/app/src/main/res/drawable-xhdpi/bg_sign_in_dialog.webp new file mode 100644 index 000000000..a88f6a1d6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_sign_in_dialog.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_sign_in_reward_list.9.png b/app/src/main/res/drawable-xhdpi/bg_sign_in_reward_list.9.png new file mode 100644 index 000000000..f7ba1ddc3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_sign_in_reward_list.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_sign_in_top.png b/app/src/main/res/drawable-xhdpi/bg_sign_in_top.png new file mode 100644 index 000000000..6c6d6c7bd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_sign_in_top.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_start_live.webp b/app/src/main/res/drawable-xhdpi/bg_start_live.webp new file mode 100644 index 000000000..c3b59db3d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_start_live.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_task_top.webp b/app/src/main/res/drawable-xhdpi/bg_task_top.webp new file mode 100644 index 000000000..0f810bfda Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_task_top.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_try_car.webp b/app/src/main/res/drawable-xhdpi/bg_try_car.webp new file mode 100644 index 000000000..581a4a43f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_try_car.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_user_match.webp b/app/src/main/res/drawable-xhdpi/bg_user_match.webp new file mode 100644 index 000000000..513f7ff5f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_user_match.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bg_voice_match_android_6.png b/app/src/main/res/drawable-xhdpi/bg_voice_match_android_6.png new file mode 100644 index 000000000..83c45954e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_voice_match_android_6.png differ diff --git a/app/src/main/res/drawable-xhdpi/boss_chair.webp b/app/src/main/res/drawable-xhdpi/boss_chair.webp new file mode 100644 index 000000000..ca222d008 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/boss_chair.webp differ diff --git a/app/src/main/res/drawable-xhdpi/bq_bg.png b/app/src/main/res/drawable-xhdpi/bq_bg.png new file mode 100644 index 000000000..e2557b727 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bq_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/btn_close.webp b/app/src/main/res/drawable-xhdpi/btn_close.webp new file mode 100644 index 000000000..df00d33ab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/btn_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/btn_pause.webp b/app/src/main/res/drawable-xhdpi/btn_pause.webp new file mode 100644 index 000000000..93386ec18 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/btn_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/btn_play.webp b/app/src/main/res/drawable-xhdpi/btn_play.webp new file mode 100644 index 000000000..8216cb8f3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/btn_play.webp differ diff --git a/app/src/main/res/drawable-xhdpi/chat_button_say.png b/app/src/main/res/drawable-xhdpi/chat_button_say.png new file mode 100644 index 000000000..e8230d7fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_button_say.png differ diff --git a/app/src/main/res/drawable-xhdpi/chat_button_say_unenable.webp b/app/src/main/res/drawable-xhdpi/chat_button_say_unenable.webp new file mode 100644 index 000000000..adf4a7ea7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_button_say_unenable.webp differ diff --git a/app/src/main/res/drawable-xhdpi/chat_game_overlays.png b/app/src/main/res/drawable-xhdpi/chat_game_overlays.png new file mode 100644 index 000000000..31154d07b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_game_overlays.png differ diff --git a/app/src/main/res/drawable-xhdpi/chat_icon_say.webp b/app/src/main/res/drawable-xhdpi/chat_icon_say.webp new file mode 100644 index 000000000..5703c4994 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_icon_say.webp differ diff --git a/app/src/main/res/drawable-xhdpi/chat_popup_game_bg.png b/app/src/main/res/drawable-xhdpi/chat_popup_game_bg.png new file mode 100644 index 000000000..97f19b37d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_popup_game_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/chat_popup_game_close.png b/app/src/main/res/drawable-xhdpi/chat_popup_game_close.png new file mode 100644 index 000000000..73dbd11a0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_popup_game_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/chat_say_game.png b/app/src/main/res/drawable-xhdpi/chat_say_game.png new file mode 100644 index 000000000..a4ec02a75 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chat_say_game.png differ diff --git a/app/src/main/res/drawable-xhdpi/close.webp b/app/src/main/res/drawable-xhdpi/close.webp new file mode 100644 index 000000000..7a3db23e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/confirm_dialog_button_background.webp b/app/src/main/res/drawable-xhdpi/confirm_dialog_button_background.webp new file mode 100644 index 000000000..c35ebf69e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/confirm_dialog_button_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/default_auction_header.webp b/app/src/main/res/drawable-xhdpi/default_auction_header.webp new file mode 100644 index 000000000..ff631ab17 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/default_auction_header.webp differ diff --git a/app/src/main/res/drawable-xhdpi/default_avatar.webp b/app/src/main/res/drawable-xhdpi/default_avatar.webp new file mode 100644 index 000000000..c79660933 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/default_avatar.webp differ diff --git a/app/src/main/res/drawable-xhdpi/default_cover.webp b/app/src/main/res/drawable-xhdpi/default_cover.webp new file mode 100644 index 000000000..c79660933 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/default_cover.webp differ diff --git a/app/src/main/res/drawable-xhdpi/default_user_head.webp b/app/src/main/res/drawable-xhdpi/default_user_head.webp new file mode 100644 index 000000000..fbd719d4f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/default_user_head.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_1.webp b/app/src/main/res/drawable-xhdpi/dice_1.webp new file mode 100644 index 000000000..c487d2cae Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_2.webp b/app/src/main/res/drawable-xhdpi/dice_2.webp new file mode 100644 index 000000000..8304d0000 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_3.webp b/app/src/main/res/drawable-xhdpi/dice_3.webp new file mode 100644 index 000000000..aef22e3ea Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_4.webp b/app/src/main/res/drawable-xhdpi/dice_4.webp new file mode 100644 index 000000000..d4d1c70e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_4.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_5.webp b/app/src/main/res/drawable-xhdpi/dice_5.webp new file mode 100644 index 000000000..a96d0117b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_5.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_6.webp b/app/src/main/res/drawable-xhdpi/dice_6.webp new file mode 100644 index 000000000..36ebcccab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_6.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_guide.webp b/app/src/main/res/drawable-xhdpi/dice_guide.webp new file mode 100644 index 000000000..18a208d3f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_guide.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dice_guide_bottom.webp b/app/src/main/res/drawable-xhdpi/dice_guide_bottom.webp new file mode 100644 index 000000000..897185ffd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dice_guide_bottom.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dot_normal.webp b/app/src/main/res/drawable-xhdpi/dot_normal.webp new file mode 100644 index 000000000..c6f29a628 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dot_normal.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dot_selected.webp b/app/src/main/res/drawable-xhdpi/dot_selected.webp new file mode 100644 index 000000000..a42b4f211 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dot_selected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/double_arrow_right.webp b/app/src/main/res/drawable-xhdpi/double_arrow_right.webp new file mode 100644 index 000000000..1eda68915 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/double_arrow_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dragon_cancel.webp b/app/src/main/res/drawable-xhdpi/dragon_cancel.webp new file mode 100644 index 000000000..6612da2f7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dragon_cancel.webp differ diff --git a/app/src/main/res/drawable-xhdpi/dragon_three.webp b/app/src/main/res/drawable-xhdpi/dragon_three.webp new file mode 100644 index 000000000..cf3d18d94 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dragon_three.webp differ diff --git a/app/src/main/res/drawable-xhdpi/empty_ktv_no_room.webp b/app/src/main/res/drawable-xhdpi/empty_ktv_no_room.webp new file mode 100644 index 000000000..7fa9db1cf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/empty_ktv_no_room.webp differ diff --git a/app/src/main/res/drawable-xhdpi/enterhome.webp b/app/src/main/res/drawable-xhdpi/enterhome.webp new file mode 100644 index 000000000..c6e77ac11 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/enterhome.webp differ diff --git a/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_about_me.webp b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_about_me.webp new file mode 100644 index 000000000..ef10cdef6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_about_me.webp differ diff --git a/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_monster.webp b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_monster.webp new file mode 100644 index 000000000..022be6979 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_monster.webp differ diff --git a/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_new.webp b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_new.webp new file mode 100644 index 000000000..ae9511102 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/erban_toutiao_tag_new.webp differ diff --git a/app/src/main/res/drawable-xhdpi/explosion_five.png b/app/src/main/res/drawable-xhdpi/explosion_five.png new file mode 100644 index 000000000..ddc600151 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/explosion_five.png differ diff --git a/app/src/main/res/drawable-xhdpi/explosion_four.png b/app/src/main/res/drawable-xhdpi/explosion_four.png new file mode 100644 index 000000000..dff158bfa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/explosion_four.png differ diff --git a/app/src/main/res/drawable-xhdpi/explosion_one.png b/app/src/main/res/drawable-xhdpi/explosion_one.png new file mode 100644 index 000000000..2d5f34b54 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/explosion_one.png differ diff --git a/app/src/main/res/drawable-xhdpi/explosion_three.png b/app/src/main/res/drawable-xhdpi/explosion_three.png new file mode 100644 index 000000000..987cc43ce Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/explosion_three.png differ diff --git a/app/src/main/res/drawable-xhdpi/explosion_two.png b/app/src/main/res/drawable-xhdpi/explosion_two.png new file mode 100644 index 000000000..a59f6ed52 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/explosion_two.png differ diff --git a/app/src/main/res/drawable-xhdpi/find_00000.webp b/app/src/main/res/drawable-xhdpi/find_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00001.webp b/app/src/main/res/drawable-xhdpi/find_00001.webp new file mode 100644 index 000000000..a13d7525f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00002.webp b/app/src/main/res/drawable-xhdpi/find_00002.webp new file mode 100644 index 000000000..c72c88e10 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00003.webp b/app/src/main/res/drawable-xhdpi/find_00003.webp new file mode 100644 index 000000000..9a10b4f66 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00004.webp b/app/src/main/res/drawable-xhdpi/find_00004.webp new file mode 100644 index 000000000..bf00ce49f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00005.webp b/app/src/main/res/drawable-xhdpi/find_00005.webp new file mode 100644 index 000000000..6a5f20d82 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00006.webp b/app/src/main/res/drawable-xhdpi/find_00006.webp new file mode 100644 index 000000000..1e88eda6d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00007.webp b/app/src/main/res/drawable-xhdpi/find_00007.webp new file mode 100644 index 000000000..22c9565db Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00008.webp b/app/src/main/res/drawable-xhdpi/find_00008.webp new file mode 100644 index 000000000..e477fe26d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00009.webp b/app/src/main/res/drawable-xhdpi/find_00009.webp new file mode 100644 index 000000000..8b3f72c25 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00010.webp b/app/src/main/res/drawable-xhdpi/find_00010.webp new file mode 100644 index 000000000..8928d4946 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00011.webp b/app/src/main/res/drawable-xhdpi/find_00011.webp new file mode 100644 index 000000000..36c9b0d90 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00012.webp b/app/src/main/res/drawable-xhdpi/find_00012.webp new file mode 100644 index 000000000..03b7dd4e4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00013.webp b/app/src/main/res/drawable-xhdpi/find_00013.webp new file mode 100644 index 000000000..80c7cc14a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00014.webp b/app/src/main/res/drawable-xhdpi/find_00014.webp new file mode 100644 index 000000000..80bc93e2d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00015.webp b/app/src/main/res/drawable-xhdpi/find_00015.webp new file mode 100644 index 000000000..a16a9c1f9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00016.webp b/app/src/main/res/drawable-xhdpi/find_00016.webp new file mode 100644 index 000000000..699b13a3b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00017.webp b/app/src/main/res/drawable-xhdpi/find_00017.webp new file mode 100644 index 000000000..948de5596 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00018.webp b/app/src/main/res/drawable-xhdpi/find_00018.webp new file mode 100644 index 000000000..34b380f21 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00019.webp b/app/src/main/res/drawable-xhdpi/find_00019.webp new file mode 100644 index 000000000..652837965 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00020.webp b/app/src/main/res/drawable-xhdpi/find_00020.webp new file mode 100644 index 000000000..29230819f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00021.webp b/app/src/main/res/drawable-xhdpi/find_00021.webp new file mode 100644 index 000000000..7771c0b14 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00022.webp b/app/src/main/res/drawable-xhdpi/find_00022.webp new file mode 100644 index 000000000..aac995156 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00023.webp b/app/src/main/res/drawable-xhdpi/find_00023.webp new file mode 100644 index 000000000..45d677d5b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00024.webp b/app/src/main/res/drawable-xhdpi/find_00024.webp new file mode 100644 index 000000000..fabd4440e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00025.webp b/app/src/main/res/drawable-xhdpi/find_00025.webp new file mode 100644 index 000000000..dc3f433b4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00026.webp b/app/src/main/res/drawable-xhdpi/find_00026.webp new file mode 100644 index 000000000..762bbaa1b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00027.webp b/app/src/main/res/drawable-xhdpi/find_00027.webp new file mode 100644 index 000000000..6a916edf2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00028.webp b/app/src/main/res/drawable-xhdpi/find_00028.webp new file mode 100644 index 000000000..79d29e8d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00029.webp b/app/src/main/res/drawable-xhdpi/find_00029.webp new file mode 100644 index 000000000..b9a0a1125 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00030.webp b/app/src/main/res/drawable-xhdpi/find_00030.webp new file mode 100644 index 000000000..d94d1a130 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00031.webp b/app/src/main/res/drawable-xhdpi/find_00031.webp new file mode 100644 index 000000000..d155c0e94 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00032.webp b/app/src/main/res/drawable-xhdpi/find_00032.webp new file mode 100644 index 000000000..f25b794a9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00033.webp b/app/src/main/res/drawable-xhdpi/find_00033.webp new file mode 100644 index 000000000..4b73942c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00034.webp b/app/src/main/res/drawable-xhdpi/find_00034.webp new file mode 100644 index 000000000..ffd63892e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00035.webp b/app/src/main/res/drawable-xhdpi/find_00035.webp new file mode 100644 index 000000000..559269f41 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00036.webp b/app/src/main/res/drawable-xhdpi/find_00036.webp new file mode 100644 index 000000000..384b48e64 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/find_00037.webp b/app/src/main/res/drawable-xhdpi/find_00037.webp new file mode 100644 index 000000000..1d5532843 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00000.webp b/app/src/main/res/drawable-xhdpi/game_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00001.webp b/app/src/main/res/drawable-xhdpi/game_00001.webp new file mode 100644 index 000000000..599b62e70 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00002.webp b/app/src/main/res/drawable-xhdpi/game_00002.webp new file mode 100644 index 000000000..a9268883e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00003.webp b/app/src/main/res/drawable-xhdpi/game_00003.webp new file mode 100644 index 000000000..9c995230e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00004.webp b/app/src/main/res/drawable-xhdpi/game_00004.webp new file mode 100644 index 000000000..5ce2775e9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00005.webp b/app/src/main/res/drawable-xhdpi/game_00005.webp new file mode 100644 index 000000000..8bc6a6e6e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00006.webp b/app/src/main/res/drawable-xhdpi/game_00006.webp new file mode 100644 index 000000000..8a1fc7e87 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00007.webp b/app/src/main/res/drawable-xhdpi/game_00007.webp new file mode 100644 index 000000000..a454f4038 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00008.webp b/app/src/main/res/drawable-xhdpi/game_00008.webp new file mode 100644 index 000000000..018b9fc4b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00009.webp b/app/src/main/res/drawable-xhdpi/game_00009.webp new file mode 100644 index 000000000..8445b9caa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00010.webp b/app/src/main/res/drawable-xhdpi/game_00010.webp new file mode 100644 index 000000000..65f549434 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00011.webp b/app/src/main/res/drawable-xhdpi/game_00011.webp new file mode 100644 index 000000000..aa00b5fd7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00012.webp b/app/src/main/res/drawable-xhdpi/game_00012.webp new file mode 100644 index 000000000..0cbf5aeff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00013.webp b/app/src/main/res/drawable-xhdpi/game_00013.webp new file mode 100644 index 000000000..de6b7777b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00014.webp b/app/src/main/res/drawable-xhdpi/game_00014.webp new file mode 100644 index 000000000..fafa71f4a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00015.webp b/app/src/main/res/drawable-xhdpi/game_00015.webp new file mode 100644 index 000000000..28a873601 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00016.webp b/app/src/main/res/drawable-xhdpi/game_00016.webp new file mode 100644 index 000000000..b5767e1a5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00017.webp b/app/src/main/res/drawable-xhdpi/game_00017.webp new file mode 100644 index 000000000..1174c997e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00018.webp b/app/src/main/res/drawable-xhdpi/game_00018.webp new file mode 100644 index 000000000..9aa8e6451 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00019.webp b/app/src/main/res/drawable-xhdpi/game_00019.webp new file mode 100644 index 000000000..d06ac6317 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00020.webp b/app/src/main/res/drawable-xhdpi/game_00020.webp new file mode 100644 index 000000000..8b4ffc8e4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00021.webp b/app/src/main/res/drawable-xhdpi/game_00021.webp new file mode 100644 index 000000000..15caea29a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00022.webp b/app/src/main/res/drawable-xhdpi/game_00022.webp new file mode 100644 index 000000000..e80e4ffb3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00023.webp b/app/src/main/res/drawable-xhdpi/game_00023.webp new file mode 100644 index 000000000..b365321d4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00024.webp b/app/src/main/res/drawable-xhdpi/game_00024.webp new file mode 100644 index 000000000..5eeb68079 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00025.webp b/app/src/main/res/drawable-xhdpi/game_00025.webp new file mode 100644 index 000000000..9f4c77853 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00026.webp b/app/src/main/res/drawable-xhdpi/game_00026.webp new file mode 100644 index 000000000..572215e53 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00027.webp b/app/src/main/res/drawable-xhdpi/game_00027.webp new file mode 100644 index 000000000..a3e19e18d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00028.webp b/app/src/main/res/drawable-xhdpi/game_00028.webp new file mode 100644 index 000000000..093ba464b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00029.webp b/app/src/main/res/drawable-xhdpi/game_00029.webp new file mode 100644 index 000000000..5a16963ea Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00030.webp b/app/src/main/res/drawable-xhdpi/game_00030.webp new file mode 100644 index 000000000..6bba9cd70 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00031.webp b/app/src/main/res/drawable-xhdpi/game_00031.webp new file mode 100644 index 000000000..2d76e57a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00032.webp b/app/src/main/res/drawable-xhdpi/game_00032.webp new file mode 100644 index 000000000..99982b04b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00033.webp b/app/src/main/res/drawable-xhdpi/game_00033.webp new file mode 100644 index 000000000..3db7b0082 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00034.webp b/app/src/main/res/drawable-xhdpi/game_00034.webp new file mode 100644 index 000000000..013778615 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00035.webp b/app/src/main/res/drawable-xhdpi/game_00035.webp new file mode 100644 index 000000000..bf927a920 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00036.webp b/app/src/main/res/drawable-xhdpi/game_00036.webp new file mode 100644 index 000000000..b19f20086 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_00037.webp b/app/src/main/res/drawable-xhdpi/game_00037.webp new file mode 100644 index 000000000..06943a4bd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_all_find_player.png b/app/src/main/res/drawable-xhdpi/game_all_find_player.png new file mode 100644 index 000000000..8bdc749f8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_all_find_player.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_avatar_shade.png b/app/src/main/res/drawable-xhdpi/game_avatar_shade.png new file mode 100644 index 000000000..ee416a7d1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_avatar_shade.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_bg.png b/app/src/main/res/drawable-xhdpi/game_button_bg.png new file mode 100644 index 000000000..9f740d1be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_bg2.png b/app/src/main/res/drawable-xhdpi/game_button_bg2.png new file mode 100644 index 000000000..7ae50cfc9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_bg2.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_volume_off.png b/app/src/main/res/drawable-xhdpi/game_button_volume_off.png new file mode 100644 index 000000000..da392f274 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_volume_off.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_volume_on.png b/app/src/main/res/drawable-xhdpi/game_button_volume_on.png new file mode 100644 index 000000000..70cccbe27 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_volume_on.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_wheat_off.png b/app/src/main/res/drawable-xhdpi/game_button_wheat_off.png new file mode 100644 index 000000000..0597a51df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_wheat_off.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_button_wheat_on.png b/app/src/main/res/drawable-xhdpi/game_button_wheat_on.png new file mode 100644 index 000000000..b96c3a84b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_button_wheat_on.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_change_watch_left.png b/app/src/main/res/drawable-xhdpi/game_change_watch_left.png new file mode 100644 index 000000000..bc43e6b15 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_change_watch_left.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_change_watch_right.png b/app/src/main/res/drawable-xhdpi/game_change_watch_right.png new file mode 100644 index 000000000..194967cc2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_change_watch_right.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_gender_boy.png b/app/src/main/res/drawable-xhdpi/game_gender_boy.png new file mode 100644 index 000000000..b6ab41c94 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_gender_boy.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_gender_girl.png b/app/src/main/res/drawable-xhdpi/game_gender_girl.png new file mode 100644 index 000000000..326a3a12f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_gender_girl.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_h5_close.png b/app/src/main/res/drawable-xhdpi/game_h5_close.png new file mode 100644 index 000000000..1d72e6507 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_h5_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_h5_explain.png b/app/src/main/res/drawable-xhdpi/game_h5_explain.png new file mode 100644 index 000000000..9c551d2ce Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_h5_explain.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_h5_voice_off.png b/app/src/main/res/drawable-xhdpi/game_h5_voice_off.png new file mode 100644 index 000000000..df0f3dd38 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_h5_voice_off.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_h5_voice_on.png b/app/src/main/res/drawable-xhdpi/game_h5_voice_on.png new file mode 100644 index 000000000..9f5d4c34c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_h5_voice_on.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00000.webp b/app/src/main/res/drawable-xhdpi/game_home_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00001.webp b/app/src/main/res/drawable-xhdpi/game_home_00001.webp new file mode 100644 index 000000000..599b62e70 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00002.webp b/app/src/main/res/drawable-xhdpi/game_home_00002.webp new file mode 100644 index 000000000..a9268883e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00003.webp b/app/src/main/res/drawable-xhdpi/game_home_00003.webp new file mode 100644 index 000000000..9c995230e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00004.webp b/app/src/main/res/drawable-xhdpi/game_home_00004.webp new file mode 100644 index 000000000..5ce2775e9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00005.webp b/app/src/main/res/drawable-xhdpi/game_home_00005.webp new file mode 100644 index 000000000..8bc6a6e6e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00006.webp b/app/src/main/res/drawable-xhdpi/game_home_00006.webp new file mode 100644 index 000000000..8a1fc7e87 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00007.webp b/app/src/main/res/drawable-xhdpi/game_home_00007.webp new file mode 100644 index 000000000..a454f4038 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00008.webp b/app/src/main/res/drawable-xhdpi/game_home_00008.webp new file mode 100644 index 000000000..018b9fc4b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00009.webp b/app/src/main/res/drawable-xhdpi/game_home_00009.webp new file mode 100644 index 000000000..8445b9caa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00010.webp b/app/src/main/res/drawable-xhdpi/game_home_00010.webp new file mode 100644 index 000000000..65f549434 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00011.webp b/app/src/main/res/drawable-xhdpi/game_home_00011.webp new file mode 100644 index 000000000..aa00b5fd7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00012.webp b/app/src/main/res/drawable-xhdpi/game_home_00012.webp new file mode 100644 index 000000000..0cbf5aeff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00013.webp b/app/src/main/res/drawable-xhdpi/game_home_00013.webp new file mode 100644 index 000000000..de6b7777b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00014.webp b/app/src/main/res/drawable-xhdpi/game_home_00014.webp new file mode 100644 index 000000000..fafa71f4a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00015.webp b/app/src/main/res/drawable-xhdpi/game_home_00015.webp new file mode 100644 index 000000000..28a873601 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00016.webp b/app/src/main/res/drawable-xhdpi/game_home_00016.webp new file mode 100644 index 000000000..b5767e1a5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00017.webp b/app/src/main/res/drawable-xhdpi/game_home_00017.webp new file mode 100644 index 000000000..1174c997e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00018.webp b/app/src/main/res/drawable-xhdpi/game_home_00018.webp new file mode 100644 index 000000000..9aa8e6451 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00019.webp b/app/src/main/res/drawable-xhdpi/game_home_00019.webp new file mode 100644 index 000000000..d06ac6317 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00020.webp b/app/src/main/res/drawable-xhdpi/game_home_00020.webp new file mode 100644 index 000000000..8b4ffc8e4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00021.webp b/app/src/main/res/drawable-xhdpi/game_home_00021.webp new file mode 100644 index 000000000..15caea29a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00022.webp b/app/src/main/res/drawable-xhdpi/game_home_00022.webp new file mode 100644 index 000000000..e80e4ffb3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00023.webp b/app/src/main/res/drawable-xhdpi/game_home_00023.webp new file mode 100644 index 000000000..b365321d4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00024.webp b/app/src/main/res/drawable-xhdpi/game_home_00024.webp new file mode 100644 index 000000000..5eeb68079 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00025.webp b/app/src/main/res/drawable-xhdpi/game_home_00025.webp new file mode 100644 index 000000000..9f4c77853 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00026.webp b/app/src/main/res/drawable-xhdpi/game_home_00026.webp new file mode 100644 index 000000000..572215e53 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00027.webp b/app/src/main/res/drawable-xhdpi/game_home_00027.webp new file mode 100644 index 000000000..a3e19e18d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00028.webp b/app/src/main/res/drawable-xhdpi/game_home_00028.webp new file mode 100644 index 000000000..093ba464b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00029.webp b/app/src/main/res/drawable-xhdpi/game_home_00029.webp new file mode 100644 index 000000000..5a16963ea Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00030.webp b/app/src/main/res/drawable-xhdpi/game_home_00030.webp new file mode 100644 index 000000000..6bba9cd70 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00031.webp b/app/src/main/res/drawable-xhdpi/game_home_00031.webp new file mode 100644 index 000000000..2d76e57a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00032.webp b/app/src/main/res/drawable-xhdpi/game_home_00032.webp new file mode 100644 index 000000000..99982b04b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00033.webp b/app/src/main/res/drawable-xhdpi/game_home_00033.webp new file mode 100644 index 000000000..3db7b0082 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00034.webp b/app/src/main/res/drawable-xhdpi/game_home_00034.webp new file mode 100644 index 000000000..013778615 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00035.webp b/app/src/main/res/drawable-xhdpi/game_home_00035.webp new file mode 100644 index 000000000..bf927a920 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00036.webp b/app/src/main/res/drawable-xhdpi/game_home_00036.webp new file mode 100644 index 000000000..b19f20086 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_00037.webp b/app/src/main/res/drawable-xhdpi/game_home_00037.webp new file mode 100644 index 000000000..06943a4bd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_home_find_player.png b/app/src/main/res/drawable-xhdpi/game_home_find_player.png new file mode 100644 index 000000000..be77ace01 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_home_find_player.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_ic_playing.png b/app/src/main/res/drawable-xhdpi/game_ic_playing.png new file mode 100644 index 000000000..4b39cace4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_ic_playing.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_img_banner.png b/app/src/main/res/drawable-xhdpi/game_img_banner.png new file mode 100644 index 000000000..531f51199 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_img_banner.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_img_banner1.png b/app/src/main/res/drawable-xhdpi/game_img_banner1.png new file mode 100644 index 000000000..8fff9c15a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_img_banner1.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_img_banner2.png b/app/src/main/res/drawable-xhdpi/game_img_banner2.png new file mode 100644 index 000000000..c5736596d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_img_banner2.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_img_bg.png b/app/src/main/res/drawable-xhdpi/game_img_bg.png new file mode 100644 index 000000000..49d34af89 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_img_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_img_bg2.png b/app/src/main/res/drawable-xhdpi/game_img_bg2.png new file mode 100644 index 000000000..29597e2a4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_img_bg2.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_results_bg.png b/app/src/main/res/drawable-xhdpi/game_results_bg.png new file mode 100644 index 000000000..792bc5679 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_results_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_results_share.png b/app/src/main/res/drawable-xhdpi/game_results_share.png new file mode 100644 index 000000000..6572f8531 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_results_share.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_bg.webp b/app/src/main/res/drawable-xhdpi/game_suited_bg.webp new file mode 100644 index 000000000..1d2984cb8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_close.png b/app/src/main/res/drawable-xhdpi/game_suited_close.png new file mode 100644 index 000000000..dcdf48e9b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_font.png b/app/src/main/res/drawable-xhdpi/game_suited_font.png new file mode 100644 index 000000000..cd7178fe3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_font.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_font2.png b/app/src/main/res/drawable-xhdpi/game_suited_font2.png new file mode 100644 index 000000000..5490147e5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_font2.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_ing.png b/app/src/main/res/drawable-xhdpi/game_suited_ing.png new file mode 100644 index 000000000..6c0d03ece Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_ing.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_ing1.png b/app/src/main/res/drawable-xhdpi/game_suited_ing1.png new file mode 100644 index 000000000..caa7a8ea2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_ing1.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_ing2.png b/app/src/main/res/drawable-xhdpi/game_suited_ing2.png new file mode 100644 index 000000000..dbaa9636f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_ing2.png differ diff --git a/app/src/main/res/drawable-xhdpi/game_suited_ing3.png b/app/src/main/res/drawable-xhdpi/game_suited_ing3.png new file mode 100644 index 000000000..58b45290e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/game_suited_ing3.png differ diff --git a/app/src/main/res/drawable-xhdpi/guide_p2p_message_voice_match_say_hi.9.png b/app/src/main/res/drawable-xhdpi/guide_p2p_message_voice_match_say_hi.9.png new file mode 100644 index 000000000..9abfc5939 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/guide_p2p_message_voice_match_say_hi.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_00000.webp b/app/src/main/res/drawable-xhdpi/home_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00001.webp b/app/src/main/res/drawable-xhdpi/home_00001.webp new file mode 100644 index 000000000..db2c4d36c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00002.webp b/app/src/main/res/drawable-xhdpi/home_00002.webp new file mode 100644 index 000000000..1115cbcac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00003.webp b/app/src/main/res/drawable-xhdpi/home_00003.webp new file mode 100644 index 000000000..eb276ba48 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00004.webp b/app/src/main/res/drawable-xhdpi/home_00004.webp new file mode 100644 index 000000000..92336264b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00005.webp b/app/src/main/res/drawable-xhdpi/home_00005.webp new file mode 100644 index 000000000..0e70a5d45 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00006.webp b/app/src/main/res/drawable-xhdpi/home_00006.webp new file mode 100644 index 000000000..ad9fad3f9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00007.webp b/app/src/main/res/drawable-xhdpi/home_00007.webp new file mode 100644 index 000000000..9b3350161 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00008.webp b/app/src/main/res/drawable-xhdpi/home_00008.webp new file mode 100644 index 000000000..dcdeec8f1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00009.webp b/app/src/main/res/drawable-xhdpi/home_00009.webp new file mode 100644 index 000000000..513c91da2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00010.webp b/app/src/main/res/drawable-xhdpi/home_00010.webp new file mode 100644 index 000000000..8204be356 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00011.webp b/app/src/main/res/drawable-xhdpi/home_00011.webp new file mode 100644 index 000000000..e26f76f72 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00012.webp b/app/src/main/res/drawable-xhdpi/home_00012.webp new file mode 100644 index 000000000..f92355b95 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00013.webp b/app/src/main/res/drawable-xhdpi/home_00013.webp new file mode 100644 index 000000000..fdea59e09 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00014.webp b/app/src/main/res/drawable-xhdpi/home_00014.webp new file mode 100644 index 000000000..904475f0b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00015.webp b/app/src/main/res/drawable-xhdpi/home_00015.webp new file mode 100644 index 000000000..130e2372b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00016.webp b/app/src/main/res/drawable-xhdpi/home_00016.webp new file mode 100644 index 000000000..5afaa782e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00017.webp b/app/src/main/res/drawable-xhdpi/home_00017.webp new file mode 100644 index 000000000..ff2ef7a34 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00018.webp b/app/src/main/res/drawable-xhdpi/home_00018.webp new file mode 100644 index 000000000..54d709a70 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00019.webp b/app/src/main/res/drawable-xhdpi/home_00019.webp new file mode 100644 index 000000000..f30688ec5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00020.webp b/app/src/main/res/drawable-xhdpi/home_00020.webp new file mode 100644 index 000000000..ba75e78cd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00021.webp b/app/src/main/res/drawable-xhdpi/home_00021.webp new file mode 100644 index 000000000..3041a703c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00022.webp b/app/src/main/res/drawable-xhdpi/home_00022.webp new file mode 100644 index 000000000..01d996def Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00023.webp b/app/src/main/res/drawable-xhdpi/home_00023.webp new file mode 100644 index 000000000..f97d21ec8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00024.webp b/app/src/main/res/drawable-xhdpi/home_00024.webp new file mode 100644 index 000000000..3bf9ffe10 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00025.webp b/app/src/main/res/drawable-xhdpi/home_00025.webp new file mode 100644 index 000000000..d76ce11a4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00026.webp b/app/src/main/res/drawable-xhdpi/home_00026.webp new file mode 100644 index 000000000..9f53667aa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00027.webp b/app/src/main/res/drawable-xhdpi/home_00027.webp new file mode 100644 index 000000000..abbd2b4b1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00028.webp b/app/src/main/res/drawable-xhdpi/home_00028.webp new file mode 100644 index 000000000..4ad31e414 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00029.webp b/app/src/main/res/drawable-xhdpi/home_00029.webp new file mode 100644 index 000000000..9f26ff684 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00030.webp b/app/src/main/res/drawable-xhdpi/home_00030.webp new file mode 100644 index 000000000..5c1f65fe9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00031.webp b/app/src/main/res/drawable-xhdpi/home_00031.webp new file mode 100644 index 000000000..82d12cf2a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00032.webp b/app/src/main/res/drawable-xhdpi/home_00032.webp new file mode 100644 index 000000000..1e5c975d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00033.webp b/app/src/main/res/drawable-xhdpi/home_00033.webp new file mode 100644 index 000000000..be740ddac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00034.webp b/app/src/main/res/drawable-xhdpi/home_00034.webp new file mode 100644 index 000000000..9abd63d17 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00035.webp b/app/src/main/res/drawable-xhdpi/home_00035.webp new file mode 100644 index 000000000..ca2f92304 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00036.webp b/app/src/main/res/drawable-xhdpi/home_00036.webp new file mode 100644 index 000000000..ca40b3229 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_00037.webp b/app/src/main/res/drawable-xhdpi/home_00037.webp new file mode 100644 index 000000000..c44fd0006 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_bg_find_player.webp b/app/src/main/res/drawable-xhdpi/home_bg_find_player.webp new file mode 100644 index 000000000..b5b399ac5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_bg_find_player.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_bg_sex_match.png b/app/src/main/res/drawable-xhdpi/home_bg_sex_match.png new file mode 100644 index 000000000..26a959990 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_bg_sex_match.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_friend_more.png b/app/src/main/res/drawable-xhdpi/home_friend_more.png new file mode 100644 index 000000000..9956cf05b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_friend_more.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_game_more.png b/app/src/main/res/drawable-xhdpi/home_game_more.png new file mode 100644 index 000000000..8b6b49d57 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_game_more.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_icon_list_game.png b/app/src/main/res/drawable-xhdpi/home_icon_list_game.png new file mode 100644 index 000000000..32916a6d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_icon_list_game.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_icon_list_room.png b/app/src/main/res/drawable-xhdpi/home_icon_list_room.png new file mode 100644 index 000000000..0d8a2aa12 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_icon_list_room.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_img_party_room.webp b/app/src/main/res/drawable-xhdpi/home_img_party_room.webp new file mode 100644 index 000000000..5fb0d1904 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_img_party_room.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_list_title_bg.webp b/app/src/main/res/drawable-xhdpi/home_list_title_bg.webp new file mode 100644 index 000000000..e61d280ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_list_title_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/home_ranking.png b/app/src/main/res/drawable-xhdpi/home_ranking.png new file mode 100644 index 000000000..c2853e590 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_ranking.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_ranking2.png b/app/src/main/res/drawable-xhdpi/home_ranking2.png new file mode 100644 index 000000000..7f79bad37 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_ranking2.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_ranking_img.png b/app/src/main/res/drawable-xhdpi/home_ranking_img.png new file mode 100644 index 000000000..d38fd2419 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_ranking_img.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_accompany.png b/app/src/main/res/drawable-xhdpi/ic_accompany.png new file mode 100644 index 000000000..640bd6bb9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_accompany.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_achievement_tips.png b/app/src/main/res/drawable-xhdpi/ic_achievement_tips.png new file mode 100644 index 000000000..0728dd949 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_achievement_tips.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ali_charge.webp b/app/src/main/res/drawable-xhdpi/ic_ali_charge.webp new file mode 100644 index 000000000..309414851 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ali_charge.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_approve.webp b/app/src/main/res/drawable-xhdpi/ic_approve.webp new file mode 100644 index 000000000..77945032e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_approve.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_top.png b/app/src/main/res/drawable-xhdpi/ic_arrow_top.png new file mode 100644 index 000000000..68bbefde2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_top.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_attened.webp b/app/src/main/res/drawable-xhdpi/ic_attened.webp new file mode 100644 index 000000000..a8969cc22 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_attened.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_attention_more.png b/app/src/main/res/drawable-xhdpi/ic_attention_more.png new file mode 100644 index 000000000..69e4aea99 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_attention_more.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bg_down_time.webp b/app/src/main/res/drawable-xhdpi/ic_bg_down_time.webp new file mode 100644 index 000000000..4ce3f83c0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bg_down_time.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bg_mask.webp b/app/src/main/res/drawable-xhdpi/ic_bg_mask.webp new file mode 100644 index 000000000..47a0f166e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bg_mask.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bind_success.png b/app/src/main/res/drawable-xhdpi/ic_bind_success.png new file mode 100644 index 000000000..e41c61b3f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bind_success.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_box_right.webp b/app/src/main/res/drawable-xhdpi/ic_box_right.webp new file mode 100644 index 000000000..e0df983fe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_box_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_box_unchecked.webp b/app/src/main/res/drawable-xhdpi/ic_box_unchecked.webp new file mode 100644 index 000000000..a887a1e27 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_box_unchecked.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_btn_bg_app_color.png b/app/src/main/res/drawable-xhdpi/ic_btn_bg_app_color.png new file mode 100644 index 000000000..b31c82a9c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_btn_bg_app_color.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_car_down.webp b/app/src/main/res/drawable-xhdpi/ic_car_down.webp new file mode 100644 index 000000000..8fdafc829 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_car_down.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_car_expire.webp b/app/src/main/res/drawable-xhdpi/ic_car_expire.webp new file mode 100644 index 000000000..d3ac94a6e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_car_expire.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_car_price.webp b/app/src/main/res/drawable-xhdpi/ic_car_price.webp new file mode 100644 index 000000000..0c7188966 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_car_price.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_car_selected.webp b/app/src/main/res/drawable-xhdpi/ic_car_selected.webp new file mode 100644 index 000000000..d1e53d2b2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_car_selected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_car_unselected.webp b/app/src/main/res/drawable-xhdpi/ic_car_unselected.webp new file mode 100644 index 000000000..9848e8aa0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_car_unselected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_card_has_used.webp b/app/src/main/res/drawable-xhdpi/ic_card_has_used.webp new file mode 100644 index 000000000..1bf0a19ce Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_card_has_used.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_card_invalid.webp b/app/src/main/res/drawable-xhdpi/ic_card_invalid.webp new file mode 100644 index 000000000..fda6cb3e7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_card_invalid.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_card_valid_days.webp b/app/src/main/res/drawable-xhdpi/ic_card_valid_days.webp new file mode 100644 index 000000000..e9ee8ca85 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_card_valid_days.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_charm_level.webp b/app/src/main/res/drawable-xhdpi/ic_charm_level.webp new file mode 100644 index 000000000..a3d3cef5f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_charm_level.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_chat_charm_level.webp b/app/src/main/res/drawable-xhdpi/ic_chat_charm_level.webp new file mode 100644 index 000000000..c0e001745 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_chat_charm_level.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_chat_game_overlays.png b/app/src/main/res/drawable-xhdpi/ic_chat_game_overlays.png new file mode 100644 index 000000000..38ca2dba0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_chat_game_overlays.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_chat_navigation_attention.webp b/app/src/main/res/drawable-xhdpi/ic_chat_navigation_attention.webp new file mode 100644 index 000000000..97800b8dd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_chat_navigation_attention.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_chat_user_level.webp b/app/src/main/res/drawable-xhdpi/ic_chat_user_level.webp new file mode 100644 index 000000000..70f3893ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_chat_user_level.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_chatterbox_init.webp b/app/src/main/res/drawable-xhdpi/ic_chatterbox_init.webp new file mode 100644 index 000000000..970755ddc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_chatterbox_init.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_close_all_server_one.webp b/app/src/main/res/drawable-xhdpi/ic_close_all_server_one.webp new file mode 100644 index 000000000..6fde9a590 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_close_all_server_one.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_close_all_server_two.webp b/app/src/main/res/drawable-xhdpi/ic_close_all_server_two.webp new file mode 100644 index 000000000..443649f8e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_close_all_server_two.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_close_gift.webp b/app/src/main/res/drawable-xhdpi/ic_close_gift.webp new file mode 100644 index 000000000..c3054bbfc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_close_gift.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_colon.webp b/app/src/main/res/drawable-xhdpi/ic_colon.webp new file mode 100644 index 000000000..31168efab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_colon.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_community_notice_list.png b/app/src/main/res/drawable-xhdpi/ic_community_notice_list.png new file mode 100644 index 000000000..83d70842c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_community_notice_list.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_community_notice_rink.png b/app/src/main/res/drawable-xhdpi/ic_community_notice_rink.png new file mode 100644 index 000000000..a18efd98f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_community_notice_rink.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_confirm_payment_close.png b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_close.png new file mode 100644 index 000000000..e75dc9455 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_down.webp b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_down.webp new file mode 100644 index 000000000..a7a828e16 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_down.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_up.webp b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_up.webp new file mode 100644 index 000000000..519a44b99 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_confirm_payment_select_way_up.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_contact.webp b/app/src/main/res/drawable-xhdpi/ic_contact.webp new file mode 100644 index 000000000..296a0eed4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_contact.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_dialog_close.png b/app/src/main/res/drawable-xhdpi/ic_dialog_close.png new file mode 100644 index 000000000..a05bb380d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_dialog_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_dissolve_family.webp b/app/src/main/res/drawable-xhdpi/ic_dissolve_family.webp new file mode 100644 index 000000000..eb2257b9e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_dissolve_family.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_exit_family.webp b/app/src/main/res/drawable-xhdpi/ic_exit_family.webp new file mode 100644 index 000000000..c817de70e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_exit_family.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_eyes_close.webp b/app/src/main/res/drawable-xhdpi/ic_eyes_close.webp new file mode 100644 index 000000000..4e06cc728 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_eyes_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_eyes_open.webp b/app/src/main/res/drawable-xhdpi/ic_eyes_open.webp new file mode 100644 index 000000000..8f76d31ef Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_eyes_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_add.webp b/app/src/main/res/drawable-xhdpi/ic_family_add.webp new file mode 100644 index 000000000..d8e7fadb5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_add.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_add_manager.webp b/app/src/main/res/drawable-xhdpi/ic_family_add_manager.webp new file mode 100644 index 000000000..8631ff8cf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_add_manager.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_add_mute.webp b/app/src/main/res/drawable-xhdpi/ic_family_add_mute.webp new file mode 100644 index 000000000..26f79ef3a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_add_mute.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_group_create.webp b/app/src/main/res/drawable-xhdpi/ic_family_group_create.webp new file mode 100644 index 000000000..aae3b51a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_group_create.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_list_search.webp b/app/src/main/res/drawable-xhdpi/ic_family_list_search.webp new file mode 100644 index 000000000..36019bc51 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_list_search.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_manage.png b/app/src/main/res/drawable-xhdpi/ic_family_manage.png new file mode 100644 index 000000000..a2c7165db Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_manage.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_manage_currency.webp b/app/src/main/res/drawable-xhdpi/ic_family_manage_currency.webp new file mode 100644 index 000000000..a527079d1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_manage_currency.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_manage_info.webp b/app/src/main/res/drawable-xhdpi/ic_family_manage_info.webp new file mode 100644 index 000000000..2b3e057f0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_manage_info.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_manage_member.webp b/app/src/main/res/drawable-xhdpi/ic_family_manage_member.webp new file mode 100644 index 000000000..a64d8b334 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_manage_member.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_more.webp b/app/src/main/res/drawable-xhdpi/ic_family_more.webp new file mode 100644 index 000000000..c9c8632ad Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_more.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_remove_manager.webp b/app/src/main/res/drawable-xhdpi/ic_family_remove_manager.webp new file mode 100644 index 000000000..a46d0afeb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_remove_manager.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_remove_mute.webp b/app/src/main/res/drawable-xhdpi/ic_family_remove_mute.webp new file mode 100644 index 000000000..66bbdc93e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_remove_mute.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_remove_person.webp b/app/src/main/res/drawable-xhdpi/ic_family_remove_person.webp new file mode 100644 index 000000000..2a1e15801 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_remove_person.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_search.webp b/app/src/main/res/drawable-xhdpi/ic_family_search.webp new file mode 100644 index 000000000..07b3e126e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_search.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_share.webp b/app/src/main/res/drawable-xhdpi/ic_family_share.webp new file mode 100644 index 000000000..47b8ccdc0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_share.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_family_team_default_avatar.webp b/app/src/main/res/drawable-xhdpi/ic_family_team_default_avatar.webp new file mode 100644 index 000000000..4f8fc76fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_family_team_default_avatar.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_female.webp b/app/src/main/res/drawable-xhdpi/ic_female.webp new file mode 100644 index 000000000..e9a336ea5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_female.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_gift_achievement.png b/app/src/main/res/drawable-xhdpi/ic_gift_achievement.png new file mode 100644 index 000000000..d8d3cfd9d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_gift_achievement.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_gift_change.png b/app/src/main/res/drawable-xhdpi/ic_gift_change.png new file mode 100644 index 000000000..0f3593f2c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_gift_change.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_gift_received.png b/app/src/main/res/drawable-xhdpi/ic_gift_received.png new file mode 100644 index 000000000..5d2ed0e75 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_gift_received.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_bottom_1.png b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_1.png new file mode 100644 index 000000000..a3d27072e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_1.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_bottom_2.png b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_2.png new file mode 100644 index 000000000..e2cc669b0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_bottom_3.png b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_3.png new file mode 100644 index 000000000..1953efd42 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_bottom_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_center_1.png b/app/src/main/res/drawable-xhdpi/ic_guide_center_1.png new file mode 100644 index 000000000..91cc3d16c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_center_1.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_center_2.png b/app/src/main/res/drawable-xhdpi/ic_guide_center_2.png new file mode 100644 index 000000000..c05927c99 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_center_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_center_3.png b/app/src/main/res/drawable-xhdpi/ic_guide_center_3.png new file mode 100644 index 000000000..3cd92ec3d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_center_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_home_1.webp b/app/src/main/res/drawable-xhdpi/ic_guide_home_1.webp new file mode 100644 index 000000000..021480c29 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_home_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_home_2.webp b/app/src/main/res/drawable-xhdpi/ic_guide_home_2.webp new file mode 100644 index 000000000..95e9fd947 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_home_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_top_1.png b/app/src/main/res/drawable-xhdpi/ic_guide_top_1.png new file mode 100644 index 000000000..fae810b2e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_top_1.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_top_2.png b/app/src/main/res/drawable-xhdpi/ic_guide_top_2.png new file mode 100644 index 000000000..cb1eabab4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_top_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_guide_top_3.png b/app/src/main/res/drawable-xhdpi/ic_guide_top_3.png new file mode 100644 index 000000000..2b821386a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_guide_top_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_high_audio.webp b/app/src/main/res/drawable-xhdpi/ic_high_audio.webp new file mode 100644 index 000000000..32973b74a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_high_audio.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_accost.png b/app/src/main/res/drawable-xhdpi/ic_home_accost.png new file mode 100644 index 000000000..7fe788847 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_accost.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_arrow_down_black.webp b/app/src/main/res/drawable-xhdpi/ic_home_arrow_down_black.webp new file mode 100644 index 000000000..ca1f99798 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_arrow_down_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_arrow_up_black.png b/app/src/main/res/drawable-xhdpi/ic_home_arrow_up_black.png new file mode 100644 index 000000000..97bc8fe17 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_arrow_up_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_female_age.png b/app/src/main/res/drawable-xhdpi/ic_home_female_age.png new file mode 100644 index 000000000..ba38fc725 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_female_age.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_find_ta.png b/app/src/main/res/drawable-xhdpi/ic_home_find_ta.png new file mode 100644 index 000000000..a239f6667 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_find_ta.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_list_arrow_right.png b/app/src/main/res/drawable-xhdpi/ic_home_list_arrow_right.png new file mode 100644 index 000000000..f5aa2dd99 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_list_arrow_right.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_male_age.png b/app/src/main/res/drawable-xhdpi/ic_home_male_age.png new file mode 100644 index 000000000..e83564256 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_male_age.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_play_together.png b/app/src/main/res/drawable-xhdpi/ic_home_play_together.png new file mode 100644 index 000000000..b63a63a38 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_play_together.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_search.webp b/app/src/main/res/drawable-xhdpi/ic_home_search.webp new file mode 100644 index 000000000..439266a15 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home_search.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_invite_family.webp b/app/src/main/res/drawable-xhdpi/ic_invite_family.webp new file mode 100644 index 000000000..c39dd4b84 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_invite_family.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_key_large.webp b/app/src/main/res/drawable-xhdpi/ic_key_large.webp new file mode 100644 index 000000000..b3b274d76 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_key_large.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_king_recommend.webp b/app/src/main/res/drawable-xhdpi/ic_king_recommend.webp new file mode 100644 index 000000000..c7775b019 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_king_recommend.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_knap_gift_empty.webp b/app/src/main/res/drawable-xhdpi/ic_knap_gift_empty.webp new file mode 100644 index 000000000..7f1580892 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_knap_gift_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ktv_clear.webp b/app/src/main/res/drawable-xhdpi/ic_ktv_clear.webp new file mode 100644 index 000000000..7d9028d84 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ktv_clear.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ktv_close.webp b/app/src/main/res/drawable-xhdpi/ic_ktv_close.webp new file mode 100644 index 000000000..9e523f65a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ktv_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ktv_search.webp b/app/src/main/res/drawable-xhdpi/ic_ktv_search.webp new file mode 100644 index 000000000..957cf8c3b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ktv_search.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ktv_select.webp b/app/src/main/res/drawable-xhdpi/ic_ktv_select.webp new file mode 100644 index 000000000..1a9a484ab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ktv_select.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_ktv_tag.webp b/app/src/main/res/drawable-xhdpi/ic_ktv_tag.webp new file mode 100644 index 000000000..c0b50012d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_ktv_tag.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_1.webp b/app/src/main/res/drawable-xhdpi/ic_living_1.webp new file mode 100644 index 000000000..5fbbf76c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_10.png b/app/src/main/res/drawable-xhdpi/ic_living_10.png new file mode 100644 index 000000000..990562a4f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_10.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_11.png b/app/src/main/res/drawable-xhdpi/ic_living_11.png new file mode 100644 index 000000000..47f722ca3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_11.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_12.png b/app/src/main/res/drawable-xhdpi/ic_living_12.png new file mode 100644 index 000000000..8f8d6212f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_12.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_2.png b/app/src/main/res/drawable-xhdpi/ic_living_2.png new file mode 100644 index 000000000..cc765426b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_3.png b/app/src/main/res/drawable-xhdpi/ic_living_3.png new file mode 100644 index 000000000..9db96b8d6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_4.png b/app/src/main/res/drawable-xhdpi/ic_living_4.png new file mode 100644 index 000000000..f4a6d5d77 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_4.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_5.png b/app/src/main/res/drawable-xhdpi/ic_living_5.png new file mode 100644 index 000000000..895bd7d39 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_5.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_6.png b/app/src/main/res/drawable-xhdpi/ic_living_6.png new file mode 100644 index 000000000..089c76042 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_6.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_7.png b/app/src/main/res/drawable-xhdpi/ic_living_7.png new file mode 100644 index 000000000..7c6f8f52f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_7.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_8.webp b/app/src/main/res/drawable-xhdpi/ic_living_8.webp new file mode 100644 index 000000000..41fce43cd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_8.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_9.png b/app/src/main/res/drawable-xhdpi/ic_living_9.png new file mode 100644 index 000000000..e02f3605a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_9.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_living_room_history.png b/app/src/main/res/drawable-xhdpi/ic_living_room_history.png new file mode 100644 index 000000000..1ac861415 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_living_room_history.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_male.webp b/app/src/main/res/drawable-xhdpi/ic_male.webp new file mode 100644 index 000000000..22417491e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_male.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mark_discount.webp b/app/src/main/res/drawable-xhdpi/ic_mark_discount.webp new file mode 100644 index 000000000..17abd3907 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mark_discount.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mark_exclusive.webp b/app/src/main/res/drawable-xhdpi/ic_mark_exclusive.webp new file mode 100644 index 000000000..dc2fbc16e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mark_exclusive.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mark_limit.webp b/app/src/main/res/drawable-xhdpi/ic_mark_limit.webp new file mode 100644 index 000000000..b527dd4ed Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mark_limit.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mark_new.webp b/app/src/main/res/drawable-xhdpi/ic_mark_new.webp new file mode 100644 index 000000000..85663989d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mark_new.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_monster_close.webp b/app/src/main/res/drawable-xhdpi/ic_monster_close.webp new file mode 100644 index 000000000..53114bbde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_monster_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_more.webp b/app/src/main/res/drawable-xhdpi/ic_more.webp new file mode 100644 index 000000000..c1bcbbfb6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_more.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_music_added.webp b/app/src/main/res/drawable-xhdpi/ic_music_added.webp new file mode 100644 index 000000000..ae5a95d0a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_music_added.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_mute_notification.webp b/app/src/main/res/drawable-xhdpi/ic_mute_notification.webp new file mode 100644 index 000000000..5e344413c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_mute_notification.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_my_car_no.webp b/app/src/main/res/drawable-xhdpi/ic_my_car_no.webp new file mode 100644 index 000000000..585237fca Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_my_car_no.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_my_id.webp b/app/src/main/res/drawable-xhdpi/ic_my_id.webp new file mode 100644 index 000000000..155219511 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_my_id.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_new_user_task_radish.webp b/app/src/main/res/drawable-xhdpi/ic_new_user_task_radish.webp new file mode 100644 index 000000000..685d86017 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_new_user_task_radish.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_nick_delete.webp b/app/src/main/res/drawable-xhdpi/ic_nick_delete.webp new file mode 100644 index 000000000..bfade565a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_nick_delete.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_normal_room.png b/app/src/main/res/drawable-xhdpi/ic_normal_room.png new file mode 100644 index 000000000..bdcbef759 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_normal_room.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num0.png b/app/src/main/res/drawable-xhdpi/ic_num0.png new file mode 100644 index 000000000..497890e98 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num0.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num1.png b/app/src/main/res/drawable-xhdpi/ic_num1.png new file mode 100644 index 000000000..089498c6e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num1.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num2.png b/app/src/main/res/drawable-xhdpi/ic_num2.png new file mode 100644 index 000000000..f29f37d97 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num2.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num3.png b/app/src/main/res/drawable-xhdpi/ic_num3.png new file mode 100644 index 000000000..9dae3dce0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num3.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num4.png b/app/src/main/res/drawable-xhdpi/ic_num4.png new file mode 100644 index 000000000..33195c550 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num4.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num5.png b/app/src/main/res/drawable-xhdpi/ic_num5.png new file mode 100644 index 000000000..1add70f25 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num5.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num6.png b/app/src/main/res/drawable-xhdpi/ic_num6.png new file mode 100644 index 000000000..ec6a14054 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num6.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num7.webp b/app/src/main/res/drawable-xhdpi/ic_num7.webp new file mode 100644 index 000000000..3ab928393 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num7.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num8.webp b/app/src/main/res/drawable-xhdpi/ic_num8.webp new file mode 100644 index 000000000..f42b31523 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num8.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_num9.webp b/app/src/main/res/drawable-xhdpi/ic_num9.webp new file mode 100644 index 000000000..8e4d3d0be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_num9.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_open_room.png b/app/src/main/res/drawable-xhdpi/ic_open_room.png new file mode 100644 index 000000000..91a22806b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_open_room.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_patriarch_tag.webp b/app/src/main/res/drawable-xhdpi/ic_patriarch_tag.webp new file mode 100644 index 000000000..e72aa33a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_patriarch_tag.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_person_edit.webp b/app/src/main/res/drawable-xhdpi/ic_person_edit.webp new file mode 100644 index 000000000..86af383de Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_person_edit.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_projection.webp b/app/src/main/res/drawable-xhdpi/ic_projection.webp new file mode 100644 index 000000000..d2eca1903 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_projection.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_pwd_close.webp b/app/src/main/res/drawable-xhdpi/ic_pwd_close.webp new file mode 100644 index 000000000..459499916 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_pwd_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_1.webp b/app/src/main/res/drawable-xhdpi/ic_rank_1.webp new file mode 100644 index 000000000..1c7aa10e9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_10.webp b/app/src/main/res/drawable-xhdpi/ic_rank_10.webp new file mode 100644 index 000000000..e588bc325 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_10.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_11.webp b/app/src/main/res/drawable-xhdpi/ic_rank_11.webp new file mode 100644 index 000000000..82defee16 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_11.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_12.webp b/app/src/main/res/drawable-xhdpi/ic_rank_12.webp new file mode 100644 index 000000000..9b4e00a1a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_12.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_13.webp b/app/src/main/res/drawable-xhdpi/ic_rank_13.webp new file mode 100644 index 000000000..54ab9731f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_13.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_14.png b/app/src/main/res/drawable-xhdpi/ic_rank_14.png new file mode 100644 index 000000000..638e37c14 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_14.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_15.webp b/app/src/main/res/drawable-xhdpi/ic_rank_15.webp new file mode 100644 index 000000000..037620e5f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_15.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_16.webp b/app/src/main/res/drawable-xhdpi/ic_rank_16.webp new file mode 100644 index 000000000..d8eee381c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_16.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_17.webp b/app/src/main/res/drawable-xhdpi/ic_rank_17.webp new file mode 100644 index 000000000..98c7c8bc0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_17.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_18.webp b/app/src/main/res/drawable-xhdpi/ic_rank_18.webp new file mode 100644 index 000000000..2a3a6ad19 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_18.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_19.webp b/app/src/main/res/drawable-xhdpi/ic_rank_19.webp new file mode 100644 index 000000000..32b6b3ecf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_19.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_2.webp b/app/src/main/res/drawable-xhdpi/ic_rank_2.webp new file mode 100644 index 000000000..c09b92caf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_20.webp b/app/src/main/res/drawable-xhdpi/ic_rank_20.webp new file mode 100644 index 000000000..235599394 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_20.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_3.webp b/app/src/main/res/drawable-xhdpi/ic_rank_3.webp new file mode 100644 index 000000000..f021fa538 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_4.png b/app/src/main/res/drawable-xhdpi/ic_rank_4.png new file mode 100644 index 000000000..67419efce Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_4.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_5.webp b/app/src/main/res/drawable-xhdpi/ic_rank_5.webp new file mode 100644 index 000000000..083a2cdde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_5.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_6.webp b/app/src/main/res/drawable-xhdpi/ic_rank_6.webp new file mode 100644 index 000000000..fe1aae120 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_6.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_7.webp b/app/src/main/res/drawable-xhdpi/ic_rank_7.webp new file mode 100644 index 000000000..f803cc40a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_7.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_8.webp b/app/src/main/res/drawable-xhdpi/ic_rank_8.webp new file mode 100644 index 000000000..6f77035d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_8.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rank_9.webp b/app/src/main/res/drawable-xhdpi/ic_rank_9.webp new file mode 100644 index 000000000..b494a77d5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rank_9.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rcmd_help.webp b/app/src/main/res/drawable-xhdpi/ic_rcmd_help.webp new file mode 100644 index 000000000..a4baae6ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rcmd_help.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recall_close.webp b/app/src/main/res/drawable-xhdpi/ic_recall_close.webp new file mode 100644 index 000000000..153feb529 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recall_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording.webp b/app/src/main/res/drawable-xhdpi/ic_recording.webp new file mode 100644 index 000000000..bfd795be1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording_end.webp b/app/src/main/res/drawable-xhdpi/ic_recording_end.webp new file mode 100644 index 000000000..16db1ceab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording_end.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording_finish.webp b/app/src/main/res/drawable-xhdpi/ic_recording_finish.webp new file mode 100644 index 000000000..60ed5ad78 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording_finish.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording_listener.webp b/app/src/main/res/drawable-xhdpi/ic_recording_listener.webp new file mode 100644 index 000000000..80ed3d1e7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording_listener.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording_pause.webp b/app/src/main/res/drawable-xhdpi/ic_recording_pause.webp new file mode 100644 index 000000000..375ef3771 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_recording_re_record.webp b/app/src/main/res/drawable-xhdpi/ic_recording_re_record.webp new file mode 100644 index 000000000..882b133aa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_recording_re_record.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_register_back.webp b/app/src/main/res/drawable-xhdpi/ic_register_back.webp new file mode 100644 index 000000000..5fd7a3d00 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_register_back.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_leave.webp b/app/src/main/res/drawable-xhdpi/ic_room_leave.webp new file mode 100644 index 000000000..c03d409c3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_leave.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_lock.webp b/app/src/main/res/drawable-xhdpi/ic_room_lock.webp new file mode 100644 index 000000000..8094de8cc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_lock.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_lock_icon.webp b/app/src/main/res/drawable-xhdpi/ic_room_lock_icon.webp new file mode 100644 index 000000000..539e239e7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_lock_icon.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_opt_in_pk.webp b/app/src/main/res/drawable-xhdpi/ic_room_opt_in_pk.webp new file mode 100644 index 000000000..b53ade97c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_opt_in_pk.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv.webp b/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv.webp new file mode 100644 index 000000000..fdaa3285c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv_select_song.webp b/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv_select_song.webp new file mode 100644 index 000000000..709177da9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_opt_ktv_select_song.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_opt_op_pk.webp b/app/src/main/res/drawable-xhdpi/ic_room_opt_op_pk.webp new file mode 100644 index 000000000..f374e9a9a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_opt_op_pk.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_green.webp b/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_green.webp new file mode 100644 index 000000000..be9238e1e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_green.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_pink.webp b/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_pink.webp new file mode 100644 index 000000000..68f7b29fc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_rank_top_3_pink.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_send_search.webp b/app/src/main/res/drawable-xhdpi/ic_send_search.webp new file mode 100644 index 000000000..07b3e126e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_send_search.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_send_tag.webp b/app/src/main/res/drawable-xhdpi/ic_send_tag.webp new file mode 100644 index 000000000..0aeb62d10 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_send_tag.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_share.webp b/app/src/main/res/drawable-xhdpi/ic_share.webp new file mode 100644 index 000000000..a9a6ea81e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_share.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_star.png b/app/src/main/res/drawable-xhdpi/ic_star.png new file mode 100644 index 000000000..d9b7cafc7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_star.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_system_notification.webp b/app/src/main/res/drawable-xhdpi/ic_system_notification.webp new file mode 100644 index 000000000..2794da284 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_system_notification.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_1.webp b/app/src/main/res/drawable-xhdpi/ic_tag_1.webp new file mode 100644 index 000000000..efd2db1ac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_2.webp b/app/src/main/res/drawable-xhdpi/ic_tag_2.webp new file mode 100644 index 000000000..639b08e1e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_3.webp b/app/src/main/res/drawable-xhdpi/ic_tag_3.webp new file mode 100644 index 000000000..cc361837d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_4.webp b/app/src/main/res/drawable-xhdpi/ic_tag_4.webp new file mode 100644 index 000000000..88b424727 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_4.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_5.webp b/app/src/main/res/drawable-xhdpi/ic_tag_5.webp new file mode 100644 index 000000000..bad42fde1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_5.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_6.webp b/app/src/main/res/drawable-xhdpi/ic_tag_6.webp new file mode 100644 index 000000000..82aa3ee39 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_6.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_7.webp b/app/src/main/res/drawable-xhdpi/ic_tag_7.webp new file mode 100644 index 000000000..c617d8304 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_7.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_tag_emperor_recommend.png b/app/src/main/res/drawable-xhdpi/ic_tag_emperor_recommend.png new file mode 100644 index 000000000..52983d6ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_tag_emperor_recommend.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_temp_achievement.png b/app/src/main/res/drawable-xhdpi/ic_temp_achievement.png new file mode 100644 index 000000000..fc48b68ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_temp_achievement.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_textview_close.webp b/app/src/main/res/drawable-xhdpi/ic_textview_close.webp new file mode 100644 index 000000000..420975fa5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_textview_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_textview_open.webp b/app/src/main/res/drawable-xhdpi/ic_textview_open.webp new file mode 100644 index 000000000..5ce57e7c1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_textview_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_time_left.webp b/app/src/main/res/drawable-xhdpi/ic_time_left.webp new file mode 100644 index 000000000..af355f34f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_time_left.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_user_charm_level.webp b/app/src/main/res/drawable-xhdpi/ic_user_charm_level.webp new file mode 100644 index 000000000..f13b38626 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_user_charm_level.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_user_info_address.webp b/app/src/main/res/drawable-xhdpi/ic_user_info_address.webp new file mode 100644 index 000000000..28401ee25 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_user_info_address.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_user_info_play.webp b/app/src/main/res/drawable-xhdpi/ic_user_info_play.webp new file mode 100644 index 000000000..9c3e4f0fa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_user_info_play.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_user_info_stop.webp b/app/src/main/res/drawable-xhdpi/ic_user_info_stop.webp new file mode 100644 index 000000000..081d25a47 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_user_info_stop.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_bar_no_data_add.webp b/app/src/main/res/drawable-xhdpi/ic_voice_bar_no_data_add.webp new file mode 100644 index 000000000..18237d813 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_bar_no_data_add.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_bar_pause.webp b/app/src/main/res/drawable-xhdpi/ic_voice_bar_pause.webp new file mode 100644 index 000000000..53c3242bf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_bar_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_bar_play.webp b/app/src/main/res/drawable-xhdpi/ic_voice_bar_play.webp new file mode 100644 index 000000000..122238831 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_bar_play.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_bottle_im_msg_heart.webp b/app/src/main/res/drawable-xhdpi/ic_voice_bottle_im_msg_heart.webp new file mode 100644 index 000000000..f7292012d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_bottle_im_msg_heart.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_bottle_my_voice_entrance.webp b/app/src/main/res/drawable-xhdpi/ic_voice_bottle_my_voice_entrance.webp new file mode 100644 index 000000000..eddcca7a3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_bottle_my_voice_entrance.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_card_bottom_shadow.webp b/app/src/main/res/drawable-xhdpi/ic_voice_card_bottom_shadow.webp new file mode 100644 index 000000000..8b1df1dfe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_card_bottom_shadow.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_card_change.webp b/app/src/main/res/drawable-xhdpi/ic_voice_card_change.webp new file mode 100644 index 000000000..7f391f50e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_card_change.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_heard_count.webp b/app/src/main/res/drawable-xhdpi/ic_voice_heard_count.webp new file mode 100644 index 000000000..db6447413 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_heard_count.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_im_msg_say_hi.webp b/app/src/main/res/drawable-xhdpi/ic_voice_im_msg_say_hi.webp new file mode 100644 index 000000000..51f3c6db4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_im_msg_say_hi.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_in_review.webp b/app/src/main/res/drawable-xhdpi/ic_voice_in_review.webp new file mode 100644 index 000000000..e2752b89b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_in_review.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_like_count.webp b/app/src/main/res/drawable-xhdpi/ic_voice_like_count.webp new file mode 100644 index 000000000..92f7c8ffa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_like_count.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ic_voice_match_filter_gender.png b/app/src/main/res/drawable-xhdpi/ic_voice_match_filter_gender.png new file mode 100644 index 000000000..6398376ac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_voice_match_filter_gender.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_vs.png b/app/src/main/res/drawable-xhdpi/ic_vs.png new file mode 100644 index 000000000..934b88dfb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_vs.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_webview_close.png b/app/src/main/res/drawable-xhdpi/ic_webview_close.png new file mode 100644 index 000000000..7403be988 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_webview_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_wechat_charge.webp b/app/src/main/res/drawable-xhdpi/ic_wechat_charge.webp new file mode 100644 index 000000000..9f5eb8df0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_wechat_charge.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_activity_timer.png b/app/src/main/res/drawable-xhdpi/icon_activity_timer.png new file mode 100644 index 000000000..823f7b2b9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_activity_timer.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_add_black_list.webp b/app/src/main/res/drawable-xhdpi/icon_add_black_list.webp new file mode 100644 index 000000000..6522672fa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_add_black_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_add_photo.webp b/app/src/main/res/drawable-xhdpi/icon_add_photo.webp new file mode 100644 index 000000000..c1928e0f4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_add_photo.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_admin_logo.webp b/app/src/main/res/drawable-xhdpi/icon_admin_logo.webp new file mode 100644 index 000000000..44168ef51 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_admin_logo.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_0.webp b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_0.webp new file mode 100644 index 000000000..6b2248a56 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_0.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_1.png b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_1.png new file mode 100644 index 000000000..5a4e35c25 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_1.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_2.webp b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_2.webp new file mode 100644 index 000000000..840290870 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_3.webp b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_3.webp new file mode 100644 index 000000000..5a8fd9c0b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_4.webp b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_4.webp new file mode 100644 index 000000000..c7a4bc4ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_anim_attention_live_4.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_arrow_left_black.webp b/app/src/main/res/drawable-xhdpi/icon_arrow_left_black.webp new file mode 100644 index 000000000..4c456a735 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_arrow_left_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_arrow_right_small.webp b/app/src/main/res/drawable-xhdpi/icon_arrow_right_small.webp new file mode 100644 index 000000000..8f660039a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_arrow_right_small.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_attention_flag_auction.webp b/app/src/main/res/drawable-xhdpi/icon_attention_flag_auction.webp new file mode 100644 index 000000000..2294d181c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_attention_flag_auction.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_attention_flag_homeparty.webp b/app/src/main/res/drawable-xhdpi/icon_attention_flag_homeparty.webp new file mode 100644 index 000000000..a6c0d878c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_attention_flag_homeparty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_attention_flag_light_chat.webp b/app/src/main/res/drawable-xhdpi/icon_attention_flag_light_chat.webp new file mode 100644 index 000000000..36fd94f57 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_attention_flag_light_chat.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_corn.webp b/app/src/main/res/drawable-xhdpi/icon_auction_corn.webp new file mode 100644 index 000000000..7fc7bfb2a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_corn.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_finish_bg.webp b/app/src/main/res/drawable-xhdpi/icon_auction_finish_bg.webp new file mode 100644 index 000000000..efe268e29 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_finish_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_open.webp b/app/src/main/res/drawable-xhdpi/icon_auction_open.webp new file mode 100644 index 000000000..20bde51a9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_week_list_first.webp b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_first.webp new file mode 100644 index 000000000..72f1d5652 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_week_list_second.webp b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_second.webp new file mode 100644 index 000000000..59f12d9bb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_second.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_week_list_third.webp b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_third.webp new file mode 100644 index 000000000..3645f1a04 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_week_list_third.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_auction_wing.webp b/app/src/main/res/drawable-xhdpi/icon_auction_wing.webp new file mode 100644 index 000000000..369f79c78 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_auction_wing.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_award_title_left.webp b/app/src/main/res/drawable-xhdpi/icon_award_title_left.webp new file mode 100644 index 000000000..1d6b939ef Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_award_title_left.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_award_title_right.webp b/app/src/main/res/drawable-xhdpi/icon_award_title_right.webp new file mode 100644 index 000000000..7eeb794dc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_award_title_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_be_acution.webp b/app/src/main/res/drawable-xhdpi/icon_be_acution.webp new file mode 100644 index 000000000..f967b4bb3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_be_acution.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bg_number_default.png b/app/src/main/res/drawable-xhdpi/icon_bg_number_default.png new file mode 100644 index 000000000..9c21de538 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bg_number_default.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_big_reward.webp b/app/src/main/res/drawable-xhdpi/icon_big_reward.webp new file mode 100644 index 000000000..dd35588ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_big_reward.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bills_charge.webp b/app/src/main/res/drawable-xhdpi/icon_bills_charge.webp new file mode 100644 index 000000000..84f86e7e2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bills_charge.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bills_gift.webp b/app/src/main/res/drawable-xhdpi/icon_bills_gift.webp new file mode 100644 index 000000000..d258e3de6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bills_gift.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bills_red.webp b/app/src/main/res/drawable-xhdpi/icon_bills_red.webp new file mode 100644 index 000000000..0a28425c2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bills_red.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bills_withdraw.webp b/app/src/main/res/drawable-xhdpi/icon_bills_withdraw.webp new file mode 100644 index 000000000..9e01fac0e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bills_withdraw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_buy_use_false.webp b/app/src/main/res/drawable-xhdpi/icon_buy_use_false.webp new file mode 100644 index 000000000..b586d5a9f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_buy_use_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_buy_use_ture.webp b/app/src/main/res/drawable-xhdpi/icon_buy_use_ture.webp new file mode 100644 index 000000000..773ecb4f7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_buy_use_ture.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cd_key_bg.png b/app/src/main/res/drawable-xhdpi/icon_cd_key_bg.png new file mode 100644 index 000000000..ab122f8a3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cd_key_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cd_key_btn.webp b/app/src/main/res/drawable-xhdpi/icon_cd_key_btn.webp new file mode 100644 index 000000000..a355447c1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cd_key_btn.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_charge_dialog_bg.webp b/app/src/main/res/drawable-xhdpi/icon_charge_dialog_bg.webp new file mode 100644 index 000000000..4641408bc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_charge_dialog_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_chat_light.webp b/app/src/main/res/drawable-xhdpi/icon_chat_light.webp new file mode 100644 index 000000000..60c74ae37 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_chat_light.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_clear_song.webp b/app/src/main/res/drawable-xhdpi/icon_clear_song.webp new file mode 100644 index 000000000..efe5a87fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_clear_song.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_blue.webp b/app/src/main/res/drawable-xhdpi/icon_close_blue.webp new file mode 100644 index 000000000..87a575ac7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_blue.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_dialog_web.png b/app/src/main/res/drawable-xhdpi/icon_close_dialog_web.png new file mode 100644 index 000000000..7dd7022fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_dialog_web.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_gift_value.webp b/app/src/main/res/drawable-xhdpi/icon_close_gift_value.webp new file mode 100644 index 000000000..4d07d1ce3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_gift_value.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_labe.webp b/app/src/main/res/drawable-xhdpi/icon_close_labe.webp new file mode 100644 index 000000000..d79241add Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_labe.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_my_effect.webp b/app/src/main/res/drawable-xhdpi/icon_close_my_effect.webp new file mode 100644 index 000000000..e923c868a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_my_effect.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_public_screen.webp b/app/src/main/res/drawable-xhdpi/icon_close_public_screen.webp new file mode 100644 index 000000000..aa0ea5e79 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_public_screen.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_red.webp b/app/src/main/res/drawable-xhdpi/icon_close_red.webp new file mode 100644 index 000000000..22e415aea Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_red.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_room_effect.webp b/app/src/main/res/drawable-xhdpi/icon_close_room_effect.webp new file mode 100644 index 000000000..e923c868a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_room_effect.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_sign_in_dialog.webp b/app/src/main/res/drawable-xhdpi/icon_close_sign_in_dialog.webp new file mode 100644 index 000000000..7e8f1557a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_sign_in_dialog.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_close_user_dialog.png b/app/src/main/res/drawable-xhdpi/icon_close_user_dialog.png new file mode 100644 index 000000000..0adbe0eea Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_close_user_dialog.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_common_failure.png b/app/src/main/res/drawable-xhdpi/icon_common_failure.png new file mode 100644 index 000000000..f40838bf0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_common_failure.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_common_failure_green.webp b/app/src/main/res/drawable-xhdpi/icon_common_failure_green.webp new file mode 100644 index 000000000..cc30ebee5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_common_failure_green.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_common_no_network.webp b/app/src/main/res/drawable-xhdpi/icon_common_no_network.webp new file mode 100644 index 000000000..e62de61df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_common_no_network.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_first.webp b/app/src/main/res/drawable-xhdpi/icon_consume_first.webp new file mode 100644 index 000000000..0db02c3de Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_first_empty.webp b/app/src/main/res/drawable-xhdpi/icon_consume_first_empty.webp new file mode 100644 index 000000000..71095eb90 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_first_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_second.webp b/app/src/main/res/drawable-xhdpi/icon_consume_second.webp new file mode 100644 index 000000000..fee24fd30 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_second.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_second_empty.webp b/app/src/main/res/drawable-xhdpi/icon_consume_second_empty.webp new file mode 100644 index 000000000..b6a1c92f7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_second_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_third.webp b/app/src/main/res/drawable-xhdpi/icon_consume_third.webp new file mode 100644 index 000000000..7dcaab603 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_third.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_consume_third_empty.webp b/app/src/main/res/drawable-xhdpi/icon_consume_third_empty.webp new file mode 100644 index 000000000..3d6a71602 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_consume_third_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_contribute_left.webp b/app/src/main/res/drawable-xhdpi/icon_contribute_left.webp new file mode 100644 index 000000000..522926974 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_contribute_left.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_contribute_list.webp b/app/src/main/res/drawable-xhdpi/icon_contribute_list.webp new file mode 100644 index 000000000..db4bad053 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_contribute_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_contribute_list_cp.png b/app/src/main/res/drawable-xhdpi/icon_contribute_list_cp.png new file mode 100644 index 000000000..636138749 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_contribute_list_cp.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_current_auction_list.webp b/app/src/main/res/drawable-xhdpi/icon_current_auction_list.webp new file mode 100644 index 000000000..ac20792ec Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_current_auction_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_current_list_first.webp b/app/src/main/res/drawable-xhdpi/icon_current_list_first.webp new file mode 100644 index 000000000..c58fa7f96 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_current_list_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_current_list_second.webp b/app/src/main/res/drawable-xhdpi/icon_current_list_second.webp new file mode 100644 index 000000000..f6996cf11 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_current_list_second.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_current_list_third.webp b/app/src/main/res/drawable-xhdpi/icon_current_list_third.webp new file mode 100644 index 000000000..475b8b971 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_current_list_third.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_date_yellow.png b/app/src/main/res/drawable-xhdpi/icon_date_yellow.png new file mode 100644 index 000000000..7f888cf93 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_date_yellow.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_decoration_action.webp b/app/src/main/res/drawable-xhdpi/icon_decoration_action.webp new file mode 100644 index 000000000..f5ff03411 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_decoration_action.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_default_auction_avatar.webp b/app/src/main/res/drawable-xhdpi/icon_default_auction_avatar.webp new file mode 100644 index 000000000..10237ac8b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_default_auction_avatar.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_attent.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_attent.webp new file mode 100644 index 000000000..630669a6b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_attent.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_cancel_attent.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_cancel_attent.webp new file mode 100644 index 000000000..bff085e2c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_cancel_attent.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_find_ta.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_find_ta.webp new file mode 100644 index 000000000..ff22ff524 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_find_ta.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_kickout_room.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_kickout_room.webp new file mode 100644 index 000000000..dfed3799c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_kickout_room.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_mark_black_list.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_mark_black_list.webp new file mode 100644 index 000000000..c4c07d3fd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_mark_black_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_send_decaration.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_send_decaration.webp new file mode 100644 index 000000000..237fa4611 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_send_decaration.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_send_magic.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_send_magic.webp new file mode 100644 index 000000000..5e012334d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_send_magic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_false.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_false.webp new file mode 100644 index 000000000..a46a152c1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_ture.webp b/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_ture.webp new file mode 100644 index 000000000..68031150f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_dialog_set_manager_ture.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_diamond.webp b/app/src/main/res/drawable-xhdpi/icon_diamond.webp new file mode 100644 index 000000000..064168544 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_diamond.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_donee_arrow.png b/app/src/main/res/drawable-xhdpi/icon_donee_arrow.png new file mode 100644 index 000000000..bd55eec5c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_donee_arrow.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_draw_gold.webp b/app/src/main/res/drawable-xhdpi/icon_draw_gold.webp new file mode 100644 index 000000000..34b1e4e7e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_draw_gold.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_edit_black.webp b/app/src/main/res/drawable-xhdpi/icon_edit_black.webp new file mode 100644 index 000000000..aa8bce6fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_edit_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_erban_friends.webp b/app/src/main/res/drawable-xhdpi/icon_erban_friends.webp new file mode 100644 index 000000000..9da47ff3b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_erban_friends.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_erban_friends_disable.webp b/app/src/main/res/drawable-xhdpi/icon_erban_friends_disable.webp new file mode 100644 index 000000000..f4e740f80 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_erban_friends_disable.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_erban_grid_2_empty.webp b/app/src/main/res/drawable-xhdpi/icon_erban_grid_2_empty.webp new file mode 100644 index 000000000..5e717690e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_erban_grid_2_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_erban_grid_empty.webp b/app/src/main/res/drawable-xhdpi/icon_erban_grid_empty.webp new file mode 100644 index 000000000..ba5385473 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_erban_grid_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_error.webp b/app/src/main/res/drawable-xhdpi/icon_error.webp new file mode 100644 index 000000000..7ae48b130 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_error.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_exchange_gold.webp b/app/src/main/res/drawable-xhdpi/icon_exchange_gold.webp new file mode 100644 index 000000000..a6225b54d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_exchange_gold.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_exchange_jew.webp b/app/src/main/res/drawable-xhdpi/icon_exchange_jew.webp new file mode 100644 index 000000000..7f39a2605 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_exchange_jew.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_exchange_tip.webp b/app/src/main/res/drawable-xhdpi/icon_exchange_tip.webp new file mode 100644 index 000000000..1d78e35a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_exchange_tip.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_face_btn.webp b/app/src/main/res/drawable-xhdpi/icon_face_btn.webp new file mode 100644 index 000000000..12803864d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_face_btn.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_family_game_action.webp b/app/src/main/res/drawable-xhdpi/icon_family_game_action.webp new file mode 100644 index 000000000..2052cf34a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_family_game_action.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_family_office_position_boss.webp b/app/src/main/res/drawable-xhdpi/icon_family_office_position_boss.webp new file mode 100644 index 000000000..fa80b3dab Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_family_office_position_boss.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_family_office_position_manager.webp b/app/src/main/res/drawable-xhdpi/icon_family_office_position_manager.webp new file mode 100644 index 000000000..8ed8169e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_family_office_position_manager.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_find_mentor.webp b/app/src/main/res/drawable-xhdpi/icon_find_mentor.webp new file mode 100644 index 000000000..73c61023e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_find_mentor.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_finish_auction_close.webp b/app/src/main/res/drawable-xhdpi/icon_finish_auction_close.webp new file mode 100644 index 000000000..7a3db23e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_finish_auction_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_finish_first.webp b/app/src/main/res/drawable-xhdpi/icon_finish_first.webp new file mode 100644 index 000000000..ad0a16baf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_finish_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_first.webp b/app/src/main/res/drawable-xhdpi/icon_first.webp new file mode 100644 index 000000000..1f04dfc48 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_game_close.png b/app/src/main/res/drawable-xhdpi/icon_game_close.png new file mode 100644 index 000000000..c6ef1f7be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_game_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_get_red.webp b/app/src/main/res/drawable-xhdpi/icon_get_red.webp new file mode 100644 index 000000000..bc7efce3c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_get_red.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_action.webp b/app/src/main/res/drawable-xhdpi/icon_gift_action.webp new file mode 100644 index 000000000..285867c7a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_action.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_false.webp b/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_false.webp new file mode 100644 index 000000000..9f368f0ed Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_ture.webp b/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_ture.webp new file mode 100644 index 000000000..cc0954a22 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_all_mic_ture.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_effect.webp b/app/src/main/res/drawable-xhdpi/icon_gift_effect.webp new file mode 100644 index 000000000..48d6bc6a5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_effect.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_1.webp b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_1.webp new file mode 100644 index 000000000..5fb2d3d12 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_2.webp b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_2.webp new file mode 100644 index 000000000..5296ee2d7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_3.webp b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_3.webp new file mode 100644 index 000000000..5965d0729 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_effect_bg_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_exclusive.webp b/app/src/main/res/drawable-xhdpi/icon_gift_exclusive.webp new file mode 100644 index 000000000..f565309d5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_exclusive.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_limit_time.webp b/app/src/main/res/drawable-xhdpi/icon_gift_limit_time.webp new file mode 100644 index 000000000..880259c50 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_limit_time.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_new.webp b/app/src/main/res/drawable-xhdpi/icon_gift_new.webp new file mode 100644 index 000000000..685df8ef2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_new.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_recharge.png b/app/src/main/res/drawable-xhdpi/icon_gift_recharge.png new file mode 100644 index 000000000..4a5d8b2a4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_recharge.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_room_ownerer.png b/app/src/main/res/drawable-xhdpi/icon_gift_room_ownerer.png new file mode 100644 index 000000000..f2f8520c0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_room_ownerer.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gift_value.webp b/app/src/main/res/drawable-xhdpi/icon_gift_value.webp new file mode 100644 index 000000000..c81e65899 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gift_value.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_go_right_now.webp b/app/src/main/res/drawable-xhdpi/icon_go_right_now.webp new file mode 100644 index 000000000..d76c20d32 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_go_right_now.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gold.webp b/app/src/main/res/drawable-xhdpi/icon_gold.webp new file mode 100644 index 000000000..9a989ea23 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gold.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gold_num.webp b/app/src/main/res/drawable-xhdpi/icon_gold_num.webp new file mode 100644 index 000000000..e9dd42be3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gold_num.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_gold_pool_line.webp b/app/src/main/res/drawable-xhdpi/icon_gold_pool_line.webp new file mode 100644 index 000000000..d8875b4a6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_gold_pool_line.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_knowed.png b/app/src/main/res/drawable-xhdpi/icon_guide_knowed.png new file mode 100644 index 000000000..cd4e3fdfe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_knowed.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_bottom.png b/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_bottom.png new file mode 100644 index 000000000..f12d76113 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_bottom.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_center.webp b/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_center.webp new file mode 100644 index 000000000..11eb3ef4f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_logo_left_center.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_logo_right_bottom.webp b/app/src/main/res/drawable-xhdpi/icon_guide_logo_right_bottom.webp new file mode 100644 index 000000000..db5950b04 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_logo_right_bottom.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_1.webp b/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_1.webp new file mode 100644 index 000000000..2fadae378 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_2.webp b/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_2.webp new file mode 100644 index 000000000..031119e64 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_main_home_copywriting_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_0.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_0.webp new file mode 100644 index 000000000..8068735a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_0.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_1.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_1.webp new file mode 100644 index 000000000..07810e8b7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_2.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_2.webp new file mode 100644 index 000000000..cdc77521e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_bottom_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_0.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_0.webp new file mode 100644 index 000000000..7eee2b478 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_0.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_1.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_1.webp new file mode 100644 index 000000000..a2eccabcb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_2.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_2.webp new file mode 100644 index 000000000..3fc41dee7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_corner_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_0.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_0.webp new file mode 100644 index 000000000..fbc2432c0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_0.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_1.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_1.webp new file mode 100644 index 000000000..44a5a4c7e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_2.webp b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_2.webp new file mode 100644 index 000000000..12e8cb660 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_pager_top_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_guide_to_use.webp b/app/src/main/res/drawable-xhdpi/icon_guide_to_use.webp new file mode 100644 index 000000000..02cc4d972 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_guide_to_use.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hammer.webp b/app/src/main/res/drawable-xhdpi/icon_hammer.webp new file mode 100644 index 000000000..d626f2909 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hammer.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hammer_finish_auction.webp b/app/src/main/res/drawable-xhdpi/icon_hammer_finish_auction.webp new file mode 100644 index 000000000..ae03272c8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hammer_finish_auction.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hammer_tip.webp b/app/src/main/res/drawable-xhdpi/icon_hammer_tip.webp new file mode 100644 index 000000000..dcb507f63 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hammer_tip.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hammer_tip_finish.webp b/app/src/main/res/drawable-xhdpi/icon_hammer_tip_finish.webp new file mode 100644 index 000000000..7339af3ad Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hammer_tip_finish.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_headline.webp b/app/src/main/res/drawable-xhdpi/icon_headline.webp new file mode 100644 index 000000000..2b4cf7727 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_headline.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_page_more.webp b/app/src/main/res/drawable-xhdpi/icon_home_page_more.webp new file mode 100644 index 000000000..89e368ac0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_page_more.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_page_more_black.webp b/app/src/main/res/drawable-xhdpi/icon_home_page_more_black.webp new file mode 100644 index 000000000..c9c8632ad Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_page_more_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_party_open.webp b/app/src/main/res/drawable-xhdpi/icon_home_party_open.webp new file mode 100644 index 000000000..0468e3179 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_party_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_square_cover.png b/app/src/main/res/drawable-xhdpi/icon_home_square_cover.png new file mode 100644 index 000000000..2283f6856 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_square_cover.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hot_auction.webp b/app/src/main/res/drawable-xhdpi/icon_hot_auction.webp new file mode 100644 index 000000000..afc74843a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hot_auction.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hot_home_party.webp b/app/src/main/res/drawable-xhdpi/icon_hot_home_party.webp new file mode 100644 index 000000000..e1e98d7db Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hot_home_party.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_hot_light_chat.webp b/app/src/main/res/drawable-xhdpi/icon_hot_light_chat.webp new file mode 100644 index 000000000..b12599815 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_hot_light_chat.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_identify.webp b/app/src/main/res/drawable-xhdpi/icon_identify.webp new file mode 100644 index 000000000..39cfbbc3d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_identify.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_avatar_bg.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_avatar_bg.webp new file mode 100644 index 000000000..fcb252d97 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_avatar_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_clear_history.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_clear_history.webp new file mode 100644 index 000000000..b01099b3c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_clear_history.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_hot_songs.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_hot_songs.webp new file mode 100644 index 000000000..9f649fd32 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_hot_songs.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_lock_bg.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_lock_bg.webp new file mode 100644 index 000000000..1a846791c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_lock_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_mv_report_error.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_mv_report_error.webp new file mode 100644 index 000000000..efafb8afd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_mv_report_error.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_pause.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_pause.webp new file mode 100644 index 000000000..15bb4acb4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_play.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_play.webp new file mode 100644 index 000000000..118ca2e5c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_play.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_select_song_right.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_select_song_right.webp new file mode 100644 index 000000000..439ea687c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_select_song_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_singer.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_singer.webp new file mode 100644 index 000000000..a338b0553 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_singer.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_song_let_top.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_song_let_top.webp new file mode 100644 index 000000000..4fa53298d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_song_let_top.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_ktv_swich_song.webp b/app/src/main/res/drawable-xhdpi/icon_ktv_swich_song.webp new file mode 100644 index 000000000..a297357ae Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_ktv_swich_song.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_light_bg.webp b/app/src/main/res/drawable-xhdpi/icon_light_bg.webp new file mode 100644 index 000000000..adbc0eb27 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_light_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_light_rotate.webp b/app/src/main/res/drawable-xhdpi/icon_light_rotate.webp new file mode 100644 index 000000000..d1ce38b3a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_light_rotate.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_000.webp b/app/src/main/res/drawable-xhdpi/icon_living_000.webp new file mode 100644 index 000000000..57851bd58 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_000_black.png b/app/src/main/res/drawable-xhdpi/icon_living_000_black.png new file mode 100644 index 000000000..09bb94bd8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_000_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_001.png b/app/src/main/res/drawable-xhdpi/icon_living_001.png new file mode 100644 index 000000000..587069f66 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_001.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_001_black.png b/app/src/main/res/drawable-xhdpi/icon_living_001_black.png new file mode 100644 index 000000000..57ed97605 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_001_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_002.png b/app/src/main/res/drawable-xhdpi/icon_living_002.png new file mode 100644 index 000000000..7d908a01f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_002.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_002_black.png b/app/src/main/res/drawable-xhdpi/icon_living_002_black.png new file mode 100644 index 000000000..f99be2cb8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_002_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_003.png b/app/src/main/res/drawable-xhdpi/icon_living_003.png new file mode 100644 index 000000000..542a0d54b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_003.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_003_black.png b/app/src/main/res/drawable-xhdpi/icon_living_003_black.png new file mode 100644 index 000000000..e79855c96 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_003_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_004.png b/app/src/main/res/drawable-xhdpi/icon_living_004.png new file mode 100644 index 000000000..c22f0ec3a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_004.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_004_black.png b/app/src/main/res/drawable-xhdpi/icon_living_004_black.png new file mode 100644 index 000000000..a2704e451 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_004_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_005.png b/app/src/main/res/drawable-xhdpi/icon_living_005.png new file mode 100644 index 000000000..cc7e52e88 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_005.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_005_black.png b/app/src/main/res/drawable-xhdpi/icon_living_005_black.png new file mode 100644 index 000000000..271af6a72 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_005_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_006.png b/app/src/main/res/drawable-xhdpi/icon_living_006.png new file mode 100644 index 000000000..bdd8c796e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_006.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_006_black.png b/app/src/main/res/drawable-xhdpi/icon_living_006_black.png new file mode 100644 index 000000000..ea925f424 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_006_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_007.webp b/app/src/main/res/drawable-xhdpi/icon_living_007.webp new file mode 100644 index 000000000..a46ec93ad Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_007_black.png b/app/src/main/res/drawable-xhdpi/icon_living_007_black.png new file mode 100644 index 000000000..a6f1a931f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_007_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_008.png b/app/src/main/res/drawable-xhdpi/icon_living_008.png new file mode 100644 index 000000000..31a20004c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_008.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_008_black.png b/app/src/main/res/drawable-xhdpi/icon_living_008_black.png new file mode 100644 index 000000000..5198caff5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_008_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_009.png b/app/src/main/res/drawable-xhdpi/icon_living_009.png new file mode 100644 index 000000000..4b6a50e9f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_009.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_009_black.png b/app/src/main/res/drawable-xhdpi/icon_living_009_black.png new file mode 100644 index 000000000..395b900da Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_009_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_010.png b/app/src/main/res/drawable-xhdpi/icon_living_010.png new file mode 100644 index 000000000..8e7615d03 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_010.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_010_black.png b/app/src/main/res/drawable-xhdpi/icon_living_010_black.png new file mode 100644 index 000000000..7454e2095 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_010_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_011.png b/app/src/main/res/drawable-xhdpi/icon_living_011.png new file mode 100644 index 000000000..6a86bc216 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_011.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_living_011_black.png b/app/src/main/res/drawable-xhdpi/icon_living_011_black.png new file mode 100644 index 000000000..f0eca4c91 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_living_011_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_loading_rotate.webp b/app/src/main/res/drawable-xhdpi/icon_loading_rotate.webp new file mode 100644 index 000000000..ad6c885c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_loading_rotate.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_lock_bg.webp b/app/src/main/res/drawable-xhdpi/icon_lock_bg.webp new file mode 100644 index 000000000..e4c1430f7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_lock_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_look.webp b/app/src/main/res/drawable-xhdpi/icon_look.webp new file mode 100644 index 000000000..a95c22554 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_look.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_lottery_bg.webp b/app/src/main/res/drawable-xhdpi/icon_lottery_bg.webp new file mode 100644 index 000000000..4fd899109 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_lottery_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_lucky_money_action.webp b/app/src/main/res/drawable-xhdpi/icon_lucky_money_action.webp new file mode 100644 index 000000000..3cdc1c6bb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_lucky_money_action.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_lucky_money_luckiest.webp b/app/src/main/res/drawable-xhdpi/icon_lucky_money_luckiest.webp new file mode 100644 index 000000000..945a52b02 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_lucky_money_luckiest.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_lucky_money_receive_tips.webp b/app/src/main/res/drawable-xhdpi/icon_lucky_money_receive_tips.webp new file mode 100644 index 000000000..318f190c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_lucky_money_receive_tips.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_me_id.webp b/app/src/main/res/drawable-xhdpi/icon_me_id.webp new file mode 100644 index 000000000..155219511 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_me_id.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mic_charm_arrow.png b/app/src/main/res/drawable-xhdpi/icon_mic_charm_arrow.png new file mode 100644 index 000000000..2c3a3d0b1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mic_charm_arrow.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mic_female.webp b/app/src/main/res/drawable-xhdpi/icon_mic_female.webp new file mode 100644 index 000000000..caa22cc82 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mic_female.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_minus.webp b/app/src/main/res/drawable-xhdpi/icon_minus.webp new file mode 100644 index 000000000..d600eb5a8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_minus.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_msg_red_packet.webp b/app/src/main/res/drawable-xhdpi/icon_msg_red_packet.webp new file mode 100644 index 000000000..9dbec754b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_msg_red_packet.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_music_pause.webp b/app/src/main/res/drawable-xhdpi/icon_music_pause.webp new file mode 100644 index 000000000..d41df6458 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_music_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mv_error_false.webp b/app/src/main/res/drawable-xhdpi/icon_mv_error_false.webp new file mode 100644 index 000000000..8d6567b46 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mv_error_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_mv_error_true.webp b/app/src/main/res/drawable-xhdpi/icon_mv_error_true.webp new file mode 100644 index 000000000..17f3dd83a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_mv_error_true.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_nav_back.webp b/app/src/main/res/drawable-xhdpi/icon_nav_back.webp new file mode 100644 index 000000000..51b01808c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_nav_back.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_num_down.webp b/app/src/main/res/drawable-xhdpi/icon_num_down.webp new file mode 100644 index 000000000..153feb529 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_num_down.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open.webp b/app/src/main/res/drawable-xhdpi/icon_open.webp new file mode 100644 index 000000000..eaea79304 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open_gift_value.webp b/app/src/main/res/drawable-xhdpi/icon_open_gift_value.webp new file mode 100644 index 000000000..c12e59f12 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open_gift_value.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open_my_effect.webp b/app/src/main/res/drawable-xhdpi/icon_open_my_effect.webp new file mode 100644 index 000000000..ffbdf26ce Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open_my_effect.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open_noble.webp b/app/src/main/res/drawable-xhdpi/icon_open_noble.webp new file mode 100644 index 000000000..92ea1cccd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open_noble.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open_public_screen.webp b/app/src/main/res/drawable-xhdpi/icon_open_public_screen.webp new file mode 100644 index 000000000..3ed4dae86 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open_public_screen.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_open_redbag.webp b/app/src/main/res/drawable-xhdpi/icon_open_redbag.webp new file mode 100644 index 000000000..8752a1a37 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_open_redbag.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_party_room_guide.png b/app/src/main/res/drawable-xhdpi/icon_party_room_guide.png new file mode 100644 index 000000000..65131d6e7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_party_room_guide.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_people.webp b/app/src/main/res/drawable-xhdpi/icon_people.webp new file mode 100644 index 000000000..d36927737 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_people.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_photo_delete.webp b/app/src/main/res/drawable-xhdpi/icon_photo_delete.webp new file mode 100644 index 000000000..58bd32260 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_photo_delete.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_play.webp b/app/src/main/res/drawable-xhdpi/icon_play.webp new file mode 100644 index 000000000..a43ace143 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_play.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_play_stop.webp b/app/src/main/res/drawable-xhdpi/icon_play_stop.webp new file mode 100644 index 000000000..56493ccc4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_play_stop.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_play_together.webp b/app/src/main/res/drawable-xhdpi/icon_play_together.webp new file mode 100644 index 000000000..545ae1196 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_play_together.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_plus_big.webp b/app/src/main/res/drawable-xhdpi/icon_plus_big.webp new file mode 100644 index 000000000..812c08f6b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_plus_big.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_plus_head.webp b/app/src/main/res/drawable-xhdpi/icon_plus_head.webp new file mode 100644 index 000000000..e6b42b46b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_plus_head.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_plus_up.webp b/app/src/main/res/drawable-xhdpi/icon_plus_up.webp new file mode 100644 index 000000000..5aca58486 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_plus_up.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_pm_close.png b/app/src/main/res/drawable-xhdpi/icon_pm_close.png new file mode 100644 index 000000000..16d0d2a53 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_pm_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_pm_top.webp b/app/src/main/res/drawable-xhdpi/icon_pm_top.webp new file mode 100644 index 000000000..50b72960e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_pm_top.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_qq.webp b/app/src/main/res/drawable-xhdpi/icon_qq.webp new file mode 100644 index 000000000..3674d7eb1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_qq.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_qq_zone.webp b/app/src/main/res/drawable-xhdpi/icon_qq_zone.webp new file mode 100644 index 000000000..589d8e42a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_qq_zone.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_false.webp b/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_false.webp new file mode 100644 index 000000000..d874e570e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_true.webp b/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_true.webp new file mode 100644 index 000000000..166f78f6b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radio_not_tips_true.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radish.webp b/app/src/main/res/drawable-xhdpi/icon_radish.webp new file mode 100644 index 000000000..82929ee0b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radish.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radish_task.webp b/app/src/main/res/drawable-xhdpi/icon_radish_task.webp new file mode 100644 index 000000000..3b16ab9be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radish_task.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radish_transparent.png b/app/src/main/res/drawable-xhdpi/icon_radish_transparent.png new file mode 100644 index 000000000..c3b9dbf04 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radish_transparent.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_radish_transparent_selected.webp b/app/src/main/res/drawable-xhdpi/icon_radish_transparent_selected.webp new file mode 100644 index 000000000..169499ea2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_radish_transparent_selected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_rank_half.webp b/app/src/main/res/drawable-xhdpi/icon_rank_half.webp new file mode 100644 index 000000000..1247df99a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_rank_half.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_record.webp b/app/src/main/res/drawable-xhdpi/icon_record.webp new file mode 100644 index 000000000..3125604f1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_record.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_record_save.webp b/app/src/main/res/drawable-xhdpi/icon_record_save.webp new file mode 100644 index 000000000..6942f9d2f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_record_save.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_recording.webp b/app/src/main/res/drawable-xhdpi/icon_recording.webp new file mode 100644 index 000000000..711fcbf3a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_recording.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_red_method.webp b/app/src/main/res/drawable-xhdpi/icon_red_method.webp new file mode 100644 index 000000000..80cdbe2d0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_red_method.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_red_rank.png b/app/src/main/res/drawable-xhdpi/icon_red_rank.png new file mode 100644 index 000000000..044c459f9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_red_rank.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_red_rule.webp b/app/src/main/res/drawable-xhdpi/icon_red_rule.webp new file mode 100644 index 000000000..8d2e0ca01 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_red_rule.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_remote_mute_close.webp b/app/src/main/res/drawable-xhdpi/icon_remote_mute_close.webp new file mode 100644 index 000000000..a19afeec0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_remote_mute_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_remote_mute_open.webp b/app/src/main/res/drawable-xhdpi/icon_remote_mute_open.webp new file mode 100644 index 000000000..219dc7fdf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_remote_mute_open.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_retry_record.webp b/app/src/main/res/drawable-xhdpi/icon_retry_record.webp new file mode 100644 index 000000000..ab2ff851a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_retry_record.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_bg.webp b/app/src/main/res/drawable-xhdpi/icon_reward_bg.webp new file mode 100644 index 000000000..629226548 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_content.webp b/app/src/main/res/drawable-xhdpi/icon_reward_content.webp new file mode 100644 index 000000000..9e5397710 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_content.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_got.webp b/app/src/main/res/drawable-xhdpi/icon_reward_got.webp new file mode 100644 index 000000000..2782cbeb6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_got.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_notice_left.webp b/app/src/main/res/drawable-xhdpi/icon_reward_notice_left.webp new file mode 100644 index 000000000..f79a16fc5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_notice_left.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_notice_right.webp b/app/src/main/res/drawable-xhdpi/icon_reward_notice_right.webp new file mode 100644 index 000000000..e71e8acbc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_notice_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_notice_select.webp b/app/src/main/res/drawable-xhdpi/icon_reward_notice_select.webp new file mode 100644 index 000000000..17f0858b6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_notice_select.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_package.webp b/app/src/main/res/drawable-xhdpi/icon_reward_package.webp new file mode 100644 index 000000000..a5c156bb1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_package.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_reward_un_sign_in.webp b/app/src/main/res/drawable-xhdpi/icon_reward_un_sign_in.webp new file mode 100644 index 000000000..01db24340 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_reward_un_sign_in.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_right_black.webp b/app/src/main/res/drawable-xhdpi/icon_right_black.webp new file mode 100644 index 000000000..023d7f6b7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_right_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_right_green.png b/app/src/main/res/drawable-xhdpi/icon_right_green.png new file mode 100644 index 000000000..a78059210 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_right_green.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_admin.webp b/app/src/main/res/drawable-xhdpi/icon_room_admin.webp new file mode 100644 index 000000000..77aa3e700 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_admin.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_close_mic.webp b/app/src/main/res/drawable-xhdpi/icon_room_close_mic.webp new file mode 100644 index 000000000..f16937945 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_close_mic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_desc_edit.png b/app/src/main/res/drawable-xhdpi/icon_room_desc_edit.png new file mode 100644 index 000000000..33a6814d1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_desc_edit.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_dragon_buton.webp b/app/src/main/res/drawable-xhdpi/icon_room_dragon_buton.webp new file mode 100644 index 000000000..81ca9aef2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_dragon_buton.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_game.png b/app/src/main/res/drawable-xhdpi/icon_room_game.png new file mode 100644 index 000000000..623be2432 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_game.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_game_close.png b/app/src/main/res/drawable-xhdpi/icon_room_game_close.png new file mode 100644 index 000000000..4e5861886 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_game_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_good_number.webp b/app/src/main/res/drawable-xhdpi/icon_room_good_number.webp new file mode 100644 index 000000000..723f5a66f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_good_number.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_ktv.png b/app/src/main/res/drawable-xhdpi/icon_room_ktv.png new file mode 100644 index 000000000..7d9e986e8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_ktv.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_limit.webp b/app/src/main/res/drawable-xhdpi/icon_room_limit.webp new file mode 100644 index 000000000..c78196a19 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_limit.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_lock.webp b/app/src/main/res/drawable-xhdpi/icon_room_lock.webp new file mode 100644 index 000000000..9ed97f661 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_lock.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_lock_micro.webp b/app/src/main/res/drawable-xhdpi/icon_room_lock_micro.webp new file mode 100644 index 000000000..5a8034b10 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_lock_micro.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_lock_micro_cp.webp b/app/src/main/res/drawable-xhdpi/icon_room_lock_micro_cp.webp new file mode 100644 index 000000000..6a85763d6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_lock_micro_cp.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_mic_queue.webp b/app/src/main/res/drawable-xhdpi/icon_room_mic_queue.webp new file mode 100644 index 000000000..f9fa496d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_mic_queue.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_mic_queue_not_empty.webp b/app/src/main/res/drawable-xhdpi/icon_room_mic_queue_not_empty.webp new file mode 100644 index 000000000..a06811bac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_mic_queue_not_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_min.webp b/app/src/main/res/drawable-xhdpi/icon_room_min.webp new file mode 100644 index 000000000..5b6d1dc91 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_min.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_module_hall.webp b/app/src/main/res/drawable-xhdpi/icon_room_module_hall.webp new file mode 100644 index 000000000..581666101 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_module_hall.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_more.webp b/app/src/main/res/drawable-xhdpi/icon_room_more.webp new file mode 100644 index 000000000..6c306377c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_more.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_mute_micro.webp b/app/src/main/res/drawable-xhdpi/icon_room_mute_micro.webp new file mode 100644 index 000000000..9b8f04d02 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_mute_micro.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_open_mic.webp b/app/src/main/res/drawable-xhdpi/icon_room_open_mic.webp new file mode 100644 index 000000000..4c7b0df5e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_open_mic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_send_arrow.png b/app/src/main/res/drawable-xhdpi/icon_room_send_arrow.png new file mode 100644 index 000000000..c2cb5661d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_send_arrow.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_send_gift.webp b/app/src/main/res/drawable-xhdpi/icon_room_send_gift.webp new file mode 100644 index 000000000..9a0c67d40 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_send_gift.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_send_msg.webp b/app/src/main/res/drawable-xhdpi/icon_room_send_msg.webp new file mode 100644 index 000000000..85ebe0319 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_send_msg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_set_arrow.png b/app/src/main/res/drawable-xhdpi/icon_room_set_arrow.png new file mode 100644 index 000000000..e3fa0f74e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_set_arrow.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_set_lock_false.webp b/app/src/main/res/drawable-xhdpi/icon_room_set_lock_false.webp new file mode 100644 index 000000000..a9b924fd6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_set_lock_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_set_lock_true.webp b/app/src/main/res/drawable-xhdpi/icon_room_set_lock_true.webp new file mode 100644 index 000000000..972039da1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_set_lock_true.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_setting.webp b/app/src/main/res/drawable-xhdpi/icon_room_setting.webp new file mode 100644 index 000000000..003211a1b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_setting.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_share.webp b/app/src/main/res/drawable-xhdpi/icon_room_share.webp new file mode 100644 index 000000000..e06825e1d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_share.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_super_admin.webp b/app/src/main/res/drawable-xhdpi/icon_room_super_admin.webp new file mode 100644 index 000000000..bfcc9d881 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_super_admin.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_up_micro.webp b/app/src/main/res/drawable-xhdpi/icon_room_up_micro.webp new file mode 100644 index 000000000..0c4966a13 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_up_micro.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_up_micro_cp.webp b/app/src/main/res/drawable-xhdpi/icon_room_up_micro_cp.webp new file mode 100644 index 000000000..1b8d95de6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_up_micro_cp.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_up_micro_king.webp b/app/src/main/res/drawable-xhdpi/icon_room_up_micro_king.webp new file mode 100644 index 000000000..5e26fa135 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_up_micro_king.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_second.webp b/app/src/main/res/drawable-xhdpi/icon_second.webp new file mode 100644 index 000000000..7653dfabb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_second.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_select_team_member_selected.webp b/app/src/main/res/drawable-xhdpi/icon_select_team_member_selected.webp new file mode 100644 index 000000000..4bd81296d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_select_team_member_selected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_select_team_member_unselected.webp b/app/src/main/res/drawable-xhdpi/icon_select_team_member_unselected.webp new file mode 100644 index 000000000..b2abf8745 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_select_team_member_unselected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_send_gift_ture.webp b/app/src/main/res/drawable-xhdpi/icon_send_gift_ture.webp new file mode 100644 index 000000000..411b7d020 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_send_gift_ture.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_send_magic.webp b/app/src/main/res/drawable-xhdpi/icon_send_magic.webp new file mode 100644 index 000000000..e82e53079 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_send_magic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_send_magic_new.webp b/app/src/main/res/drawable-xhdpi/icon_send_magic_new.webp new file mode 100644 index 000000000..6ea1dc03a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_send_magic_new.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_share_money.webp b/app/src/main/res/drawable-xhdpi/icon_share_money.webp new file mode 100644 index 000000000..29c4898df Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_share_money.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_show_bind_phone.webp b/app/src/main/res/drawable-xhdpi/icon_show_bind_phone.webp new file mode 100644 index 000000000..505f6dbb9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_show_bind_phone.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_shut_up.png b/app/src/main/res/drawable-xhdpi/icon_shut_up.png new file mode 100644 index 000000000..a65baa517 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_shut_up.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_draw_gold.webp b/app/src/main/res/drawable-xhdpi/icon_sign_draw_gold.webp new file mode 100644 index 000000000..bbb1d6443 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_draw_gold.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_in_ed_status.png b/app/src/main/res/drawable-xhdpi/icon_sign_in_ed_status.png new file mode 100644 index 000000000..f8ab06861 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_in_ed_status.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_in_horn.png b/app/src/main/res/drawable-xhdpi/icon_sign_in_horn.png new file mode 100644 index 000000000..77bd5f40a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_in_horn.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_in_logo.webp b/app/src/main/res/drawable-xhdpi/icon_sign_in_logo.webp new file mode 100644 index 000000000..81a7e0061 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_in_logo.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_in_un_status.webp b/app/src/main/res/drawable-xhdpi/icon_sign_in_un_status.webp new file mode 100644 index 000000000..e88e67d97 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_in_un_status.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_sign_rule_close.webp b/app/src/main/res/drawable-xhdpi/icon_sign_rule_close.webp new file mode 100644 index 000000000..cd9283382 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_sign_rule_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_state_agreed.webp b/app/src/main/res/drawable-xhdpi/icon_state_agreed.webp new file mode 100644 index 000000000..810917d3e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_state_agreed.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_state_rejected.webp b/app/src/main/res/drawable-xhdpi/icon_state_rejected.webp new file mode 100644 index 000000000..c2ad51356 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_state_rejected.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_supplement_sign_success.webp b/app/src/main/res/drawable-xhdpi/icon_supplement_sign_success.webp new file mode 100644 index 000000000..cce5b1c4a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_supplement_sign_success.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_tab_mask.webp b/app/src/main/res/drawable-xhdpi/icon_tab_mask.webp new file mode 100644 index 000000000..a9fa290f2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_tab_mask.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_task_finished_not_receive.webp b/app/src/main/res/drawable-xhdpi/icon_task_finished_not_receive.webp new file mode 100644 index 000000000..c98f0a5b0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_task_finished_not_receive.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_task_has_received.webp b/app/src/main/res/drawable-xhdpi/icon_task_has_received.webp new file mode 100644 index 000000000..e3eb5fd3c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_task_has_received.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_task_tips.webp b/app/src/main/res/drawable-xhdpi/icon_task_tips.webp new file mode 100644 index 000000000..c9442e65d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_task_tips.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_task_un_finish.webp b/app/src/main/res/drawable-xhdpi/icon_task_un_finish.webp new file mode 100644 index 000000000..c20553aad Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_task_un_finish.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_team_member_management.webp b/app/src/main/res/drawable-xhdpi/icon_team_member_management.webp new file mode 100644 index 000000000..c35159f55 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_team_member_management.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_test.webp b/app/src/main/res/drawable-xhdpi/icon_test.webp new file mode 100644 index 000000000..e530ba090 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_test.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_third.webp b/app/src/main/res/drawable-xhdpi/icon_third.webp new file mode 100644 index 000000000..75a3d293b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_third.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_title_share.webp b/app/src/main/res/drawable-xhdpi/icon_title_share.webp new file mode 100644 index 000000000..5004c14a4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_title_share.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_to_sign_in.png b/app/src/main/res/drawable-xhdpi/icon_to_sign_in.png new file mode 100644 index 000000000..65613c512 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_to_sign_in.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_total_auction_list.webp b/app/src/main/res/drawable-xhdpi/icon_total_auction_list.webp new file mode 100644 index 000000000..b2520c9c4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_total_auction_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_trophy_first.webp b/app/src/main/res/drawable-xhdpi/icon_trophy_first.webp new file mode 100644 index 000000000..3f1005c6b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_trophy_first.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_trumpet.webp b/app/src/main/res/drawable-xhdpi/icon_trumpet.webp new file mode 100644 index 000000000..e095ad84c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_trumpet.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_try_listen.webp b/app/src/main/res/drawable-xhdpi/icon_try_listen.webp new file mode 100644 index 000000000..597bd1ddd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_try_listen.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_try_listen_pause.webp b/app/src/main/res/drawable-xhdpi/icon_try_listen_pause.webp new file mode 100644 index 000000000..31b674f92 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_try_listen_pause.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_un_withdraw.webp b/app/src/main/res/drawable-xhdpi/icon_un_withdraw.webp new file mode 100644 index 000000000..087dd941e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_un_withdraw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_up_mic_false.webp b/app/src/main/res/drawable-xhdpi/icon_up_mic_false.webp new file mode 100644 index 000000000..4868c4eb1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_up_mic_false.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_up_mic_ture.webp b/app/src/main/res/drawable-xhdpi/icon_up_mic_ture.webp new file mode 100644 index 000000000..6cb277cc4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_up_mic_ture.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_back.webp b/app/src/main/res/drawable-xhdpi/icon_user_back.webp new file mode 100644 index 000000000..dfd726df2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_back.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_back_black.webp b/app/src/main/res/drawable-xhdpi/icon_user_back_black.webp new file mode 100644 index 000000000..0ac0dc4a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_back_black.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_info_dialog_close.webp b/app/src/main/res/drawable-xhdpi/icon_user_info_dialog_close.webp new file mode 100644 index 000000000..153feb529 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_info_dialog_close.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_info_edit.webp b/app/src/main/res/drawable-xhdpi/icon_user_info_edit.webp new file mode 100644 index 000000000..2dad69623 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_info_edit.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_list_room_ownner.webp b/app/src/main/res/drawable-xhdpi/icon_user_list_room_ownner.webp new file mode 100644 index 000000000..6aa92c8ef Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_list_room_ownner.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_list_up_mic.webp b/app/src/main/res/drawable-xhdpi/icon_user_list_up_mic.webp new file mode 100644 index 000000000..3d3b07923 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_list_up_mic.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_room_new.png b/app/src/main/res/drawable-xhdpi/icon_user_room_new.png new file mode 100644 index 000000000..28da8abb1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_room_new.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_user_where_new.webp b/app/src/main/res/drawable-xhdpi/icon_user_where_new.webp new file mode 100644 index 000000000..59a2fe4f4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_user_where_new.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_vioce_like.webp b/app/src/main/res/drawable-xhdpi/icon_vioce_like.webp new file mode 100644 index 000000000..b971d5ca9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_vioce_like.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_dont_like.webp b/app/src/main/res/drawable-xhdpi/icon_voice_dont_like.webp new file mode 100644 index 000000000..103bf901a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_dont_like.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_like_value.webp b/app/src/main/res/drawable-xhdpi/icon_voice_like_value.webp new file mode 100644 index 000000000..700246fe5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_like_value.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_net_error.webp b/app/src/main/res/drawable-xhdpi/icon_voice_net_error.webp new file mode 100644 index 000000000..99fe59ae8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_net_error.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_no_bottle.webp b/app/src/main/res/drawable-xhdpi/icon_voice_no_bottle.webp new file mode 100644 index 000000000..af29b910a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_no_bottle.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_to_start.png b/app/src/main/res/drawable-xhdpi/icon_voice_to_start.png new file mode 100644 index 000000000..6b3a0d5d0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_to_start.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_voice_to_stop.png b/app/src/main/res/drawable-xhdpi/icon_voice_to_stop.png new file mode 100644 index 000000000..af4c3ea4b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_voice_to_stop.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_water_wave.webp b/app/src/main/res/drawable-xhdpi/icon_water_wave.webp new file mode 100644 index 000000000..bf62a4532 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_water_wave.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_week_auction_list.webp b/app/src/main/res/drawable-xhdpi/icon_week_auction_list.webp new file mode 100644 index 000000000..14cc2b6c7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_week_auction_list.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_weixin.webp b/app/src/main/res/drawable-xhdpi/icon_weixin.webp new file mode 100644 index 000000000..26bd0d265 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_weixin.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_weixinpy.webp b/app/src/main/res/drawable-xhdpi/icon_weixinpy.webp new file mode 100644 index 000000000..4d31387f2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_weixinpy.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_withdraw.webp b/app/src/main/res/drawable-xhdpi/icon_withdraw.webp new file mode 100644 index 000000000..6088f0120 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_withdraw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_withdraw_bank_card.png b/app/src/main/res/drawable-xhdpi/icon_withdraw_bank_card.png new file mode 100644 index 000000000..0aec72de2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_withdraw_bank_card.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_withdraw_type.png b/app/src/main/res/drawable-xhdpi/icon_withdraw_type.png new file mode 100644 index 000000000..18ffedcd9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_withdraw_type.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_zhifubao.webp b/app/src/main/res/drawable-xhdpi/icon_zhifubao.webp new file mode 100644 index 000000000..322f63197 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_zhifubao.webp differ diff --git a/app/src/main/res/drawable-xhdpi/icon_zhifubao_grey.webp b/app/src/main/res/drawable-xhdpi/icon_zhifubao_grey.webp new file mode 100644 index 000000000..d4bf6ca2b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_zhifubao_grey.webp differ diff --git a/app/src/main/res/drawable-xhdpi/img_bg_all_service_gift.png b/app/src/main/res/drawable-xhdpi/img_bg_all_service_gift.png new file mode 100644 index 000000000..351cd6ac3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_bg_all_service_gift.png differ diff --git a/app/src/main/res/drawable-xhdpi/img_bg_circusee.webp b/app/src/main/res/drawable-xhdpi/img_bg_circusee.webp new file mode 100644 index 000000000..3bc6bff5c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/img_bg_circusee.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_music_name_bg.9.png b/app/src/main/res/drawable-xhdpi/ktv_music_name_bg.9.png new file mode 100644 index 000000000..5a375a9fe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_music_name_bg.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_pk_singing_mark.webp b/app/src/main/res/drawable-xhdpi/ktv_pk_singing_mark.webp new file mode 100644 index 000000000..8a493712e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_pk_singing_mark.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_room_bg_1.webp b/app/src/main/res/drawable-xhdpi/ktv_room_bg_1.webp new file mode 100644 index 000000000..a4e4b319d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_room_bg_1.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_room_bg_2.webp b/app/src/main/res/drawable-xhdpi/ktv_room_bg_2.webp new file mode 100644 index 000000000..911685c76 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_room_bg_2.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_room_bg_3.webp b/app/src/main/res/drawable-xhdpi/ktv_room_bg_3.webp new file mode 100644 index 000000000..63d0e170e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_room_bg_3.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_room_bg_4.webp b/app/src/main/res/drawable-xhdpi/ktv_room_bg_4.webp new file mode 100644 index 000000000..370c48dde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_room_bg_4.webp differ diff --git a/app/src/main/res/drawable-xhdpi/ktv_video_bg.webp b/app/src/main/res/drawable-xhdpi/ktv_video_bg.webp new file mode 100644 index 000000000..38e7bb923 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ktv_video_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/le_bubble_arrow_light.webp b/app/src/main/res/drawable-xhdpi/le_bubble_arrow_light.webp new file mode 100644 index 000000000..ac6d918ca Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/le_bubble_arrow_light.webp differ diff --git a/app/src/main/res/drawable-xhdpi/le_bubble_cancel.webp b/app/src/main/res/drawable-xhdpi/le_bubble_cancel.webp new file mode 100644 index 000000000..f8e2035af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/le_bubble_cancel.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading00.webp b/app/src/main/res/drawable-xhdpi/loading00.webp new file mode 100644 index 000000000..efacea2bb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading00.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading01.webp b/app/src/main/res/drawable-xhdpi/loading01.webp new file mode 100644 index 000000000..8e8d91994 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading01.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading02.webp b/app/src/main/res/drawable-xhdpi/loading02.webp new file mode 100644 index 000000000..e809b8415 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading02.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading03.webp b/app/src/main/res/drawable-xhdpi/loading03.webp new file mode 100644 index 000000000..d610f7893 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading03.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading04.webp b/app/src/main/res/drawable-xhdpi/loading04.webp new file mode 100644 index 000000000..b1ac1671e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading04.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading05.webp b/app/src/main/res/drawable-xhdpi/loading05.webp new file mode 100644 index 000000000..adf361f4f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading05.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading06.webp b/app/src/main/res/drawable-xhdpi/loading06.webp new file mode 100644 index 000000000..f40ecee88 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading06.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading07.webp b/app/src/main/res/drawable-xhdpi/loading07.webp new file mode 100644 index 000000000..c2cb317b1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading07.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading08.webp b/app/src/main/res/drawable-xhdpi/loading08.webp new file mode 100644 index 000000000..54ba5b423 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading08.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading09.webp b/app/src/main/res/drawable-xhdpi/loading09.webp new file mode 100644 index 000000000..fbe4d40c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading09.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading10.webp b/app/src/main/res/drawable-xhdpi/loading10.webp new file mode 100644 index 000000000..38e4a4bcd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading10.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading11.webp b/app/src/main/res/drawable-xhdpi/loading11.webp new file mode 100644 index 000000000..fa0e4b84f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading11.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading12.webp b/app/src/main/res/drawable-xhdpi/loading12.webp new file mode 100644 index 000000000..705adaa7d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading12.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading13.webp b/app/src/main/res/drawable-xhdpi/loading13.webp new file mode 100644 index 000000000..31ddb1628 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading13.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading_icon.webp b/app/src/main/res/drawable-xhdpi/loading_icon.webp new file mode 100644 index 000000000..db815f13d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading_icon.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading_progress.webp b/app/src/main/res/drawable-xhdpi/loading_progress.webp new file mode 100644 index 000000000..a11558d8b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading_progress.webp differ diff --git a/app/src/main/res/drawable-xhdpi/loading_spinner.webp b/app/src/main/res/drawable-xhdpi/loading_spinner.webp new file mode 100644 index 000000000..8bda156ec Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/loading_spinner.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_detail_top_background.webp b/app/src/main/res/drawable-xhdpi/lucky_money_detail_top_background.webp new file mode 100644 index 000000000..31d203d26 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_detail_top_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_avatar_bg.webp b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_avatar_bg.webp new file mode 100644 index 000000000..13a850186 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_avatar_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_background.webp b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_background.webp new file mode 100644 index 000000000..7320f7232 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_draw_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_dialog_gone_background.webp b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_gone_background.webp new file mode 100644 index 000000000..39a7f5a3b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_gone_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_dialog_ready_to_draw.webp b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_ready_to_draw.webp new file mode 100644 index 000000000..a02bddb8b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_dialog_ready_to_draw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_msg_draw.webp b/app/src/main/res/drawable-xhdpi/lucky_money_msg_draw.webp new file mode 100644 index 000000000..aae616da3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_msg_draw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/lucky_money_msg_undraw.webp b/app/src/main/res/drawable-xhdpi/lucky_money_msg_undraw.webp new file mode 100644 index 000000000..74cb43fe2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/lucky_money_msg_undraw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/match_ing.png b/app/src/main/res/drawable-xhdpi/match_ing.png new file mode 100644 index 000000000..140fa15af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/match_ing.png differ diff --git a/app/src/main/res/drawable-xhdpi/match_start.png b/app/src/main/res/drawable-xhdpi/match_start.png new file mode 100644 index 000000000..d1ba5bcfd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/match_start.png differ diff --git a/app/src/main/res/drawable-xhdpi/match_success.png b/app/src/main/res/drawable-xhdpi/match_success.png new file mode 100644 index 000000000..19c6750c7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/match_success.png differ diff --git a/app/src/main/res/drawable-xhdpi/monster_default_image.webp b/app/src/main/res/drawable-xhdpi/monster_default_image.webp new file mode 100644 index 000000000..09cec52f6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_default_image.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_escape_background.webp b/app/src/main/res/drawable-xhdpi/monster_escape_background.webp new file mode 100644 index 000000000..6577f8225 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_escape_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_escape_confirm.webp b/app/src/main/res/drawable-xhdpi/monster_escape_confirm.webp new file mode 100644 index 000000000..9d1b93dfa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_escape_confirm.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hp_background.webp b/app/src/main/res/drawable-xhdpi/monster_hp_background.webp new file mode 100644 index 000000000..b9bbf977f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hp_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_check_damage.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_check_damage.webp new file mode 100644 index 000000000..e4e5d98e3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_check_damage.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_countdown.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_countdown.webp new file mode 100644 index 000000000..9499f3768 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_countdown.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_exit.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_exit.webp new file mode 100644 index 000000000..53114bbde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_exit.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_introduction.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_introduction.webp new file mode 100644 index 000000000..d1adf78d0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_introduction.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_introduction_background.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_introduction_background.webp new file mode 100644 index 000000000..228d2dfdc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_introduction_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_lucky_man_background.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_lucky_man_background.webp new file mode 100644 index 000000000..7e48e2953 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_lucky_man_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_result_background.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_result_background.webp new file mode 100644 index 000000000..2669a0ca8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_result_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_reward_background.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_reward_background.webp new file mode 100644 index 000000000..008b7bbaa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_reward_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_hunting_reward_decoration.webp b/app/src/main/res/drawable-xhdpi/monster_hunting_reward_decoration.webp new file mode 100644 index 000000000..1c6d82c31 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_hunting_reward_decoration.webp differ diff --git a/app/src/main/res/drawable-xhdpi/monster_info_panel_background.webp b/app/src/main/res/drawable-xhdpi/monster_info_panel_background.webp new file mode 100644 index 000000000..66a0cc3c8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/monster_info_panel_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00000.webp b/app/src/main/res/drawable-xhdpi/my_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00001.webp b/app/src/main/res/drawable-xhdpi/my_00001.webp new file mode 100644 index 000000000..2bdcfb6be Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00002.webp b/app/src/main/res/drawable-xhdpi/my_00002.webp new file mode 100644 index 000000000..33ef76129 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00003.webp b/app/src/main/res/drawable-xhdpi/my_00003.webp new file mode 100644 index 000000000..37806af4e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00004.webp b/app/src/main/res/drawable-xhdpi/my_00004.webp new file mode 100644 index 000000000..a35e150f0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00005.webp b/app/src/main/res/drawable-xhdpi/my_00005.webp new file mode 100644 index 000000000..1f9dc9a5b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00006.webp b/app/src/main/res/drawable-xhdpi/my_00006.webp new file mode 100644 index 000000000..6c79a1e5d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00007.webp b/app/src/main/res/drawable-xhdpi/my_00007.webp new file mode 100644 index 000000000..a3e5c086c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00008.webp b/app/src/main/res/drawable-xhdpi/my_00008.webp new file mode 100644 index 000000000..2c3fdb563 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00009.webp b/app/src/main/res/drawable-xhdpi/my_00009.webp new file mode 100644 index 000000000..5f5f3b74c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00010.webp b/app/src/main/res/drawable-xhdpi/my_00010.webp new file mode 100644 index 000000000..8e25d2cfb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00011.webp b/app/src/main/res/drawable-xhdpi/my_00011.webp new file mode 100644 index 000000000..de96ec319 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00012.webp b/app/src/main/res/drawable-xhdpi/my_00012.webp new file mode 100644 index 000000000..22c1c14a0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00013.webp b/app/src/main/res/drawable-xhdpi/my_00013.webp new file mode 100644 index 000000000..b56abee88 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00014.webp b/app/src/main/res/drawable-xhdpi/my_00014.webp new file mode 100644 index 000000000..59754c509 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00015.webp b/app/src/main/res/drawable-xhdpi/my_00015.webp new file mode 100644 index 000000000..f894c5655 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00016.webp b/app/src/main/res/drawable-xhdpi/my_00016.webp new file mode 100644 index 000000000..2e463fc75 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00017.webp b/app/src/main/res/drawable-xhdpi/my_00017.webp new file mode 100644 index 000000000..a30c252e5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00018.webp b/app/src/main/res/drawable-xhdpi/my_00018.webp new file mode 100644 index 000000000..956730732 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00019.webp b/app/src/main/res/drawable-xhdpi/my_00019.webp new file mode 100644 index 000000000..206c88724 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00020.webp b/app/src/main/res/drawable-xhdpi/my_00020.webp new file mode 100644 index 000000000..3012c0750 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00021.webp b/app/src/main/res/drawable-xhdpi/my_00021.webp new file mode 100644 index 000000000..bec408e5e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00022.webp b/app/src/main/res/drawable-xhdpi/my_00022.webp new file mode 100644 index 000000000..ff9a2fffe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00023.webp b/app/src/main/res/drawable-xhdpi/my_00023.webp new file mode 100644 index 000000000..e5a7ec57e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00024.webp b/app/src/main/res/drawable-xhdpi/my_00024.webp new file mode 100644 index 000000000..4153e53b1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00025.webp b/app/src/main/res/drawable-xhdpi/my_00025.webp new file mode 100644 index 000000000..6be3d65ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00026.webp b/app/src/main/res/drawable-xhdpi/my_00026.webp new file mode 100644 index 000000000..c7b6aa7b5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00027.webp b/app/src/main/res/drawable-xhdpi/my_00027.webp new file mode 100644 index 000000000..41a7f7328 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00028.webp b/app/src/main/res/drawable-xhdpi/my_00028.webp new file mode 100644 index 000000000..d0a315a6c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00029.webp b/app/src/main/res/drawable-xhdpi/my_00029.webp new file mode 100644 index 000000000..dd2f6cf8c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00030.webp b/app/src/main/res/drawable-xhdpi/my_00030.webp new file mode 100644 index 000000000..7a21fc4ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00031.webp b/app/src/main/res/drawable-xhdpi/my_00031.webp new file mode 100644 index 000000000..6c965cf6d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00032.webp b/app/src/main/res/drawable-xhdpi/my_00032.webp new file mode 100644 index 000000000..25eb2092c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00033.webp b/app/src/main/res/drawable-xhdpi/my_00033.webp new file mode 100644 index 000000000..c78be333e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00034.webp b/app/src/main/res/drawable-xhdpi/my_00034.webp new file mode 100644 index 000000000..935df41b0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00035.webp b/app/src/main/res/drawable-xhdpi/my_00035.webp new file mode 100644 index 000000000..9fd8abee0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00036.webp b/app/src/main/res/drawable-xhdpi/my_00036.webp new file mode 100644 index 000000000..fb18d50d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/my_00037.webp b/app/src/main/res/drawable-xhdpi/my_00037.webp new file mode 100644 index 000000000..704af615f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/my_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/neirong_empty.webp b/app/src/main/res/drawable-xhdpi/neirong_empty.webp new file mode 100644 index 000000000..b3fb9a4ff Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/neirong_empty.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00000.webp b/app/src/main/res/drawable-xhdpi/news_00000.webp new file mode 100644 index 000000000..09c584b33 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00000.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00001.webp b/app/src/main/res/drawable-xhdpi/news_00001.webp new file mode 100644 index 000000000..b799b81a1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00001.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00002.webp b/app/src/main/res/drawable-xhdpi/news_00002.webp new file mode 100644 index 000000000..e48754151 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00002.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00003.webp b/app/src/main/res/drawable-xhdpi/news_00003.webp new file mode 100644 index 000000000..2c99a4542 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00003.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00004.webp b/app/src/main/res/drawable-xhdpi/news_00004.webp new file mode 100644 index 000000000..ef73d7b6e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00004.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00005.webp b/app/src/main/res/drawable-xhdpi/news_00005.webp new file mode 100644 index 000000000..5f760a499 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00005.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00006.webp b/app/src/main/res/drawable-xhdpi/news_00006.webp new file mode 100644 index 000000000..e6afb1e5e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00006.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00007.webp b/app/src/main/res/drawable-xhdpi/news_00007.webp new file mode 100644 index 000000000..a9fc0ad46 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00007.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00008.webp b/app/src/main/res/drawable-xhdpi/news_00008.webp new file mode 100644 index 000000000..23a51296b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00008.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00009.webp b/app/src/main/res/drawable-xhdpi/news_00009.webp new file mode 100644 index 000000000..df442d8e9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00009.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00010.webp b/app/src/main/res/drawable-xhdpi/news_00010.webp new file mode 100644 index 000000000..38d2c213a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00010.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00011.webp b/app/src/main/res/drawable-xhdpi/news_00011.webp new file mode 100644 index 000000000..ef114674c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00011.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00012.webp b/app/src/main/res/drawable-xhdpi/news_00012.webp new file mode 100644 index 000000000..910916f15 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00012.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00013.webp b/app/src/main/res/drawable-xhdpi/news_00013.webp new file mode 100644 index 000000000..20cf515c0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00013.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00014.webp b/app/src/main/res/drawable-xhdpi/news_00014.webp new file mode 100644 index 000000000..ca64e030b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00014.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00015.webp b/app/src/main/res/drawable-xhdpi/news_00015.webp new file mode 100644 index 000000000..97ef8e875 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00015.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00016.webp b/app/src/main/res/drawable-xhdpi/news_00016.webp new file mode 100644 index 000000000..be1596ee5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00016.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00017.webp b/app/src/main/res/drawable-xhdpi/news_00017.webp new file mode 100644 index 000000000..3f6826c9b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00017.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00018.webp b/app/src/main/res/drawable-xhdpi/news_00018.webp new file mode 100644 index 000000000..c7813be9a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00018.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00019.webp b/app/src/main/res/drawable-xhdpi/news_00019.webp new file mode 100644 index 000000000..3827b3208 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00019.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00020.webp b/app/src/main/res/drawable-xhdpi/news_00020.webp new file mode 100644 index 000000000..b080c8e37 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00020.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00021.webp b/app/src/main/res/drawable-xhdpi/news_00021.webp new file mode 100644 index 000000000..83113d554 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00021.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00022.webp b/app/src/main/res/drawable-xhdpi/news_00022.webp new file mode 100644 index 000000000..e48f6debd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00022.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00023.webp b/app/src/main/res/drawable-xhdpi/news_00023.webp new file mode 100644 index 000000000..03cb17109 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00023.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00024.webp b/app/src/main/res/drawable-xhdpi/news_00024.webp new file mode 100644 index 000000000..a74efb636 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00024.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00025.webp b/app/src/main/res/drawable-xhdpi/news_00025.webp new file mode 100644 index 000000000..51a89bd64 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00025.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00026.webp b/app/src/main/res/drawable-xhdpi/news_00026.webp new file mode 100644 index 000000000..0cf7227b4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00026.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00027.webp b/app/src/main/res/drawable-xhdpi/news_00027.webp new file mode 100644 index 000000000..69b7cc303 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00027.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00028.webp b/app/src/main/res/drawable-xhdpi/news_00028.webp new file mode 100644 index 000000000..f0afe2fec Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00028.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00029.webp b/app/src/main/res/drawable-xhdpi/news_00029.webp new file mode 100644 index 000000000..9b5d43343 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00029.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00030.webp b/app/src/main/res/drawable-xhdpi/news_00030.webp new file mode 100644 index 000000000..4b1ee903d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00030.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00031.webp b/app/src/main/res/drawable-xhdpi/news_00031.webp new file mode 100644 index 000000000..662424d93 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00031.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00032.webp b/app/src/main/res/drawable-xhdpi/news_00032.webp new file mode 100644 index 000000000..eb41afc57 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00032.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00033.webp b/app/src/main/res/drawable-xhdpi/news_00033.webp new file mode 100644 index 000000000..9391f8877 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00033.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00034.webp b/app/src/main/res/drawable-xhdpi/news_00034.webp new file mode 100644 index 000000000..19c79d89d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00034.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00035.webp b/app/src/main/res/drawable-xhdpi/news_00035.webp new file mode 100644 index 000000000..d599aaa7a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00035.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00036.webp b/app/src/main/res/drawable-xhdpi/news_00036.webp new file mode 100644 index 000000000..500bd28af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00036.webp differ diff --git a/app/src/main/res/drawable-xhdpi/news_00037.webp b/app/src/main/res/drawable-xhdpi/news_00037.webp new file mode 100644 index 000000000..33dcc732c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/news_00037.webp differ diff --git a/app/src/main/res/drawable-xhdpi/pk_result_bg.9.png b/app/src/main/res/drawable-xhdpi/pk_result_bg.9.png new file mode 100644 index 000000000..96401cd51 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/pk_result_bg.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/popup_down.png b/app/src/main/res/drawable-xhdpi/popup_down.png new file mode 100644 index 000000000..83536dfe6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/popup_down.png differ diff --git a/app/src/main/res/drawable-xhdpi/popup_pitch_101.png b/app/src/main/res/drawable-xhdpi/popup_pitch_101.png new file mode 100644 index 000000000..f8a1aef72 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/popup_pitch_101.png differ diff --git a/app/src/main/res/drawable-xhdpi/qq_login.png b/app/src/main/res/drawable-xhdpi/qq_login.png new file mode 100644 index 000000000..3d2c1634f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/qq_login.png differ diff --git a/app/src/main/res/drawable-xhdpi/quit_monster_hunting_background.webp b/app/src/main/res/drawable-xhdpi/quit_monster_hunting_background.webp new file mode 100644 index 000000000..b77eacb0f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/quit_monster_hunting_background.webp differ diff --git a/app/src/main/res/drawable-xhdpi/register_verificaiton_code_refresh.webp b/app/src/main/res/drawable-xhdpi/register_verificaiton_code_refresh.webp new file mode 100644 index 000000000..ac838dc9e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/register_verificaiton_code_refresh.webp differ diff --git a/app/src/main/res/drawable-xhdpi/register_verification_code.webp b/app/src/main/res/drawable-xhdpi/register_verification_code.webp new file mode 100644 index 000000000..f7f23327a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/register_verification_code.webp differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_bg.webp b/app/src/main/res/drawable-xhdpi/room_cp_game_bg.webp new file mode 100644 index 000000000..01b24b2e0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_defeated.webp b/app/src/main/res/drawable-xhdpi/room_cp_game_defeated.webp new file mode 100644 index 000000000..3de9d1f0b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_defeated.webp differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_draw.webp b/app/src/main/res/drawable-xhdpi/room_cp_game_draw.webp new file mode 100644 index 000000000..3bba5d4af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_draw.webp differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_sel.webp b/app/src/main/res/drawable-xhdpi/room_cp_game_sel.webp new file mode 100644 index 000000000..32507ea05 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_sel.webp differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_victory.png b/app/src/main/res/drawable-xhdpi/room_cp_game_victory.png new file mode 100644 index 000000000..147dc2f45 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_victory.png differ diff --git a/app/src/main/res/drawable-xhdpi/room_cp_game_victory_head.png b/app/src/main/res/drawable-xhdpi/room_cp_game_victory_head.png new file mode 100644 index 000000000..9464f0ecc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_cp_game_victory_head.png differ diff --git a/app/src/main/res/drawable-xhdpi/room_ic_opera_game.png b/app/src/main/res/drawable-xhdpi/room_ic_opera_game.png new file mode 100644 index 000000000..a8aa00ed5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/room_ic_opera_game.png differ diff --git a/app/src/main/res/drawable-xhdpi/selector_lucky_money_sender.xml b/app/src/main/res/drawable-xhdpi/selector_lucky_money_sender.xml new file mode 100644 index 000000000..69c28b151 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/selector_lucky_money_sender.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/setting_right.webp b/app/src/main/res/drawable-xhdpi/setting_right.webp new file mode 100644 index 000000000..9af6a69c0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/setting_right.webp differ diff --git a/app/src/main/res/drawable-xhdpi/share_result_hint.png b/app/src/main/res/drawable-xhdpi/share_result_hint.png new file mode 100644 index 000000000..de49b9a46 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/share_result_hint.png differ diff --git a/app/src/main/res/drawable-xhdpi/splash_logo.webp b/app/src/main/res/drawable-xhdpi/splash_logo.webp new file mode 100644 index 000000000..8e4a1248e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/splash_logo.webp differ diff --git a/app/src/main/res/drawable-xhdpi/tag_101.webp b/app/src/main/res/drawable-xhdpi/tag_101.webp new file mode 100644 index 000000000..1f31a90e5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/tag_101.webp differ diff --git a/app/src/main/res/drawable-xhdpi/tag_authentication_101bg.webp b/app/src/main/res/drawable-xhdpi/tag_authentication_101bg.webp new file mode 100644 index 000000000..af50d53a8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/tag_authentication_101bg.webp differ diff --git a/app/src/main/res/drawable-xhdpi/tag_game_top1.png b/app/src/main/res/drawable-xhdpi/tag_game_top1.png new file mode 100644 index 000000000..205552534 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/tag_game_top1.png differ diff --git a/app/src/main/res/drawable-xhdpi/tutu_default_avatar_purple.webp b/app/src/main/res/drawable-xhdpi/tutu_default_avatar_purple.webp new file mode 100644 index 000000000..0f2657049 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/tutu_default_avatar_purple.webp differ diff --git a/app/src/main/res/drawable-xhdpi/wallet_jewel.png b/app/src/main/res/drawable-xhdpi/wallet_jewel.png new file mode 100644 index 000000000..820ca6664 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wallet_jewel.png differ diff --git a/app/src/main/res/drawable-xhdpi/withdraw_focused.webp b/app/src/main/res/drawable-xhdpi/withdraw_focused.webp new file mode 100644 index 000000000..1c7392580 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/withdraw_focused.webp differ diff --git a/app/src/main/res/drawable-xhdpi/withdraw_un.webp b/app/src/main/res/drawable-xhdpi/withdraw_un.webp new file mode 100644 index 000000000..7b56dad6f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/withdraw_un.webp differ diff --git a/app/src/main/res/drawable-xhdpi/wx_login.png b/app/src/main/res/drawable-xhdpi/wx_login.png new file mode 100644 index 000000000..5c0a4a028 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wx_login.png differ diff --git a/app/src/main/res/drawable-xhdpi/zhifubao.webp b/app/src/main/res/drawable-xhdpi/zhifubao.webp new file mode 100644 index 000000000..8eeb3cd15 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/zhifubao.webp differ diff --git a/app/src/main/res/drawable-xhdpi/zhifubao_un.webp b/app/src/main/res/drawable-xhdpi/zhifubao_un.webp new file mode 100644 index 000000000..0d015dd58 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/zhifubao_un.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_one_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_one_background.webp new file mode 100644 index 000000000..e1baaf635 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_one_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_three_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_three_background.webp new file mode 100644 index 000000000..e0a322752 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_three_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_two_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_two_background.webp new file mode 100644 index 000000000..46e60365e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_avatar_level_two_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_1.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_1.webp new file mode 100644 index 000000000..e69f4911f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_1.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_2.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_2.webp new file mode 100644 index 000000000..728c5a149 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_2.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_3.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_3.webp new file mode 100644 index 000000000..c812c383d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_give_level_3.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_one_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_one_background.webp new file mode 100644 index 000000000..a64c90677 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_one_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_background.webp new file mode 100644 index 000000000..ac4abe780 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_close.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_close.webp new file mode 100644 index 000000000..b22dabba8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_close.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_go_to.9.png b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_go_to.9.png new file mode 100644 index 000000000..29e16370c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_three_go_to.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_background.webp b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_background.webp new file mode 100644 index 000000000..d85a33f75 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_background.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_go_to.9.png b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_go_to.9.png new file mode 100644 index 000000000..1f376a956 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_level_two_go_to.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_message_background.9.png b/app/src/main/res/drawable-xxhdpi/all_service_gift_message_background.9.png new file mode 100644 index 000000000..c78346358 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_message_background.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/all_service_gift_message_level_three_background.9.png b/app/src/main/res/drawable-xxhdpi/all_service_gift_message_level_three_background.9.png new file mode 100644 index 000000000..bf7c70f9d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/all_service_gift_message_level_three_background.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_charm_level_up.webp b/app/src/main/res/drawable-xxhdpi/bg_charm_level_up.webp new file mode 100644 index 000000000..064c2506d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_charm_level_up.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_level_up.webp b/app/src/main/res/drawable-xxhdpi/bg_level_up.webp new file mode 100644 index 000000000..6e22c1ac0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_level_up.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_my_top_bottom_white.webp b/app/src/main/res/drawable-xxhdpi/bg_my_top_bottom_white.webp new file mode 100644 index 000000000..2a7790ba4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_my_top_bottom_white.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/charm_level_up_line_left.webp b/app/src/main/res/drawable-xxhdpi/charm_level_up_line_left.webp new file mode 100644 index 000000000..89c878f20 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/charm_level_up_line_left.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/charm_level_up_line_right.webp b/app/src/main/res/drawable-xxhdpi/charm_level_up_line_right.webp new file mode 100644 index 000000000..71f4918e2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/charm_level_up_line_right.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_task_bottom_first.webp b/app/src/main/res/drawable-xxhdpi/cover_task_bottom_first.webp new file mode 100644 index 000000000..fd3e4e938 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cover_task_bottom_first.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_task_top_first.webp b/app/src/main/res/drawable-xxhdpi/cover_task_top_first.webp new file mode 100644 index 000000000..f5861b69e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cover_task_top_first.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_task_top_fourth.webp b/app/src/main/res/drawable-xxhdpi/cover_task_top_fourth.webp new file mode 100644 index 000000000..854923fb2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cover_task_top_fourth.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_task_top_second.webp b/app/src/main/res/drawable-xxhdpi/cover_task_top_second.webp new file mode 100644 index 000000000..2dbe47c3e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cover_task_top_second.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_task_top_third.webp b/app/src/main/res/drawable-xxhdpi/cover_task_top_third.webp new file mode 100644 index 000000000..e78d06834 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cover_task_top_third.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/dice_guide.webp b/app/src/main/res/drawable-xxhdpi/dice_guide.webp new file mode 100644 index 000000000..c5cb72b87 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/dice_guide.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_about_me.webp b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_about_me.webp new file mode 100644 index 000000000..c99e89b3c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_about_me.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_monster.webp b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_monster.webp new file mode 100644 index 000000000..34335e31e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_monster.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_new.webp b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_new.webp new file mode 100644 index 000000000..2c27b8256 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/erban_toutiao_tag_new.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_ali_charge.webp b/app/src/main/res/drawable-xxhdpi/ic_ali_charge.webp new file mode 100644 index 000000000..096a12a5b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_ali_charge.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_car_price.webp b/app/src/main/res/drawable-xxhdpi/ic_car_price.webp new file mode 100644 index 000000000..c2ab7ef29 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_car_price.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_car_selected.webp b/app/src/main/res/drawable-xxhdpi/ic_car_selected.webp new file mode 100644 index 000000000..f9b149eca Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_car_selected.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_car_unselected.webp b/app/src/main/res/drawable-xxhdpi/ic_car_unselected.webp new file mode 100644 index 000000000..728ac93d2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_car_unselected.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_chat_navigation_attention.webp b/app/src/main/res/drawable-xxhdpi/ic_chat_navigation_attention.webp new file mode 100644 index 000000000..d4f0499a4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_chat_navigation_attention.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_close_all_server_one.webp b/app/src/main/res/drawable-xxhdpi/ic_close_all_server_one.webp new file mode 100644 index 000000000..84e474571 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_close_all_server_one.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_close_all_server_two.webp b/app/src/main/res/drawable-xxhdpi/ic_close_all_server_two.webp new file mode 100644 index 000000000..ccc5494e7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_close_all_server_two.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_contact.webp b/app/src/main/res/drawable-xxhdpi/ic_contact.webp new file mode 100644 index 000000000..937075bfd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_contact.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_king_recommend.webp b/app/src/main/res/drawable-xxhdpi/ic_king_recommend.webp new file mode 100644 index 000000000..2be1027ba Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_king_recommend.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_mark_discount.webp b/app/src/main/res/drawable-xxhdpi/ic_mark_discount.webp new file mode 100644 index 000000000..988e4e9fa Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_mark_discount.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_mark_exclusive.webp b/app/src/main/res/drawable-xxhdpi/ic_mark_exclusive.webp new file mode 100644 index 000000000..bbac2dc5f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_mark_exclusive.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_mark_limit.webp b/app/src/main/res/drawable-xxhdpi/ic_mark_limit.webp new file mode 100644 index 000000000..15bc67f58 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_mark_limit.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_mark_new.webp b/app/src/main/res/drawable-xxhdpi/ic_mark_new.webp new file mode 100644 index 000000000..0cc1f6f2e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_mark_new.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_mute_notification.webp b/app/src/main/res/drawable-xxhdpi/ic_mute_notification.webp new file mode 100644 index 000000000..bd8e8b9ba Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_mute_notification.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_person_edit.webp b/app/src/main/res/drawable-xxhdpi/ic_person_edit.webp new file mode 100644 index 000000000..671670ab2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_person_edit.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_room_lock_icon.webp b/app/src/main/res/drawable-xxhdpi/ic_room_lock_icon.webp new file mode 100644 index 000000000..dc25ea671 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_room_lock_icon.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_voice_bottle_report.webp b/app/src/main/res/drawable-xxhdpi/ic_voice_bottle_report.webp new file mode 100644 index 000000000..f1ff61a38 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_voice_bottle_report.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_wechat_charge.webp b/app/src/main/res/drawable-xxhdpi/ic_wechat_charge.webp new file mode 100644 index 000000000..16244d745 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_wechat_charge.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_app.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_app.webp new file mode 100644 index 000000000..a6b5f351e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_app.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_game_enter_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_game_enter_tips.webp new file mode 100644 index 000000000..d43aeee4a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_game_enter_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_giftdialog_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_giftdialog_tips.webp new file mode 100644 index 000000000..788a7c1af Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_giftdialog_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_main_top_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_main_top_tips.webp new file mode 100644 index 000000000..e1a1b013c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_main_top_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_me_enter_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_me_enter_tips.webp new file mode 100644 index 000000000..a8a8f00b5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_me_enter_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_msg_enter_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_msg_enter_tips.webp new file mode 100644 index 000000000..37a648196 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_msg_enter_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_next.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_next.webp new file mode 100644 index 000000000..56f6ce824 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_next.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_room_send_gift_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_room_send_gift_tips.webp new file mode 100644 index 000000000..0d7ff6c26 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_room_send_gift_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_sign_text.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_sign_text.webp new file mode 100644 index 000000000..716c94d75 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_sign_text.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_skip.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_skip.webp new file mode 100644 index 000000000..83ec64a74 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_skip.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_to_like_voice_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_to_like_voice_tips.webp new file mode 100644 index 000000000..edf3bebe4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_to_like_voice_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_to_record_voice_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_to_record_voice_tips.webp new file mode 100644 index 000000000..93d7bd229 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_to_record_voice_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_guide_to_up_mic_tips.webp b/app/src/main/res/drawable-xxhdpi/icon_guide_to_up_mic_tips.webp new file mode 100644 index 000000000..88214f2e8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_guide_to_up_mic_tips.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_0.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_0.webp new file mode 100644 index 000000000..b6bd5fe39 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_0.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_2.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_2.webp new file mode 100644 index 000000000..07f5efb23 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_bottom_2.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_middle_0.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_middle_0.webp new file mode 100644 index 000000000..febfc1389 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_middle_0.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_0.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_0.webp new file mode 100644 index 000000000..ca162b187 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_0.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_1.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_1.webp new file mode 100644 index 000000000..a8f05b83a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_1.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_2.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_2.webp new file mode 100644 index 000000000..63d49c9d9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_start_top_2.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_gv_status_bar.webp b/app/src/main/res/drawable-xxhdpi/icon_gv_status_bar.webp new file mode 100644 index 000000000..35c20cabb Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_gv_status_bar.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue.webp b/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue.webp new file mode 100644 index 000000000..796ae7c1b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue_not_empty.webp b/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue_not_empty.webp new file mode 100644 index 000000000..7e52b8685 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_room_mic_queue_not_empty.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/level_up_line_left.webp b/app/src/main/res/drawable-xxhdpi/level_up_line_left.webp new file mode 100644 index 000000000..50ae1cea7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/level_up_line_left.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/level_up_line_right.webp b/app/src/main/res/drawable-xxhdpi/level_up_line_right.webp new file mode 100644 index 000000000..23894c1d0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/level_up_line_right.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/selector_filtrate_mid.xml b/app/src/main/res/drawable-xxhdpi/selector_filtrate_mid.xml new file mode 100644 index 000000000..5df8c8b05 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/selector_filtrate_mid.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/shape_filtrate_left_noselect.xml b/app/src/main/res/drawable-xxhdpi/shape_filtrate_left_noselect.xml new file mode 100644 index 000000000..4c51eff09 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/shape_filtrate_left_noselect.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/shape_filtrate_mid.xml b/app/src/main/res/drawable-xxhdpi/shape_filtrate_mid.xml new file mode 100644 index 000000000..0dc8f6501 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/shape_filtrate_mid.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/shape_gray_5dp.xml b/app/src/main/res/drawable-xxhdpi/shape_gray_5dp.xml new file mode 100644 index 000000000..2cbed9c1a --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/shape_gray_5dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/splash_logo.webp b/app/src/main/res/drawable-xxhdpi/splash_logo.webp new file mode 100644 index 000000000..fc049db3d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/splash_logo.webp differ diff --git a/app/src/main/res/drawable/anim_list_common_loading.xml b/app/src/main/res/drawable/anim_list_common_loading.xml new file mode 100644 index 000000000..39c10a18b --- /dev/null +++ b/app/src/main/res/drawable/anim_list_common_loading.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/anim_living_icon.xml b/app/src/main/res/drawable/anim_living_icon.xml new file mode 100644 index 000000000..4a380a444 --- /dev/null +++ b/app/src/main/res/drawable/anim_living_icon.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/anim_match.xml b/app/src/main/res/drawable/anim_match.xml new file mode 100644 index 000000000..da0d1c14d --- /dev/null +++ b/app/src/main/res/drawable/anim_match.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/attention_live_anim.xml b/app/src/main/res/drawable/attention_live_anim.xml new file mode 100644 index 000000000..c6f0e843b --- /dev/null +++ b/app/src/main/res/drawable/attention_live_anim.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_bind_success.xml b/app/src/main/res/drawable/bg_bind_success.xml new file mode 100644 index 000000000..6ce9c6c4e --- /dev/null +++ b/app/src/main/res/drawable/bg_bind_success.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_bind_success_close.xml b/app/src/main/res/drawable/bg_bind_success_close.xml new file mode 100644 index 000000000..6edb4a00d --- /dev/null +++ b/app/src/main/res/drawable/bg_bind_success_close.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_binding_button.xml b/app/src/main/res/drawable/bg_binding_button.xml new file mode 100644 index 000000000..16c89ad3b --- /dev/null +++ b/app/src/main/res/drawable/bg_binding_button.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_cancel_join_family.xml b/app/src/main/res/drawable/bg_cancel_join_family.xml new file mode 100644 index 000000000..d1c2618a6 --- /dev/null +++ b/app/src/main/res/drawable/bg_cancel_join_family.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_drive_selector.xml b/app/src/main/res/drawable/bg_car_drive_selector.xml new file mode 100644 index 000000000..f87690409 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_drive_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item.xml b/app/src/main/res/drawable/bg_car_item.xml new file mode 100644 index 000000000..f03fb3547 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_buy.xml b/app/src/main/res/drawable/bg_car_item_buy.xml new file mode 100644 index 000000000..4ceb0dbde --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_buy.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_buy_cancel.xml b/app/src/main/res/drawable/bg_car_item_buy_cancel.xml new file mode 100644 index 000000000..a388afbe7 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_buy_cancel.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_days.xml b/app/src/main/res/drawable/bg_car_item_days.xml new file mode 100644 index 000000000..d13258627 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_days.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_garage.xml b/app/src/main/res/drawable/bg_car_item_garage.xml new file mode 100644 index 000000000..ba520c7ab --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_garage.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_renew.xml b/app/src/main/res/drawable/bg_car_item_renew.xml new file mode 100644 index 000000000..ce321c025 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_renew.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_renew_cancel.xml b/app/src/main/res/drawable/bg_car_item_renew_cancel.xml new file mode 100644 index 000000000..07f2e4fbf --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_renew_cancel.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_select.xml b/app/src/main/res/drawable/bg_car_item_select.xml new file mode 100644 index 000000000..0e57aafc0 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_select.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_shop.xml b/app/src/main/res/drawable/bg_car_item_shop.xml new file mode 100644 index 000000000..beae2f074 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_shop.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_item_shop_select.xml b/app/src/main/res/drawable/bg_car_item_shop_select.xml new file mode 100644 index 000000000..d8358df86 --- /dev/null +++ b/app/src/main/res/drawable/bg_car_item_shop_select.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_car_tab_badge.xml b/app/src/main/res/drawable/bg_car_tab_badge.xml new file mode 100644 index 000000000..d7dc90c6f --- /dev/null +++ b/app/src/main/res/drawable/bg_car_tab_badge.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_chat_task_num.xml b/app/src/main/res/drawable/bg_chat_task_num.xml new file mode 100644 index 000000000..74cb5c79f --- /dev/null +++ b/app/src/main/res/drawable/bg_chat_task_num.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_chatter_box.xml b/app/src/main/res/drawable/bg_chatter_box.xml new file mode 100644 index 000000000..4c8ca692a --- /dev/null +++ b/app/src/main/res/drawable/bg_chatter_box.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_chatterbox_init_invalid.xml b/app/src/main/res/drawable/bg_chatterbox_init_invalid.xml new file mode 100644 index 000000000..2409341ed --- /dev/null +++ b/app/src/main/res/drawable/bg_chatterbox_init_invalid.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_chatterbox_init_valid.xml b/app/src/main/res/drawable/bg_chatterbox_init_valid.xml new file mode 100644 index 000000000..c3e3ae8b2 --- /dev/null +++ b/app/src/main/res/drawable/bg_chatterbox_init_valid.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_close_pk_mode.xml b/app/src/main/res/drawable/bg_close_pk_mode.xml new file mode 100644 index 000000000..23a6a5b03 --- /dev/null +++ b/app/src/main/res/drawable/bg_close_pk_mode.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_common_cancel.xml b/app/src/main/res/drawable/bg_common_cancel.xml new file mode 100644 index 000000000..e5a508a58 --- /dev/null +++ b/app/src/main/res/drawable/bg_common_cancel.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_common_confirm.xml b/app/src/main/res/drawable/bg_common_confirm.xml new file mode 100644 index 000000000..cfc21edee --- /dev/null +++ b/app/src/main/res/drawable/bg_common_confirm.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_common_touch_trans.xml b/app/src/main/res/drawable/bg_common_touch_trans.xml new file mode 100644 index 000000000..a91d4477c --- /dev/null +++ b/app/src/main/res/drawable/bg_common_touch_trans.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_common_touch_while.xml b/app/src/main/res/drawable/bg_common_touch_while.xml new file mode 100644 index 000000000..4bfd58c0e --- /dev/null +++ b/app/src/main/res/drawable/bg_common_touch_while.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_confirm_join_family.xml b/app/src/main/res/drawable/bg_confirm_join_family.xml new file mode 100644 index 000000000..d1ff8d764 --- /dev/null +++ b/app/src/main/res/drawable/bg_confirm_join_family.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_confirm_payment.xml b/app/src/main/res/drawable/bg_confirm_payment.xml new file mode 100644 index 000000000..903b618b1 --- /dev/null +++ b/app/src/main/res/drawable/bg_confirm_payment.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_contribute_entrance.xml b/app/src/main/res/drawable/bg_contribute_entrance.xml new file mode 100644 index 000000000..82fc361d2 --- /dev/null +++ b/app/src/main/res/drawable/bg_contribute_entrance.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dialog_loading.xml b/app/src/main/res/drawable/bg_dialog_loading.xml new file mode 100644 index 000000000..83035d124 --- /dev/null +++ b/app/src/main/res/drawable/bg_dialog_loading.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dialog_room_operation.xml b/app/src/main/res/drawable/bg_dialog_room_operation.xml new file mode 100644 index 000000000..7ca5728d5 --- /dev/null +++ b/app/src/main/res/drawable/bg_dialog_room_operation.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dialog_share.xml b/app/src/main/res/drawable/bg_dialog_share.xml new file mode 100644 index 000000000..2c666170f --- /dev/null +++ b/app/src/main/res/drawable/bg_dialog_share.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dice.xml b/app/src/main/res/drawable/bg_dice.xml new file mode 100644 index 000000000..59058383e --- /dev/null +++ b/app/src/main/res/drawable/bg_dice.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_selected.xml b/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_selected.xml new file mode 100644 index 000000000..7bc196055 --- /dev/null +++ b/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_selected.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_unselected.xml b/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_unselected.xml new file mode 100644 index 000000000..01e276bd0 --- /dev/null +++ b/app/src/main/res/drawable/bg_dynamic_face_dialog_indicator_unselected.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_dynamic_face_dialog_selector.xml b/app/src/main/res/drawable/bg_dynamic_face_dialog_selector.xml new file mode 100644 index 000000000..cc1b0d45b --- /dev/null +++ b/app/src/main/res/drawable/bg_dynamic_face_dialog_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_e6e6e6_0_2_5.xml b/app/src/main/res/drawable/bg_e6e6e6_0_2_5.xml new file mode 100644 index 000000000..77c9fbd8d --- /dev/null +++ b/app/src/main/res/drawable/bg_e6e6e6_0_2_5.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_f3f2f5_0_15.xml b/app/src/main/res/drawable/bg_f3f2f5_0_15.xml new file mode 100644 index 000000000..ae5e0e8e8 --- /dev/null +++ b/app/src/main/res/drawable/bg_f3f2f5_0_15.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_currency_action.xml b/app/src/main/res/drawable/bg_family_currency_action.xml new file mode 100644 index 000000000..5c57cc833 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_currency_action.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_dialog_edit.xml b/app/src/main/res/drawable/bg_family_dialog_edit.xml new file mode 100644 index 000000000..74fc63553 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_dialog_edit.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_group_join.xml b/app/src/main/res/drawable/bg_family_group_join.xml new file mode 100644 index 000000000..892e21e00 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_group_join.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_manage.xml b/app/src/main/res/drawable/bg_family_manage.xml new file mode 100644 index 000000000..2424a59e7 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_manage.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_member_search_edit.xml b/app/src/main/res/drawable/bg_family_member_search_edit.xml new file mode 100644 index 000000000..e53c5e1e4 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_member_search_edit.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_family_menu_dialog.xml b/app/src/main/res/drawable/bg_family_menu_dialog.xml new file mode 100644 index 000000000..facc8b370 --- /dev/null +++ b/app/src/main/res/drawable/bg_family_menu_dialog.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_ff838d_10_12_5.xml b/app/src/main/res/drawable/bg_ff838d_10_12_5.xml new file mode 100644 index 000000000..f789284c7 --- /dev/null +++ b/app/src/main/res/drawable/bg_ff838d_10_12_5.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_find_item_round_rect.xml b/app/src/main/res/drawable/bg_find_item_round_rect.xml new file mode 100644 index 000000000..34d75b8f9 --- /dev/null +++ b/app/src/main/res/drawable/bg_find_item_round_rect.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_find_item_round_rect_bottom.xml b/app/src/main/res/drawable/bg_find_item_round_rect_bottom.xml new file mode 100644 index 000000000..3002b2f99 --- /dev/null +++ b/app/src/main/res/drawable/bg_find_item_round_rect_bottom.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_find_item_round_rect_top.xml b/app/src/main/res/drawable/bg_find_item_round_rect_top.xml new file mode 100644 index 000000000..e75feeec6 --- /dev/null +++ b/app/src/main/res/drawable/bg_find_item_round_rect_top.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_game_room_tab_select.xml b/app/src/main/res/drawable/bg_game_room_tab_select.xml new file mode 100644 index 000000000..17c74fcd1 --- /dev/null +++ b/app/src/main/res/drawable/bg_game_room_tab_select.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_gift_number.xml b/app/src/main/res/drawable/bg_gift_number.xml new file mode 100644 index 000000000..186dcd41e --- /dev/null +++ b/app/src/main/res/drawable/bg_gift_number.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_giftlayout.xml b/app/src/main/res/drawable/bg_giftlayout.xml new file mode 100644 index 000000000..a05b4b987 --- /dev/null +++ b/app/src/main/res/drawable/bg_giftlayout.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_go_web.xml b/app/src/main/res/drawable/bg_go_web.xml new file mode 100644 index 000000000..e62a594e8 --- /dev/null +++ b/app/src/main/res/drawable/bg_go_web.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_gold_include_noble.xml b/app/src/main/res/drawable/bg_gold_include_noble.xml new file mode 100644 index 000000000..c5e9b2fca --- /dev/null +++ b/app/src/main/res/drawable/bg_gold_include_noble.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_notice.xml b/app/src/main/res/drawable/bg_home_notice.xml new file mode 100644 index 000000000..a00ca1b06 --- /dev/null +++ b/app/src/main/res/drawable/bg_home_notice.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_recommend_1.xml b/app/src/main/res/drawable/bg_home_recommend_1.xml new file mode 100644 index 000000000..1f5b0c09b --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_1.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_recommend_2.xml b/app/src/main/res/drawable/bg_home_recommend_2.xml new file mode 100644 index 000000000..8590c1c6d --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_2.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_recommend_3.xml b/app/src/main/res/drawable/bg_home_recommend_3.xml new file mode 100644 index 000000000..cdbd3cc99 --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_3.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_recommend_4.xml b/app/src/main/res/drawable/bg_home_recommend_4.xml new file mode 100644 index 000000000..33100519b --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_4.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_home_recommend_5.xml b/app/src/main/res/drawable/bg_home_recommend_5.xml new file mode 100644 index 000000000..68861f5f8 --- /dev/null +++ b/app/src/main/res/drawable/bg_home_recommend_5.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_introduction.xml b/app/src/main/res/drawable/bg_introduction.xml new file mode 100644 index 000000000..1ee8b5fdd --- /dev/null +++ b/app/src/main/res/drawable/bg_introduction.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_introduction_tag.xml b/app/src/main/res/drawable/bg_introduction_tag.xml new file mode 100644 index 000000000..b0e4319d8 --- /dev/null +++ b/app/src/main/res/drawable/bg_introduction_tag.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_item_family_group_join.xml b/app/src/main/res/drawable/bg_item_family_group_join.xml new file mode 100644 index 000000000..e2989ebb3 --- /dev/null +++ b/app/src/main/res/drawable/bg_item_family_group_join.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_item_select.xml b/app/src/main/res/drawable/bg_item_select.xml new file mode 100644 index 000000000..b6a6b1584 --- /dev/null +++ b/app/src/main/res/drawable/bg_item_select.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/bg_label.xml b/app/src/main/res/drawable/bg_label.xml new file mode 100644 index 000000000..886248098 --- /dev/null +++ b/app/src/main/res/drawable/bg_label.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_leave_mode.xml b/app/src/main/res/drawable/bg_leave_mode.xml new file mode 100644 index 000000000..3e87f4b4c --- /dev/null +++ b/app/src/main/res/drawable/bg_leave_mode.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_login_button.xml b/app/src/main/res/drawable/bg_login_button.xml new file mode 100644 index 000000000..b7b0011ef --- /dev/null +++ b/app/src/main/res/drawable/bg_login_button.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_logout.xml b/app/src/main/res/drawable/bg_logout.xml new file mode 100644 index 000000000..308e110c5 --- /dev/null +++ b/app/src/main/res/drawable/bg_logout.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_magic_dialog_button_send.xml b/app/src/main/res/drawable/bg_magic_dialog_button_send.xml new file mode 100644 index 000000000..7940f5685 --- /dev/null +++ b/app/src/main/res/drawable/bg_magic_dialog_button_send.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_main_get_more.xml b/app/src/main/res/drawable/bg_main_get_more.xml new file mode 100644 index 000000000..b5835ef4f --- /dev/null +++ b/app/src/main/res/drawable/bg_main_get_more.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_messge_view_bottom_tip.xml b/app/src/main/res/drawable/bg_messge_view_bottom_tip.xml new file mode 100644 index 000000000..98bdef7d9 --- /dev/null +++ b/app/src/main/res/drawable/bg_messge_view_bottom_tip.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_mic_queue_no.xml b/app/src/main/res/drawable/bg_mic_queue_no.xml new file mode 100644 index 000000000..dc7e9f400 --- /dev/null +++ b/app/src/main/res/drawable/bg_mic_queue_no.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_modify_audio_record.xml b/app/src/main/res/drawable/bg_modify_audio_record.xml new file mode 100644 index 000000000..c9de1590b --- /dev/null +++ b/app/src/main/res/drawable/bg_modify_audio_record.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_msg_gift_img.xml b/app/src/main/res/drawable/bg_msg_gift_img.xml new file mode 100644 index 000000000..4c8ca692a --- /dev/null +++ b/app/src/main/res/drawable/bg_msg_gift_img.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_msg_gift_img_normal.xml b/app/src/main/res/drawable/bg_msg_gift_img_normal.xml new file mode 100644 index 000000000..52e838ce8 --- /dev/null +++ b/app/src/main/res/drawable/bg_msg_gift_img_normal.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/app/src/main/res/drawable/bg_msg_number.xml b/app/src/main/res/drawable/bg_msg_number.xml new file mode 100644 index 000000000..6eff0e804 --- /dev/null +++ b/app/src/main/res/drawable/bg_msg_number.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_msg_view_holder_voice.xml b/app/src/main/res/drawable/bg_msg_view_holder_voice.xml new file mode 100644 index 000000000..9aad895da --- /dev/null +++ b/app/src/main/res/drawable/bg_msg_view_holder_voice.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_msg_view_holder_voice_button.xml b/app/src/main/res/drawable/bg_msg_view_holder_voice_button.xml new file mode 100644 index 000000000..767e62d7c --- /dev/null +++ b/app/src/main/res/drawable/bg_msg_view_holder_voice_button.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_music_player_empty.xml b/app/src/main/res/drawable/bg_music_player_empty.xml new file mode 100644 index 000000000..39bb05020 --- /dev/null +++ b/app/src/main/res/drawable/bg_music_player_empty.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_decoration_img.xml b/app/src/main/res/drawable/bg_my_decoration_img.xml new file mode 100644 index 000000000..7251cff7b --- /dev/null +++ b/app/src/main/res/drawable/bg_my_decoration_img.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_head_buy.xml b/app/src/main/res/drawable/bg_my_head_buy.xml new file mode 100644 index 000000000..f9a5c60dd --- /dev/null +++ b/app/src/main/res/drawable/bg_my_head_buy.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_head_invalid.xml b/app/src/main/res/drawable/bg_my_head_invalid.xml new file mode 100644 index 000000000..16d3bee5f --- /dev/null +++ b/app/src/main/res/drawable/bg_my_head_invalid.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_head_renew.xml b/app/src/main/res/drawable/bg_my_head_renew.xml new file mode 100644 index 000000000..4084553fc --- /dev/null +++ b/app/src/main/res/drawable/bg_my_head_renew.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_voice.xml b/app/src/main/res/drawable/bg_my_voice.xml new file mode 100644 index 000000000..6c4e211ff --- /dev/null +++ b/app/src/main/res/drawable/bg_my_voice.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_voice_item_in_review.xml b/app/src/main/res/drawable/bg_my_voice_item_in_review.xml new file mode 100644 index 000000000..aa6b56f69 --- /dev/null +++ b/app/src/main/res/drawable/bg_my_voice_item_in_review.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_voice_item_verified.xml b/app/src/main/res/drawable/bg_my_voice_item_verified.xml new file mode 100644 index 000000000..11c6fecb6 --- /dev/null +++ b/app/src/main/res/drawable/bg_my_voice_item_verified.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_my_voice_vie_stub.xml b/app/src/main/res/drawable/bg_my_voice_vie_stub.xml new file mode 100644 index 000000000..6b240ee8c --- /dev/null +++ b/app/src/main/res/drawable/bg_my_voice_vie_stub.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_new_user_task_button.xml b/app/src/main/res/drawable/bg_new_user_task_button.xml new file mode 100644 index 000000000..82dcfd6de --- /dev/null +++ b/app/src/main/res/drawable/bg_new_user_task_button.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_new_user_task_button_enable.xml b/app/src/main/res/drawable/bg_new_user_task_button_enable.xml new file mode 100644 index 000000000..25523d1c4 --- /dev/null +++ b/app/src/main/res/drawable/bg_new_user_task_button_enable.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_new_user_task_button_normal.xml b/app/src/main/res/drawable/bg_new_user_task_button_normal.xml new file mode 100644 index 000000000..6b928179b --- /dev/null +++ b/app/src/main/res/drawable/bg_new_user_task_button_normal.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_new_user_task_dialog.xml b/app/src/main/res/drawable/bg_new_user_task_dialog.xml new file mode 100644 index 000000000..d4849a67a --- /dev/null +++ b/app/src/main/res/drawable/bg_new_user_task_dialog.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_no_data_fragment_button.xml b/app/src/main/res/drawable/bg_no_data_fragment_button.xml new file mode 100644 index 000000000..8ffaa699c --- /dev/null +++ b/app/src/main/res/drawable/bg_no_data_fragment_button.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_number_female.xml b/app/src/main/res/drawable/bg_number_female.xml new file mode 100644 index 000000000..4dbf15f0a --- /dev/null +++ b/app/src/main/res/drawable/bg_number_female.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_number_male.xml b/app/src/main/res/drawable/bg_number_male.xml new file mode 100644 index 000000000..d2e591ad8 --- /dev/null +++ b/app/src/main/res/drawable/bg_number_male.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_radius_attention_black.xml b/app/src/main/res/drawable/bg_radius_attention_black.xml new file mode 100644 index 000000000..d4023ab15 --- /dev/null +++ b/app/src/main/res/drawable/bg_radius_attention_black.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_radius_live_black.xml b/app/src/main/res/drawable/bg_radius_live_black.xml new file mode 100644 index 000000000..3e35b1358 --- /dev/null +++ b/app/src/main/res/drawable/bg_radius_live_black.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_recall_confirm.xml b/app/src/main/res/drawable/bg_recall_confirm.xml new file mode 100644 index 000000000..4f8c6d6c0 --- /dev/null +++ b/app/src/main/res/drawable/bg_recall_confirm.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_recall_dialog.xml b/app/src/main/res/drawable/bg_recall_dialog.xml new file mode 100644 index 000000000..ad49326b1 --- /dev/null +++ b/app/src/main/res/drawable/bg_recall_dialog.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_recall_input.xml b/app/src/main/res/drawable/bg_recall_input.xml new file mode 100644 index 000000000..76aa8917c --- /dev/null +++ b/app/src/main/res/drawable/bg_recall_input.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_recall_text_cursor.xml b/app/src/main/res/drawable/bg_recall_text_cursor.xml new file mode 100644 index 000000000..497c4b7a9 --- /dev/null +++ b/app/src/main/res/drawable/bg_recall_text_cursor.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_reward_notice.xml b/app/src/main/res/drawable/bg_reward_notice.xml new file mode 100644 index 000000000..5559ad6cc --- /dev/null +++ b/app/src/main/res/drawable/bg_reward_notice.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_reward_notice_select.xml b/app/src/main/res/drawable/bg_reward_notice_select.xml new file mode 100644 index 000000000..a574e7486 --- /dev/null +++ b/app/src/main/res/drawable/bg_reward_notice_select.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_reward_number.xml b/app/src/main/res/drawable/bg_reward_number.xml new file mode 100644 index 000000000..d4d80ba59 --- /dev/null +++ b/app/src/main/res/drawable/bg_reward_number.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_reward_number_big.xml b/app/src/main/res/drawable/bg_reward_number_big.xml new file mode 100644 index 000000000..45ef3f33b --- /dev/null +++ b/app/src/main/res/drawable/bg_reward_number_big.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_message_noble_4.xml b/app/src/main/res/drawable/bg_room_message_noble_4.xml new file mode 100644 index 000000000..1124ea144 --- /dev/null +++ b/app/src/main/res/drawable/bg_room_message_noble_4.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_message_noble_5.xml b/app/src/main/res/drawable/bg_room_message_noble_5.xml new file mode 100644 index 000000000..35e713e3c --- /dev/null +++ b/app/src/main/res/drawable/bg_room_message_noble_5.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_message_noble_6.xml b/app/src/main/res/drawable/bg_room_message_noble_6.xml new file mode 100644 index 000000000..a2cf260f0 --- /dev/null +++ b/app/src/main/res/drawable/bg_room_message_noble_6.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_message_noble_7.xml b/app/src/main/res/drawable/bg_room_message_noble_7.xml new file mode 100644 index 000000000..43a290ed4 --- /dev/null +++ b/app/src/main/res/drawable/bg_room_message_noble_7.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_rank.xml b/app/src/main/res/drawable/bg_room_rank.xml new file mode 100644 index 000000000..8c644b725 --- /dev/null +++ b/app/src/main/res/drawable/bg_room_rank.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_select_dialog.xml b/app/src/main/res/drawable/bg_room_select_dialog.xml new file mode 100644 index 000000000..50525780a --- /dev/null +++ b/app/src/main/res/drawable/bg_room_select_dialog.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_room_title_edit.xml b/app/src/main/res/drawable/bg_room_title_edit.xml new file mode 100644 index 000000000..510d50bb0 --- /dev/null +++ b/app/src/main/res/drawable/bg_room_title_edit.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_search_edit.xml b/app/src/main/res/drawable/bg_search_edit.xml new file mode 100644 index 000000000..54b411589 --- /dev/null +++ b/app/src/main/res/drawable/bg_search_edit.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_search_edit_main.xml b/app/src/main/res/drawable/bg_search_edit_main.xml new file mode 100644 index 000000000..6e3e2c240 --- /dev/null +++ b/app/src/main/res/drawable/bg_search_edit_main.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_shape_attention.xml b/app/src/main/res/drawable/bg_shape_attention.xml new file mode 100644 index 000000000..885a6f950 --- /dev/null +++ b/app/src/main/res/drawable/bg_shape_attention.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_shape_modify_info.xml b/app/src/main/res/drawable/bg_shape_modify_info.xml new file mode 100644 index 000000000..097b3ff33 --- /dev/null +++ b/app/src/main/res/drawable/bg_shape_modify_info.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_shape_modify_nick.xml b/app/src/main/res/drawable/bg_shape_modify_nick.xml new file mode 100644 index 000000000..f03fb3547 --- /dev/null +++ b/app/src/main/res/drawable/bg_shape_modify_nick.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_shape_send_msg.xml b/app/src/main/res/drawable/bg_shape_send_msg.xml new file mode 100644 index 000000000..ed81a2d7c --- /dev/null +++ b/app/src/main/res/drawable/bg_shape_send_msg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_sign_option.xml b/app/src/main/res/drawable/bg_sign_option.xml new file mode 100644 index 000000000..954e35f98 --- /dev/null +++ b/app/src/main/res/drawable/bg_sign_option.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_solid_car_send.xml b/app/src/main/res/drawable/bg_solid_car_send.xml new file mode 100644 index 000000000..f0ec34efd --- /dev/null +++ b/app/src/main/res/drawable/bg_solid_car_send.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_splash.xml b/app/src/main/res/drawable/bg_splash.xml new file mode 100644 index 000000000..661f27f42 --- /dev/null +++ b/app/src/main/res/drawable/bg_splash.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/bg_tab.xml b/app/src/main/res/drawable/bg_tab.xml new file mode 100644 index 000000000..4c2a6bad9 --- /dev/null +++ b/app/src/main/res/drawable/bg_tab.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_user_info_audio.xml b/app/src/main/res/drawable/bg_user_info_audio.xml new file mode 100644 index 000000000..598880fd0 --- /dev/null +++ b/app/src/main/res/drawable/bg_user_info_audio.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_user_info_dialog_bottom.xml b/app/src/main/res/drawable/bg_user_info_dialog_bottom.xml new file mode 100644 index 000000000..07ddbbda5 --- /dev/null +++ b/app/src/main/res/drawable/bg_user_info_dialog_bottom.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_user_info_dialog_top.xml b/app/src/main/res/drawable/bg_user_info_dialog_top.xml new file mode 100644 index 000000000..b80c733ee --- /dev/null +++ b/app/src/main/res/drawable/bg_user_info_dialog_top.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_view_half_radiu.xml b/app/src/main/res/drawable/bg_view_half_radiu.xml new file mode 100644 index 000000000..11d959e36 --- /dev/null +++ b/app/src/main/res/drawable/bg_view_half_radiu.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_bar.xml b/app/src/main/res/drawable/bg_voice_bar.xml new file mode 100644 index 000000000..136436047 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_bar.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_bar_no_data.xml b/app/src/main/res/drawable/bg_voice_bar_no_data.xml new file mode 100644 index 000000000..aa1706676 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_bar_no_data.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_card_change.xml b/app/src/main/res/drawable/bg_voice_card_change.xml new file mode 100644 index 000000000..9ebad8ec8 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_card_change.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_all.xml b/app/src/main/res/drawable/bg_voice_filter_gender_all.xml new file mode 100644 index 000000000..cc1c7cf90 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_all.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_all_normal.xml b/app/src/main/res/drawable/bg_voice_filter_gender_all_normal.xml new file mode 100644 index 000000000..c9aa66869 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_all_normal.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_all_selected.xml b/app/src/main/res/drawable/bg_voice_filter_gender_all_selected.xml new file mode 100644 index 000000000..b33ff62e9 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_all_selected.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_female.xml b/app/src/main/res/drawable/bg_voice_filter_gender_female.xml new file mode 100644 index 000000000..d27d039b4 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_female.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_female_normal.xml b/app/src/main/res/drawable/bg_voice_filter_gender_female_normal.xml new file mode 100644 index 000000000..228b631ef --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_female_normal.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_female_selected.xml b/app/src/main/res/drawable/bg_voice_filter_gender_female_selected.xml new file mode 100644 index 000000000..c0d865cab --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_female_selected.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_male.xml b/app/src/main/res/drawable/bg_voice_filter_gender_male.xml new file mode 100644 index 000000000..643b253aa --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_male.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_male_normal.xml b/app/src/main/res/drawable/bg_voice_filter_gender_male_normal.xml new file mode 100644 index 000000000..3ce8fedaa --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_male_normal.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_filter_gender_male_selected.xml b/app/src/main/res/drawable/bg_voice_filter_gender_male_selected.xml new file mode 100644 index 000000000..ae0f0446e --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_filter_gender_male_selected.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_im_msg_say_hi.xml b/app/src/main/res/drawable/bg_voice_im_msg_say_hi.xml new file mode 100644 index 000000000..e32b6633e --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_im_msg_say_hi.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_im_msg_say_hi_enable.xml b/app/src/main/res/drawable/bg_voice_im_msg_say_hi_enable.xml new file mode 100644 index 000000000..9f3066917 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_im_msg_say_hi_enable.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_im_msg_say_hi_normal.xml b/app/src/main/res/drawable/bg_voice_im_msg_say_hi_normal.xml new file mode 100644 index 000000000..11cfdbe92 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_im_msg_say_hi_normal.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_voice_re_recording.xml b/app/src/main/res/drawable/bg_voice_re_recording.xml new file mode 100644 index 000000000..d1e2d7831 --- /dev/null +++ b/app/src/main/res/drawable/bg_voice_re_recording.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_wallet_gold_list_while.xml b/app/src/main/res/drawable/bg_wallet_gold_list_while.xml new file mode 100644 index 000000000..465bf70f9 --- /dev/null +++ b/app/src/main/res/drawable/bg_wallet_gold_list_while.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_wallet_total.xml b/app/src/main/res/drawable/bg_wallet_total.xml new file mode 100644 index 000000000..59058383e --- /dev/null +++ b/app/src/main/res/drawable/bg_wallet_total.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_white_0_8.xml b/app/src/main/res/drawable/bg_white_0_8.xml new file mode 100644 index 000000000..59058383e --- /dev/null +++ b/app/src/main/res/drawable/bg_white_0_8.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_white_top_0_12.xml b/app/src/main/res/drawable/bg_white_top_0_12.xml new file mode 100644 index 000000000..45bbbc97b --- /dev/null +++ b/app/src/main/res/drawable/bg_white_top_0_12.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_white_top_0_8.xml b/app/src/main/res/drawable/bg_white_top_0_8.xml new file mode 100644 index 000000000..6d7deb8f0 --- /dev/null +++ b/app/src/main/res/drawable/bg_white_top_0_8.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bottom_line.xml b/app/src/main/res/drawable/bottom_line.xml new file mode 100644 index 000000000..84d9f3569 --- /dev/null +++ b/app/src/main/res/drawable/bottom_line.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/click_white_gray_selector.xml b/app/src/main/res/drawable/click_white_gray_selector.xml new file mode 100644 index 000000000..8984e991c --- /dev/null +++ b/app/src/main/res/drawable/click_white_gray_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/color_dialog_cancel_button_selector.xml b/app/src/main/res/drawable/color_dialog_cancel_button_selector.xml new file mode 100644 index 000000000..f4e3ac3f5 --- /dev/null +++ b/app/src/main/res/drawable/color_dialog_cancel_button_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/color_dialog_ok_button_selector.xml b/app/src/main/res/drawable/color_dialog_ok_button_selector.xml new file mode 100644 index 000000000..4ff649c7f --- /dev/null +++ b/app/src/main/res/drawable/color_dialog_ok_button_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/color_magic_dialog_item_selector.xml b/app/src/main/res/drawable/color_magic_dialog_item_selector.xml new file mode 100644 index 000000000..203c6eb98 --- /dev/null +++ b/app/src/main/res/drawable/color_magic_dialog_item_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/common_yellow_btn_bg.xml b/app/src/main/res/drawable/common_yellow_btn_bg.xml new file mode 100644 index 000000000..fbc4a3594 --- /dev/null +++ b/app/src/main/res/drawable/common_yellow_btn_bg.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dialog_background.xml b/app/src/main/res/drawable/dialog_background.xml new file mode 100644 index 000000000..5e331cc79 --- /dev/null +++ b/app/src/main/res/drawable/dialog_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dialog_btn_color.xml b/app/src/main/res/drawable/dialog_btn_color.xml new file mode 100644 index 000000000..6ea2f83b0 --- /dev/null +++ b/app/src/main/res/drawable/dialog_btn_color.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/divider_linear.xml b/app/src/main/res/drawable/divider_linear.xml new file mode 100644 index 000000000..b44f13630 --- /dev/null +++ b/app/src/main/res/drawable/divider_linear.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dots.xml b/app/src/main/res/drawable/dots.xml new file mode 100644 index 000000000..ad5c4a0e4 --- /dev/null +++ b/app/src/main/res/drawable/dots.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drawable_room_rank_progress_bar.xml b/app/src/main/res/drawable/drawable_room_rank_progress_bar.xml new file mode 100644 index 000000000..13e089b6e --- /dev/null +++ b/app/src/main/res/drawable/drawable_room_rank_progress_bar.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/explosion.xml b/app/src/main/res/drawable/explosion.xml new file mode 100644 index 000000000..6b64e5cf3 --- /dev/null +++ b/app/src/main/res/drawable/explosion.xml @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/feedback_point.xml b/app/src/main/res/drawable/feedback_point.xml new file mode 100644 index 000000000..1251a7c01 --- /dev/null +++ b/app/src/main/res/drawable/feedback_point.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/full_dialog_btn_bg.xml b/app/src/main/res/drawable/full_dialog_btn_bg.xml new file mode 100644 index 000000000..0ba2c515d --- /dev/null +++ b/app/src/main/res/drawable/full_dialog_btn_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/global_broadcast_notice_bg.xml b/app/src/main/res/drawable/global_broadcast_notice_bg.xml new file mode 100644 index 000000000..736e7ca3a --- /dev/null +++ b/app/src/main/res/drawable/global_broadcast_notice_bg.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/half_btn_bg.xml b/app/src/main/res/drawable/half_btn_bg.xml new file mode 100644 index 000000000..a1a04208b --- /dev/null +++ b/app/src/main/res/drawable/half_btn_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/half_inverse_btn_bg.xml b/app/src/main/res/drawable/half_inverse_btn_bg.xml new file mode 100644 index 000000000..cc3314a42 --- /dev/null +++ b/app/src/main/res/drawable/half_inverse_btn_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_customer_service.xml b/app/src/main/res/drawable/ic_customer_service.xml new file mode 100644 index 000000000..df1ef1892 --- /dev/null +++ b/app/src/main/res/drawable/ic_customer_service.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_room_voice_point.xml b/app/src/main/res/drawable/ic_room_voice_point.xml new file mode 100644 index 000000000..6b99db24d --- /dev/null +++ b/app/src/main/res/drawable/ic_room_voice_point.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/layer_list_bottom_gray_line.xml b/app/src/main/res/drawable/layer_list_bottom_gray_line.xml new file mode 100644 index 000000000..a46d05f04 --- /dev/null +++ b/app/src/main/res/drawable/layer_list_bottom_gray_line.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/living_icon_animation.xml b/app/src/main/res/drawable/living_icon_animation.xml new file mode 100644 index 000000000..feed263b1 --- /dev/null +++ b/app/src/main/res/drawable/living_icon_animation.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/living_icon_animation_black.xml b/app/src/main/res/drawable/living_icon_animation_black.xml new file mode 100644 index 000000000..d4fa68ebb --- /dev/null +++ b/app/src/main/res/drawable/living_icon_animation_black.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/loading_animated_drawable.xml b/app/src/main/res/drawable/loading_animated_drawable.xml new file mode 100644 index 000000000..7fdfcb9c5 --- /dev/null +++ b/app/src/main/res/drawable/loading_animated_drawable.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/loading_progress_animated_drawable.xml b/app/src/main/res/drawable/loading_progress_animated_drawable.xml new file mode 100644 index 000000000..9ec87f288 --- /dev/null +++ b/app/src/main/res/drawable/loading_progress_animated_drawable.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_tab_find_animation.xml b/app/src/main/res/drawable/main_tab_find_animation.xml new file mode 100644 index 000000000..3696f129a --- /dev/null +++ b/app/src/main/res/drawable/main_tab_find_animation.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_tab_game_animation.xml b/app/src/main/res/drawable/main_tab_game_animation.xml new file mode 100644 index 000000000..bc34c9306 --- /dev/null +++ b/app/src/main/res/drawable/main_tab_game_animation.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_tab_home_animation.xml b/app/src/main/res/drawable/main_tab_home_animation.xml new file mode 100644 index 000000000..b9c154435 --- /dev/null +++ b/app/src/main/res/drawable/main_tab_home_animation.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_tab_me_animation.xml b/app/src/main/res/drawable/main_tab_me_animation.xml new file mode 100644 index 000000000..b90487689 --- /dev/null +++ b/app/src/main/res/drawable/main_tab_me_animation.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/main_tab_msg_animation.xml b/app/src/main/res/drawable/main_tab_msg_animation.xml new file mode 100644 index 000000000..93cfa8cbd --- /dev/null +++ b/app/src/main/res/drawable/main_tab_msg_animation.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/music_voice_seekbar.xml b/app/src/main/res/drawable/music_voice_seekbar.xml new file mode 100644 index 000000000..aa6727510 --- /dev/null +++ b/app/src/main/res/drawable/music_voice_seekbar.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/pk_score_pb.xml b/app/src/main/res/drawable/pk_score_pb.xml new file mode 100644 index 000000000..8e42f615d --- /dev/null +++ b/app/src/main/res/drawable/pk_score_pb.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progress_drawable.xml b/app/src/main/res/drawable/progress_drawable.xml new file mode 100644 index 000000000..3037bff79 --- /dev/null +++ b/app/src/main/res/drawable/progress_drawable.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progress_monster_hp.xml b/app/src/main/res/drawable/progress_monster_hp.xml new file mode 100644 index 000000000..24682eeb2 --- /dev/null +++ b/app/src/main/res/drawable/progress_monster_hp.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_auction_price.xml b/app/src/main/res/drawable/selector_auction_price.xml new file mode 100644 index 000000000..8f08b7165 --- /dev/null +++ b/app/src/main/res/drawable/selector_auction_price.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bg_dialog_login_code_btn.xml b/app/src/main/res/drawable/selector_bg_dialog_login_code_btn.xml new file mode 100644 index 000000000..47c2ac678 --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_dialog_login_code_btn.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bg_splash_skip.xml b/app/src/main/res/drawable/selector_bg_splash_skip.xml new file mode 100644 index 000000000..b51c4944d --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_splash_skip.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_box_hint.xml b/app/src/main/res/drawable/selector_box_hint.xml new file mode 100644 index 000000000..1206071c6 --- /dev/null +++ b/app/src/main/res/drawable/selector_box_hint.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/selector_button_create_team.xml b/app/src/main/res/drawable/selector_button_create_team.xml new file mode 100644 index 000000000..5e9099752 --- /dev/null +++ b/app/src/main/res/drawable/selector_button_create_team.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_dialog_privacy_agreement_left_btn_bg.xml b/app/src/main/res/drawable/selector_dialog_privacy_agreement_left_btn_bg.xml new file mode 100644 index 000000000..090a90608 --- /dev/null +++ b/app/src/main/res/drawable/selector_dialog_privacy_agreement_left_btn_bg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/selector_dialog_privacy_agreement_right_btn_bg.xml b/app/src/main/res/drawable/selector_dialog_privacy_agreement_right_btn_bg.xml new file mode 100644 index 000000000..26733bd99 --- /dev/null +++ b/app/src/main/res/drawable/selector_dialog_privacy_agreement_right_btn_bg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/selector_filtrate_left.xml b/app/src/main/res/drawable/selector_filtrate_left.xml new file mode 100644 index 000000000..26dc8341b --- /dev/null +++ b/app/src/main/res/drawable/selector_filtrate_left.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_filtrate_right.xml b/app/src/main/res/drawable/selector_filtrate_right.xml new file mode 100644 index 000000000..ea4718437 --- /dev/null +++ b/app/src/main/res/drawable/selector_filtrate_right.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_gender_select_men.xml b/app/src/main/res/drawable/selector_gender_select_men.xml new file mode 100644 index 000000000..6bf3781e5 --- /dev/null +++ b/app/src/main/res/drawable/selector_gender_select_men.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_gender_select_men_padding_drawable.xml b/app/src/main/res/drawable/selector_gender_select_men_padding_drawable.xml new file mode 100644 index 000000000..a8f96957d --- /dev/null +++ b/app/src/main/res/drawable/selector_gender_select_men_padding_drawable.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_gender_select_women.xml b/app/src/main/res/drawable/selector_gender_select_women.xml new file mode 100644 index 000000000..235f38482 --- /dev/null +++ b/app/src/main/res/drawable/selector_gender_select_women.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_gender_select_women_padding_drawable.xml b/app/src/main/res/drawable/selector_gender_select_women_padding_drawable.xml new file mode 100644 index 000000000..b5fd48c9e --- /dev/null +++ b/app/src/main/res/drawable/selector_gender_select_women_padding_drawable.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_gift_quantity_confirm_btn.xml b/app/src/main/res/drawable/selector_gift_quantity_confirm_btn.xml new file mode 100644 index 000000000..8a0fc1e2f --- /dev/null +++ b/app/src/main/res/drawable/selector_gift_quantity_confirm_btn.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/selector_gold_price.xml b/app/src/main/res/drawable/selector_gold_price.xml new file mode 100644 index 000000000..ec5f95eda --- /dev/null +++ b/app/src/main/res/drawable/selector_gold_price.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_mv_error.xml b/app/src/main/res/drawable/selector_mv_error.xml new file mode 100644 index 000000000..fe9740e64 --- /dev/null +++ b/app/src/main/res/drawable/selector_mv_error.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_pk_select_people_mark.xml b/app/src/main/res/drawable/selector_pk_select_people_mark.xml new file mode 100644 index 000000000..38a720ca2 --- /dev/null +++ b/app/src/main/res/drawable/selector_pk_select_people_mark.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_radio_always_not_tips.xml b/app/src/main/res/drawable/selector_radio_always_not_tips.xml new file mode 100644 index 000000000..fc3940648 --- /dev/null +++ b/app/src/main/res/drawable/selector_radio_always_not_tips.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/selector_radio_btn_buy_unit.xml b/app/src/main/res/drawable/selector_radio_btn_buy_unit.xml new file mode 100644 index 000000000..02772f714 --- /dev/null +++ b/app/src/main/res/drawable/selector_radio_btn_buy_unit.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/selector_rank_list_btn.xml b/app/src/main/res/drawable/selector_rank_list_btn.xml new file mode 100644 index 000000000..d94c23ece --- /dev/null +++ b/app/src/main/res/drawable/selector_rank_list_btn.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_room_gift_item.xml b/app/src/main/res/drawable/selector_room_gift_item.xml new file mode 100644 index 000000000..248a1c729 --- /dev/null +++ b/app/src/main/res/drawable/selector_room_gift_item.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_select_team_member.xml b/app/src/main/res/drawable/selector_select_team_member.xml new file mode 100644 index 000000000..7d23bc6e0 --- /dev/null +++ b/app/src/main/res/drawable/selector_select_team_member.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_select_team_member_confirm.xml b/app/src/main/res/drawable/selector_select_team_member_confirm.xml new file mode 100644 index 000000000..da56c1196 --- /dev/null +++ b/app/src/main/res/drawable/selector_select_team_member_confirm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_share_music_check_box.xml b/app/src/main/res/drawable/selector_share_music_check_box.xml new file mode 100644 index 000000000..da42eb944 --- /dev/null +++ b/app/src/main/res/drawable/selector_share_music_check_box.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_text_color_white_333.xml b/app/src/main/res/drawable/selector_text_color_white_333.xml new file mode 100644 index 000000000..e808a5458 --- /dev/null +++ b/app/src/main/res/drawable/selector_text_color_white_333.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/selector_text_dialog_login_code_btn.xml b/app/src/main/res/drawable/selector_text_dialog_login_code_btn.xml new file mode 100644 index 000000000..979d993f1 --- /dev/null +++ b/app/src/main/res/drawable/selector_text_dialog_login_code_btn.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_05c7c7_to_57edc2.xml b/app/src/main/res/drawable/shape_05c7c7_to_57edc2.xml new file mode 100644 index 000000000..8c5d06a5b --- /dev/null +++ b/app/src/main/res/drawable/shape_05c7c7_to_57edc2.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_24d7a7.xml b/app/src/main/res/drawable/shape_24d7a7.xml new file mode 100644 index 000000000..92c7a83f2 --- /dev/null +++ b/app/src/main/res/drawable/shape_24d7a7.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_261213_15dp.xml b/app/src/main/res/drawable/shape_261213_15dp.xml new file mode 100644 index 000000000..667460e66 --- /dev/null +++ b/app/src/main/res/drawable/shape_261213_15dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_58559d.xml b/app/src/main/res/drawable/shape_58559d.xml new file mode 100644 index 000000000..468e33b2b --- /dev/null +++ b/app/src/main/res/drawable/shape_58559d.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_appcolor_corner.xml b/app/src/main/res/drawable/shape_appcolor_corner.xml new file mode 100644 index 000000000..27bd5d868 --- /dev/null +++ b/app/src/main/res/drawable/shape_appcolor_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_appcolor_radius_2dp.xml b/app/src/main/res/drawable/shape_appcolor_radius_2dp.xml new file mode 100644 index 000000000..00957279b --- /dev/null +++ b/app/src/main/res/drawable/shape_appcolor_radius_2dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_appcolor_right_20dp.xml b/app/src/main/res/drawable/shape_appcolor_right_20dp.xml new file mode 100644 index 000000000..b2c388be2 --- /dev/null +++ b/app/src/main/res/drawable/shape_appcolor_right_20dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_activity_timer.xml b/app/src/main/res/drawable/shape_bg_activity_timer.xml new file mode 100644 index 000000000..c02486324 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_activity_timer.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_add_attention.xml b/app/src/main/res/drawable/shape_bg_add_attention.xml new file mode 100644 index 000000000..737219411 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_add_attention.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_buy_key_input.xml b/app/src/main/res/drawable/shape_bg_buy_key_input.xml new file mode 100644 index 000000000..571976e63 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_buy_key_input.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_contact_indicator.xml b/app/src/main/res/drawable/shape_bg_contact_indicator.xml new file mode 100644 index 000000000..bb1d1d7d0 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_contact_indicator.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_contact_indicator_item.xml b/app/src/main/res/drawable/shape_bg_contact_indicator_item.xml new file mode 100644 index 000000000..dbb56992f --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_contact_indicator_item.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_dialog_gift_number.xml b/app/src/main/res/drawable/shape_bg_dialog_gift_number.xml new file mode 100644 index 000000000..9d76ccae8 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_dialog_gift_number.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_dialog_login_code.xml b/app/src/main/res/drawable/shape_bg_dialog_login_code.xml new file mode 100644 index 000000000..8cc2b352f --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_dialog_login_code.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_me_panel.xml b/app/src/main/res/drawable/shape_bg_me_panel.xml new file mode 100644 index 000000000..819a7c9ad --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_me_panel.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_of_mic_charm.xml b/app/src/main/res/drawable/shape_bg_of_mic_charm.xml new file mode 100644 index 000000000..729431c1d --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_of_mic_charm.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_pk_select_people_name.xml b/app/src/main/res/drawable/shape_bg_pk_select_people_name.xml new file mode 100644 index 000000000..9589a7f82 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_pk_select_people_name.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_replenish_status_false.xml b/app/src/main/res/drawable/shape_bg_replenish_status_false.xml new file mode 100644 index 000000000..8f2f5f206 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_replenish_status_false.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_replenish_status_ture.xml b/app/src/main/res/drawable/shape_bg_replenish_status_ture.xml new file mode 100644 index 000000000..a30d4401c --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_replenish_status_ture.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_room_tag.xml b/app/src/main/res/drawable/shape_bg_room_tag.xml new file mode 100644 index 000000000..1c011dc38 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_room_tag.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_sign_reward_number_blue.xml b/app/src/main/res/drawable/shape_bg_sign_reward_number_blue.xml new file mode 100644 index 000000000..61e7f63aa --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_sign_reward_number_blue.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_sign_reward_number_gray.xml b/app/src/main/res/drawable/shape_bg_sign_reward_number_gray.xml new file mode 100644 index 000000000..a6adfa3ed --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_sign_reward_number_gray.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_black_solid_round.xml b/app/src/main/res/drawable/shape_black_solid_round.xml new file mode 100644 index 000000000..2fe106270 --- /dev/null +++ b/app/src/main/res/drawable/shape_black_solid_round.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_blue_solid_round.xml b/app/src/main/res/drawable/shape_blue_solid_round.xml new file mode 100644 index 000000000..3fdfe931b --- /dev/null +++ b/app/src/main/res/drawable/shape_blue_solid_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_charm_level_up_round_red_solid.xml b/app/src/main/res/drawable/shape_charm_level_up_round_red_solid.xml new file mode 100644 index 000000000..cd54e4061 --- /dev/null +++ b/app/src/main/res/drawable/shape_charm_level_up_round_red_solid.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_chat_hall_time_tip.xml b/app/src/main/res/drawable/shape_chat_hall_time_tip.xml new file mode 100644 index 000000000..f06c93b32 --- /dev/null +++ b/app/src/main/res/drawable/shape_chat_hall_time_tip.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circle_gray_small.xml b/app/src/main/res/drawable/shape_circle_gray_small.xml new file mode 100644 index 000000000..be04e22a3 --- /dev/null +++ b/app/src/main/res/drawable/shape_circle_gray_small.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circle_red_small.xml b/app/src/main/res/drawable/shape_circle_red_small.xml new file mode 100644 index 000000000..b753d15d6 --- /dev/null +++ b/app/src/main/res/drawable/shape_circle_red_small.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circle_white33.xml b/app/src/main/res/drawable/shape_circle_white33.xml new file mode 100644 index 000000000..45c43f82e --- /dev/null +++ b/app/src/main/res/drawable/shape_circle_white33.xml @@ -0,0 +1,6 @@ + + + + / + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_constellation_solid_round.xml b/app/src/main/res/drawable/shape_constellation_solid_round.xml new file mode 100644 index 000000000..2707a233e --- /dev/null +++ b/app/src/main/res/drawable/shape_constellation_solid_round.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dbdbdb_corner.xml b/app/src/main/res/drawable/shape_dbdbdb_corner.xml new file mode 100644 index 000000000..c7ddac6e6 --- /dev/null +++ b/app/src/main/res/drawable/shape_dbdbdb_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_delete_team_background.xml b/app/src/main/res/drawable/shape_delete_team_background.xml new file mode 100644 index 000000000..3a2bf932c --- /dev/null +++ b/app/src/main/res/drawable/shape_delete_team_background.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog_btn_white_bg.xml b/app/src/main/res/drawable/shape_dialog_btn_white_bg.xml new file mode 100644 index 000000000..d0ace5f08 --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog_btn_white_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog_btn_white_bg_hl.xml b/app/src/main/res/drawable/shape_dialog_btn_white_bg_hl.xml new file mode 100644 index 000000000..61e431df5 --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog_btn_white_bg_hl.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog_privacy_agreement_bg.xml b/app/src/main/res/drawable/shape_dialog_privacy_agreement_bg.xml new file mode 100644 index 000000000..3de4e815f --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog_privacy_agreement_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f0f0f0_corner.xml b/app/src/main/res/drawable/shape_f0f0f0_corner.xml new file mode 100644 index 000000000..7fcc37069 --- /dev/null +++ b/app/src/main/res/drawable/shape_f0f0f0_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f5f5f5_corner.xml b/app/src/main/res/drawable/shape_f5f5f5_corner.xml new file mode 100644 index 000000000..feece1d1b --- /dev/null +++ b/app/src/main/res/drawable/shape_f5f5f5_corner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_fc6c6f_to_ff9169.xml b/app/src/main/res/drawable/shape_fc6c6f_to_ff9169.xml new file mode 100644 index 000000000..bd8cd389c --- /dev/null +++ b/app/src/main/res/drawable/shape_fc6c6f_to_ff9169.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_fef5ed_19.xml b/app/src/main/res/drawable/shape_fef5ed_19.xml new file mode 100644 index 000000000..58ec7e309 --- /dev/null +++ b/app/src/main/res/drawable/shape_fef5ed_19.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_ff4362_20dp.xml b/app/src/main/res/drawable/shape_ff4362_20dp.xml new file mode 100644 index 000000000..2e8296e09 --- /dev/null +++ b/app/src/main/res/drawable/shape_ff4362_20dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_ff723e_right_20dp.xml b/app/src/main/res/drawable/shape_ff723e_right_20dp.xml new file mode 100644 index 000000000..a87d0d69e --- /dev/null +++ b/app/src/main/res/drawable/shape_ff723e_right_20dp.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_ff894f_round.xml b/app/src/main/res/drawable/shape_ff894f_round.xml new file mode 100644 index 000000000..a805044ef --- /dev/null +++ b/app/src/main/res/drawable/shape_ff894f_round.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_ffe80c_15dp.xml b/app/src/main/res/drawable/shape_ffe80c_15dp.xml new file mode 100644 index 000000000..86a00e8c6 --- /dev/null +++ b/app/src/main/res/drawable/shape_ffe80c_15dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_filtrate_left.xml b/app/src/main/res/drawable/shape_filtrate_left.xml new file mode 100644 index 000000000..4a55eca64 --- /dev/null +++ b/app/src/main/res/drawable/shape_filtrate_left.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_filtrate_mid_noselect.xml b/app/src/main/res/drawable/shape_filtrate_mid_noselect.xml new file mode 100644 index 000000000..b1440963a --- /dev/null +++ b/app/src/main/res/drawable/shape_filtrate_mid_noselect.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_filtrate_right.xml b/app/src/main/res/drawable/shape_filtrate_right.xml new file mode 100644 index 000000000..9ff039fea --- /dev/null +++ b/app/src/main/res/drawable/shape_filtrate_right.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_filtrate_right_noselect.xml b/app/src/main/res/drawable/shape_filtrate_right_noselect.xml new file mode 100644 index 000000000..9db09055b --- /dev/null +++ b/app/src/main/res/drawable/shape_filtrate_right_noselect.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_find_top_item_bg.xml b/app/src/main/res/drawable/shape_find_top_item_bg.xml new file mode 100644 index 000000000..91ffc54d9 --- /dev/null +++ b/app/src/main/res/drawable/shape_find_top_item_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_floating_live_mini_view.xml b/app/src/main/res/drawable/shape_floating_live_mini_view.xml new file mode 100644 index 000000000..2d8378c40 --- /dev/null +++ b/app/src/main/res/drawable/shape_floating_live_mini_view.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_gift_chose.xml b/app/src/main/res/drawable/shape_gift_chose.xml new file mode 100644 index 000000000..8cd4fbb3e --- /dev/null +++ b/app/src/main/res/drawable/shape_gift_chose.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_gift_dialog_room_owner_position.xml b/app/src/main/res/drawable/shape_gift_dialog_room_owner_position.xml new file mode 100644 index 000000000..619f7705e --- /dev/null +++ b/app/src/main/res/drawable/shape_gift_dialog_room_owner_position.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_gift_item_select.xml b/app/src/main/res/drawable/shape_gift_item_select.xml new file mode 100644 index 000000000..3e9372fb7 --- /dev/null +++ b/app/src/main/res/drawable/shape_gift_item_select.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_gift_tran.xml b/app/src/main/res/drawable/shape_gift_tran.xml new file mode 100644 index 000000000..69edda790 --- /dev/null +++ b/app/src/main/res/drawable/shape_gift_tran.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_gold_input_false.xml b/app/src/main/res/drawable/shape_gold_input_false.xml new file mode 100644 index 000000000..ee1a75f7e --- /dev/null +++ b/app/src/main/res/drawable/shape_gold_input_false.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_gold_input_true.xml b/app/src/main/res/drawable/shape_gold_input_true.xml new file mode 100644 index 000000000..e5ea0796d --- /dev/null +++ b/app/src/main/res/drawable/shape_gold_input_true.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_gray_round.xml b/app/src/main/res/drawable/shape_gray_round.xml new file mode 100644 index 000000000..de60cb10b --- /dev/null +++ b/app/src/main/res/drawable/shape_gray_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_green_round.xml b/app/src/main/res/drawable/shape_green_round.xml new file mode 100644 index 000000000..db306af37 --- /dev/null +++ b/app/src/main/res/drawable/shape_green_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_btn_bg.xml b/app/src/main/res/drawable/shape_half_btn_bg.xml new file mode 100644 index 000000000..7399dd7fa --- /dev/null +++ b/app/src/main/res/drawable/shape_half_btn_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_btn_bg_disabled.xml b/app/src/main/res/drawable/shape_half_btn_bg_disabled.xml new file mode 100644 index 000000000..4b8a760d5 --- /dev/null +++ b/app/src/main/res/drawable/shape_half_btn_bg_disabled.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_btn_bg_hl.xml b/app/src/main/res/drawable/shape_half_btn_bg_hl.xml new file mode 100644 index 000000000..6b5485cd5 --- /dev/null +++ b/app/src/main/res/drawable/shape_half_btn_bg_hl.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_inverse_btn_bg.xml b/app/src/main/res/drawable/shape_half_inverse_btn_bg.xml new file mode 100644 index 000000000..e49f84c9c --- /dev/null +++ b/app/src/main/res/drawable/shape_half_inverse_btn_bg.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_inverse_btn_bg_disabled.xml b/app/src/main/res/drawable/shape_half_inverse_btn_bg_disabled.xml new file mode 100644 index 000000000..4b8a760d5 --- /dev/null +++ b/app/src/main/res/drawable/shape_half_inverse_btn_bg_disabled.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_half_inverse_btn_bg_hl.xml b/app/src/main/res/drawable/shape_half_inverse_btn_bg_hl.xml new file mode 100644 index 000000000..ffe68a1cf --- /dev/null +++ b/app/src/main/res/drawable/shape_half_inverse_btn_bg_hl.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_home_hall_msg_bg_left.xml b/app/src/main/res/drawable/shape_home_hall_msg_bg_left.xml new file mode 100644 index 000000000..07107a759 --- /dev/null +++ b/app/src/main/res/drawable/shape_home_hall_msg_bg_left.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_home_hall_msg_bg_right.xml b/app/src/main/res/drawable/shape_home_hall_msg_bg_right.xml new file mode 100644 index 000000000..5bfb154d6 --- /dev/null +++ b/app/src/main/res/drawable/shape_home_hall_msg_bg_right.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_home_hall_new_ait_tip_bg.xml b/app/src/main/res/drawable/shape_home_hall_new_ait_tip_bg.xml new file mode 100644 index 000000000..7d8974100 --- /dev/null +++ b/app/src/main/res/drawable/shape_home_hall_new_ait_tip_bg.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_home_load_more_bg.xml b/app/src/main/res/drawable/shape_home_load_more_bg.xml new file mode 100644 index 000000000..95665baa2 --- /dev/null +++ b/app/src/main/res/drawable/shape_home_load_more_bg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_indicator_present_invisible.xml b/app/src/main/res/drawable/shape_indicator_present_invisible.xml new file mode 100644 index 000000000..8711f130b --- /dev/null +++ b/app/src/main/res/drawable/shape_indicator_present_invisible.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_indicator_present_visible.xml b/app/src/main/res/drawable/shape_indicator_present_visible.xml new file mode 100644 index 000000000..2a449ec80 --- /dev/null +++ b/app/src/main/res/drawable/shape_indicator_present_visible.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_input_dialog_bg.xml b/app/src/main/res/drawable/shape_input_dialog_bg.xml new file mode 100644 index 000000000..f6e10a69e --- /dev/null +++ b/app/src/main/res/drawable/shape_input_dialog_bg.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_item_room_online_member.xml b/app/src/main/res/drawable/shape_item_room_online_member.xml new file mode 100644 index 000000000..bcf7642bc --- /dev/null +++ b/app/src/main/res/drawable/shape_item_room_online_member.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_ktv_dialog_bg.xml b/app/src/main/res/drawable/shape_ktv_dialog_bg.xml new file mode 100644 index 000000000..b3fb883d2 --- /dev/null +++ b/app/src/main/res/drawable/shape_ktv_dialog_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_level_up_dialog_bg.xml b/app/src/main/res/drawable/shape_level_up_dialog_bg.xml new file mode 100644 index 000000000..927435b29 --- /dev/null +++ b/app/src/main/res/drawable/shape_level_up_dialog_bg.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_level_up_round_yellow_solid.xml b/app/src/main/res/drawable/shape_level_up_round_yellow_solid.xml new file mode 100644 index 000000000..901da526e --- /dev/null +++ b/app/src/main/res/drawable/shape_level_up_round_yellow_solid.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_mini_world_main_item_mask.xml b/app/src/main/res/drawable/shape_mini_world_main_item_mask.xml new file mode 100644 index 000000000..5a25a72b0 --- /dev/null +++ b/app/src/main/res/drawable/shape_mini_world_main_item_mask.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_monster_hunting_reward_value.xml b/app/src/main/res/drawable/shape_monster_hunting_reward_value.xml new file mode 100644 index 000000000..21968164c --- /dev/null +++ b/app/src/main/res/drawable/shape_monster_hunting_reward_value.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_monster_reward_border.xml b/app/src/main/res/drawable/shape_monster_reward_border.xml new file mode 100644 index 000000000..85c200321 --- /dev/null +++ b/app/src/main/res/drawable/shape_monster_reward_border.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_monster_reward_duration.xml b/app/src/main/res/drawable/shape_monster_reward_duration.xml new file mode 100644 index 000000000..1022876ec --- /dev/null +++ b/app/src/main/res/drawable/shape_monster_reward_duration.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_my_home_page_left.xml b/app/src/main/res/drawable/shape_my_home_page_left.xml new file mode 100644 index 000000000..75c3d8c1c --- /dev/null +++ b/app/src/main/res/drawable/shape_my_home_page_left.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_online_noble_bg_name.xml b/app/src/main/res/drawable/shape_online_noble_bg_name.xml new file mode 100644 index 000000000..c3890e7ed --- /dev/null +++ b/app/src/main/res/drawable/shape_online_noble_bg_name.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_orainge_solid_round.xml b/app/src/main/res/drawable/shape_orainge_solid_round.xml new file mode 100644 index 000000000..1cb3d075c --- /dev/null +++ b/app/src/main/res/drawable/shape_orainge_solid_round.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pink_solid_round.xml b/app/src/main/res/drawable/shape_pink_solid_round.xml new file mode 100644 index 000000000..bd4220cbc --- /dev/null +++ b/app/src/main/res/drawable/shape_pink_solid_round.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_join_blue_team_btn.xml b/app/src/main/res/drawable/shape_pk_join_blue_team_btn.xml new file mode 100644 index 000000000..521602902 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_join_blue_team_btn.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_join_blue_team_mark.xml b/app/src/main/res/drawable/shape_pk_join_blue_team_mark.xml new file mode 100644 index 000000000..521602902 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_join_blue_team_mark.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_join_red_team_btn.xml b/app/src/main/res/drawable/shape_pk_join_red_team_btn.xml new file mode 100644 index 000000000..5dd8aec08 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_join_red_team_btn.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_join_red_team_mark.xml b/app/src/main/res/drawable/shape_pk_join_red_team_mark.xml new file mode 100644 index 000000000..7a17dbb3a --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_join_red_team_mark.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_mic_queue_dialog_bg.xml b/app/src/main/res/drawable/shape_pk_mic_queue_dialog_bg.xml new file mode 100644 index 000000000..1d71bda9b --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_mic_queue_dialog_bg.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_mic_queue_mark_blue.xml b/app/src/main/res/drawable/shape_pk_mic_queue_mark_blue.xml new file mode 100644 index 000000000..168a10bb3 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_mic_queue_mark_blue.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_mic_queue_mark_red.xml b/app/src/main/res/drawable/shape_pk_mic_queue_mark_red.xml new file mode 100644 index 000000000..564981982 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_mic_queue_mark_red.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pk_record_round_5dp.xml b/app/src/main/res/drawable/shape_pk_record_round_5dp.xml new file mode 100644 index 000000000..eca7da5c9 --- /dev/null +++ b/app/src/main/res/drawable/shape_pk_record_round_5dp.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pm_point.xml b/app/src/main/res/drawable/shape_pm_point.xml new file mode 100644 index 000000000..468b8c16e --- /dev/null +++ b/app/src/main/res/drawable/shape_pm_point.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_rect_15radius_ff4362.xml b/app/src/main/res/drawable/shape_rect_15radius_ff4362.xml new file mode 100644 index 000000000..d9e34c688 --- /dev/null +++ b/app/src/main/res/drawable/shape_rect_15radius_ff4362.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_red_ff7162_corner.xml b/app/src/main/res/drawable/shape_red_ff7162_corner.xml new file mode 100644 index 000000000..52ab0a2aa --- /dev/null +++ b/app/src/main/res/drawable/shape_red_ff7162_corner.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_bg_send.xml b/app/src/main/res/drawable/shape_room_bg_send.xml new file mode 100644 index 000000000..19403da54 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_bg_send.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_category_selected.xml b/app/src/main/res/drawable/shape_room_category_selected.xml new file mode 100644 index 000000000..7b73dce40 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_category_selected.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_category_unselected.xml b/app/src/main/res/drawable/shape_room_category_unselected.xml new file mode 100644 index 000000000..cd37a04ae --- /dev/null +++ b/app/src/main/res/drawable/shape_room_category_unselected.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_finish_btn_solid_round.xml b/app/src/main/res/drawable/shape_room_finish_btn_solid_round.xml new file mode 100644 index 000000000..5b4e98761 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_finish_btn_solid_round.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_message_bg.xml b/app/src/main/res/drawable/shape_room_message_bg.xml new file mode 100644 index 000000000..23d4ccf6f --- /dev/null +++ b/app/src/main/res/drawable/shape_room_message_bg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_music_bg.xml b/app/src/main/res/drawable/shape_room_music_bg.xml new file mode 100644 index 000000000..6c9eb95c5 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_music_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_avatar_default_green.xml b/app/src/main/res/drawable/shape_room_rank_avatar_default_green.xml new file mode 100644 index 000000000..adce7a7d7 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_avatar_default_green.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_avatar_default_pink.xml b/app/src/main/res/drawable/shape_room_rank_avatar_default_pink.xml new file mode 100644 index 000000000..f263519c4 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_avatar_default_pink.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_avatar_default_purple.xml b/app/src/main/res/drawable/shape_room_rank_avatar_default_purple.xml new file mode 100644 index 000000000..36ed405b0 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_avatar_default_purple.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_room_owner_info.xml b/app/src/main/res/drawable/shape_room_rank_room_owner_info.xml new file mode 100644 index 000000000..2bccc9f0b --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_room_owner_info.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_tab_tag_normal.xml b/app/src/main/res/drawable/shape_room_rank_tab_tag_normal.xml new file mode 100644 index 000000000..40e4b64a6 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_tab_tag_normal.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_room_rank_tab_tag_selected.xml b/app/src/main/res/drawable/shape_room_rank_tab_tag_selected.xml new file mode 100644 index 000000000..2aaaed909 --- /dev/null +++ b/app/src/main/res/drawable/shape_room_rank_tab_tag_selected.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_round_rectangle_lucky_money.xml b/app/src/main/res/drawable/shape_round_rectangle_lucky_money.xml new file mode 100644 index 000000000..090f93ff8 --- /dev/null +++ b/app/src/main/res/drawable/shape_round_rectangle_lucky_money.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_gray_solid.xml b/app/src/main/res/drawable/shape_semi_round_gray_solid.xml new file mode 100644 index 000000000..3284adc74 --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_gray_solid.xml @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_gray_solid_empty.xml b/app/src/main/res/drawable/shape_semi_round_gray_solid_empty.xml new file mode 100644 index 000000000..e85b4e233 --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_gray_solid_empty.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_gray_un_solid.xml b/app/src/main/res/drawable/shape_semi_round_gray_un_solid.xml new file mode 100644 index 000000000..a6b249d5a --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_gray_un_solid.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_grey_e5_solid.xml b/app/src/main/res/drawable/shape_semi_round_grey_e5_solid.xml new file mode 100644 index 000000000..dcd8222b1 --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_grey_e5_solid.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_grey_light_solid.xml b/app/src/main/res/drawable/shape_semi_round_grey_light_solid.xml new file mode 100644 index 000000000..ad8c65cef --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_grey_light_solid.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_tranyellow_solid.xml b/app/src/main/res/drawable/shape_semi_round_tranyellow_solid.xml new file mode 100644 index 000000000..bdf1a9cdd --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_tranyellow_solid.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_semi_round_white_solid.xml b/app/src/main/res/drawable/shape_semi_round_white_solid.xml new file mode 100644 index 000000000..d8437316e --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_white_solid.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_white_solid_black_stroke.xml b/app/src/main/res/drawable/shape_semi_round_white_solid_black_stroke.xml new file mode 100644 index 000000000..f38faf96b --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_white_solid_black_stroke.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_white_solid_yellow_stroke.xml b/app/src/main/res/drawable/shape_semi_round_white_solid_yellow_stroke.xml new file mode 100644 index 000000000..e85b4e233 --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_white_solid_yellow_stroke.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_semi_round_yellow_solid.xml b/app/src/main/res/drawable/shape_semi_round_yellow_solid.xml new file mode 100644 index 000000000..bf3908572 --- /dev/null +++ b/app/src/main/res/drawable/shape_semi_round_yellow_solid.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_solid_appcolor_left_20dp.xml b/app/src/main/res/drawable/shape_solid_appcolor_left_20dp.xml new file mode 100644 index 000000000..ea9c22c7c --- /dev/null +++ b/app/src/main/res/drawable/shape_solid_appcolor_left_20dp.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_stroke_appcolor_15dp.xml b/app/src/main/res/drawable/shape_stroke_appcolor_15dp.xml new file mode 100644 index 000000000..090060f8c --- /dev/null +++ b/app/src/main/res/drawable/shape_stroke_appcolor_15dp.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_stroke_appcolor_left_20dp.xml b/app/src/main/res/drawable/shape_stroke_appcolor_left_20dp.xml new file mode 100644 index 000000000..c55a7ee80 --- /dev/null +++ b/app/src/main/res/drawable/shape_stroke_appcolor_left_20dp.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_stroke_e6e6e6_5radius_white.xml b/app/src/main/res/drawable/shape_stroke_e6e6e6_5radius_white.xml new file mode 100644 index 000000000..346b33420 --- /dev/null +++ b/app/src/main/res/drawable/shape_stroke_e6e6e6_5radius_white.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_stroke_ff723e_left_20dp.xml b/app/src/main/res/drawable/shape_stroke_ff723e_left_20dp.xml new file mode 100644 index 000000000..b948b4165 --- /dev/null +++ b/app/src/main/res/drawable/shape_stroke_ff723e_left_20dp.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_wallet_red_pack_invited_num.xml b/app/src/main/res/drawable/shape_wallet_red_pack_invited_num.xml new file mode 100644 index 000000000..9a3cc18fe --- /dev/null +++ b/app/src/main/res/drawable/shape_wallet_red_pack_invited_num.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_wallet_red_pack_reward.xml b/app/src/main/res/drawable/shape_wallet_red_pack_reward.xml new file mode 100644 index 000000000..3f5f37dd7 --- /dev/null +++ b/app/src/main/res/drawable/shape_wallet_red_pack_reward.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_20dp_round.xml b/app/src/main/res/drawable/shape_white_20dp_round.xml new file mode 100644 index 000000000..654885d88 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_20dp_round.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_alpha_10.xml b/app/src/main/res/drawable/shape_white_alpha_10.xml new file mode 100644 index 000000000..baa466572 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_alpha_10.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_corner_8dp.xml b/app/src/main/res/drawable/shape_white_corner_8dp.xml new file mode 100644 index 000000000..67b042cff --- /dev/null +++ b/app/src/main/res/drawable/shape_white_corner_8dp.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_solid_round.xml b/app/src/main/res/drawable/shape_white_solid_round.xml new file mode 100644 index 000000000..4b00777b2 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_solid_round.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_stroke.xml b/app/src/main/res/drawable/shape_white_stroke.xml new file mode 100644 index 000000000..55fb48fda --- /dev/null +++ b/app/src/main/res/drawable/shape_white_stroke.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_stroke_2dp.xml b/app/src/main/res/drawable/shape_white_stroke_2dp.xml new file mode 100644 index 000000000..c5d52c6b7 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_stroke_2dp.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_top.xml b/app/src/main/res/drawable/shape_white_top.xml new file mode 100644 index 000000000..bcceff83b --- /dev/null +++ b/app/src/main/res/drawable/shape_white_top.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/slt_btn_give.xml b/app/src/main/res/drawable/slt_btn_give.xml new file mode 100644 index 000000000..af6291254 --- /dev/null +++ b/app/src/main/res/drawable/slt_btn_give.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/toast_bg.xml b/app/src/main/res/drawable/toast_bg.xml new file mode 100644 index 000000000..02e10c7e5 --- /dev/null +++ b/app/src/main/res/drawable/toast_bg.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/triangle_bottom.xml b/app/src/main/res/drawable/triangle_bottom.xml new file mode 100644 index 000000000..28e6855dd --- /dev/null +++ b/app/src/main/res/drawable/triangle_bottom.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/triangle_top.xml b/app/src/main/res/drawable/triangle_top.xml new file mode 100644 index 000000000..e80b4ebf5 --- /dev/null +++ b/app/src/main/res/drawable/triangle_top.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/wall_gold_charge.xml b/app/src/main/res/drawable/wall_gold_charge.xml new file mode 100644 index 000000000..f5cd8ca83 --- /dev/null +++ b/app/src/main/res/drawable/wall_gold_charge.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/wall_gold_charge_normal.xml b/app/src/main/res/drawable/wall_gold_charge_normal.xml new file mode 100644 index 000000000..dbb56992f --- /dev/null +++ b/app/src/main/res/drawable/wall_gold_charge_normal.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/wall_gold_charge_pressed.xml b/app/src/main/res/drawable/wall_gold_charge_pressed.xml new file mode 100644 index 000000000..82878a452 --- /dev/null +++ b/app/src/main/res/drawable/wall_gold_charge_pressed.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/withdraw_selector.xml b/app/src/main/res/drawable/withdraw_selector.xml new file mode 100644 index 000000000..5685dc4a6 --- /dev/null +++ b/app/src/main/res/drawable/withdraw_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/yw_1222_0670.jpg b/app/src/main/res/drawable/yw_1222_0670.jpg new file mode 100644 index 000000000..79c260608 Binary files /dev/null and b/app/src/main/res/drawable/yw_1222_0670.jpg differ diff --git a/app/src/main/res/font/din_bold.ttf b/app/src/main/res/font/din_bold.ttf new file mode 100644 index 000000000..db60385f3 Binary files /dev/null and b/app/src/main/res/font/din_bold.ttf differ diff --git a/app/src/main/res/layout/act_community_notice.xml b/app/src/main/res/layout/act_community_notice.xml new file mode 100644 index 000000000..df6c91328 --- /dev/null +++ b/app/src/main/res/layout/act_community_notice.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/act_friend_list.xml b/app/src/main/res/layout/act_friend_list.xml new file mode 100644 index 000000000..e721d18d8 --- /dev/null +++ b/app/src/main/res/layout/act_friend_list.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml new file mode 100644 index 000000000..d66fe20ee --- /dev/null +++ b/app/src/main/res/layout/activity_about.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_add_team_member.xml b/app/src/main/res/layout/activity_add_team_member.xml new file mode 100644 index 000000000..a6c57765c --- /dev/null +++ b/app/src/main/res/layout/activity_add_team_member.xml @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +