Improve detail scene
This commit is contained in:
1 parent
a01e43ea95
commit
3f6d3ea21c
47 files changed
+1647
-89
No files matched your search
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.animation;
|
||||
|
||||
import android.animation.TimeInterpolator;
|
||||
|
||||
public class DurationInterpolator implements TimeInterpolator {
|
||||
|
||||
private float mDuration;
|
||||
|
||||
public DurationInterpolator(float duration) {
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getInterpolation(float input) {
|
||||
if (input > mDuration) {
|
||||
return (input - mDuration) / (1 - mDuration);
|
||||
} else {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,18 @@ public class EhImageKeyFactory {
|
||||
public static String getThumbKey(int gid) {
|
||||
return "thumb:" + gid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index start from 0
|
||||
*/
|
||||
public static String getNormalPreviewKey(int gid, int index) {
|
||||
return "preview:normal:" + gid + ":" + index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index start from 0
|
||||
*/
|
||||
public static String getLargePreviewKey(int gid, int index) {
|
||||
return "preview:large:" + gid + ":" + index;
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,9 @@ package com.hippo.ehviewer.client;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Process;
|
||||
|
||||
import com.hippo.ehviewer.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.PreviewSet;
|
||||
import com.hippo.ehviewer.network.EhOkHttpClient;
|
||||
import com.hippo.network.ResponseCodeException;
|
||||
import com.hippo.util.PriorityThreadFactory;
|
||||
@@ -426,6 +427,10 @@ public final class EhClient {
|
||||
gd.tags = parser.tags;
|
||||
gd.comments = parser.comments;
|
||||
gd.previewPageCount = parser.previewPageCount;
|
||||
gd.previewSetArray = new PreviewSet[gd.previewPageCount];
|
||||
gd.previewSetArray[0] = parser.previewSet;
|
||||
gd.previewSetArray[0].setStartIndex(0);
|
||||
gd.previewSetArray[0].setGid(gd.gid);
|
||||
|
||||
return gd;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.ehviewer.data.Comment;
|
||||
import com.hippo.ehviewer.data.TagGroup;
|
||||
import com.hippo.ehviewer.client.data.Comment;
|
||||
import com.hippo.ehviewer.client.data.LargePreviewSet;
|
||||
import com.hippo.ehviewer.client.data.NormalPreviewSet;
|
||||
import com.hippo.ehviewer.client.data.PreviewSet;
|
||||
import com.hippo.ehviewer.client.data.TagGroup;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.Utils;
|
||||
@@ -52,6 +55,7 @@ public class GalleryDetailParser {
|
||||
public static final int REQUEST_DETAIL = 0x1;
|
||||
public static final int REQUEST_TAG = 0x2;
|
||||
public static final int REQUEST_PREVIEW_INFO = 0x4;
|
||||
public static final int REQUEST_PREVIEW = 0x8;
|
||||
public static final int REQUEST_COMMENT = 0x10;
|
||||
|
||||
private static final CommentSort COMMENT_SORTER = new CommentSort();
|
||||
@@ -84,6 +88,8 @@ public class GalleryDetailParser {
|
||||
|
||||
public int previewPageCount;
|
||||
|
||||
public PreviewSet previewSet;
|
||||
|
||||
private String sortOut(String str) {
|
||||
// Avoid null
|
||||
if (str == null) {
|
||||
@@ -104,6 +110,36 @@ public class GalleryDetailParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseNormalPreview(String body) {
|
||||
Pattern p = Pattern.compile("<div[^<>]*class=\"gdtm\"[^<>]*><div[^<>]*width:(\\d+)[^<>]*height:(\\d+)[^<>]*\\((.+?)\\)[^<>]*-(\\d+)px[^<>]*><a[^<>]*href=\"(.+?)\"[^<>]*>");
|
||||
Matcher m = p.matcher(body);
|
||||
NormalPreviewSet normalPreviewSet = new NormalPreviewSet();
|
||||
while (m.find()) {
|
||||
normalPreviewSet.addItem(m.group(3), Integer.parseInt(m.group(4)), 0,
|
||||
Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),
|
||||
m.group(5));
|
||||
}
|
||||
previewSet = normalPreviewSet;
|
||||
}
|
||||
|
||||
private void parseLargePreview(String body) {
|
||||
Pattern p = Pattern.compile("<div class=\"gdtl\".+?<a href=\"(.+?)\"><img.+?src=\"(.+?)\"");
|
||||
Matcher m = p.matcher(body);
|
||||
LargePreviewSet largePreviewSet = new LargePreviewSet();
|
||||
while (m.find()) {
|
||||
largePreviewSet.addItem(m.group(2), m.group(1));
|
||||
}
|
||||
previewSet = largePreviewSet;
|
||||
}
|
||||
|
||||
private void parsePreview(String body) {
|
||||
if (body.contains("<div class=\"gdtm\"")) {
|
||||
parseNormalPreview(body);
|
||||
} else {
|
||||
parseLargePreview(body);
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String body, int request) throws EhException {
|
||||
Pattern p;
|
||||
Matcher m;
|
||||
@@ -240,6 +276,11 @@ public class GalleryDetailParser {
|
||||
}
|
||||
}
|
||||
|
||||
// Get preview
|
||||
if ((request & REQUEST_PREVIEW_INFO) != 0) {
|
||||
parsePreview(body);
|
||||
}
|
||||
|
||||
// Get comment
|
||||
if ((request & REQUEST_COMMENT) != 0) {
|
||||
p = Pattern.compile("<div class=\"c3\">Posted on ([^<>]+) by: <a[^<>]+>([^<>]+)</a>.+?<div class=\"c6\"[^>]*>(.+?)</div><div class=\"c[78]\"");
|
||||
@@ -258,6 +299,10 @@ public class GalleryDetailParser {
|
||||
}
|
||||
Collections.sort(comments, COMMENT_SORTER);
|
||||
}
|
||||
|
||||
if ((request & REQUEST_COMMENT) != 0) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void parse(String body, int request, int source) throws Exception {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.LofiGalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.LofiGalleryInfo;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.util.AssertException;
|
||||
import com.hippo.util.AssertUtils;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.util.Utils;
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
+2
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -46,4 +46,5 @@ public class GalleryDetail extends GalleryInfo {
|
||||
|
||||
public int previewPageCount;
|
||||
|
||||
public PreviewSet[] previewSetArray;
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LargePreviewSet extends PreviewSet {
|
||||
|
||||
private List<Item> mItemList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return mItemList.size();
|
||||
}
|
||||
|
||||
public void addItem(String imageUrl, String pageUrl) {
|
||||
mItemList.add(new Item(imageUrl, pageUrl));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(SimpleGridLayout simpleGridLayout, LayoutInflater inflater, Conaco conaco) {
|
||||
ensureViewGroup(simpleGridLayout, inflater);
|
||||
|
||||
int size = mItemList.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Item item = mItemList.get(i);
|
||||
final int index = i + getStartIndex();
|
||||
final ViewGroup viewGroup = (ViewGroup) simpleGridLayout.getChildAt(i);
|
||||
conaco.load((LoadImageView) viewGroup.getChildAt(0),
|
||||
EhImageKeyFactory.getLargePreviewKey(getGid(), index), item.imageUrl);
|
||||
((TextView) viewGroup.getChildAt(1)).setText(Integer.toString(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelLoadTask(SimpleGridLayout simpleGridLayout, Conaco conaco) {
|
||||
int count = simpleGridLayout.getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final ViewGroup viewGroup = (ViewGroup) simpleGridLayout.getChildAt(i);
|
||||
conaco.cancel((LoadImageView) viewGroup.getChildAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
private class Item {
|
||||
|
||||
public String imageUrl;
|
||||
public String pageUrl;
|
||||
|
||||
public Item(String imageUrl, String pageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
this.pageUrl = pageUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.conaco.BitmapHolder;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class NormalPreviewSet extends PreviewSet {
|
||||
|
||||
private List<Row> mRowArray = new ArrayList<>();
|
||||
|
||||
private Set<LoadImageTask> mLoadImageTasks = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (Row row : mRowArray) {
|
||||
size += row.itemArray.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public void addItem(String imageUrl, int xOffset, int yOffset, int width,
|
||||
int height, String url) {
|
||||
Row row;
|
||||
int size = mRowArray.size();
|
||||
if (size == 0 || ! (row = mRowArray.get(size - 1)).imageUrl.equals(imageUrl)) {
|
||||
row = new Row(imageUrl);
|
||||
mRowArray.add(row);
|
||||
}
|
||||
row.addItem(xOffset, yOffset, width, height, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(SimpleGridLayout simpleGridLayout,
|
||||
LayoutInflater inflater, Conaco conaco) {
|
||||
ensureViewGroup(simpleGridLayout, inflater);
|
||||
|
||||
int i = 0;
|
||||
for (Row row : mRowArray) {
|
||||
int rowSize = row.itemArray.size();
|
||||
ImageView[] imageViews = new ImageView[rowSize];
|
||||
for (int j = 0; j < rowSize; j++) {
|
||||
ViewGroup viewGroup = (ViewGroup) simpleGridLayout.getChildAt(i);
|
||||
imageViews[j] = (ImageView) viewGroup.getChildAt(0);
|
||||
((TextView) viewGroup.getChildAt(1)).setText(Integer.toString(i + getStartIndex() + 1));
|
||||
i++;
|
||||
}
|
||||
|
||||
LoadImageTask loadImageTask = new LoadImageTask(row, imageViews);
|
||||
mLoadImageTasks.add(loadImageTask);
|
||||
|
||||
String key;
|
||||
if (row.imageIndex != -1) {
|
||||
key = EhImageKeyFactory.getNormalPreviewKey(getGid(), row.imageIndex);
|
||||
} else {
|
||||
key = row.imageUrl;
|
||||
}
|
||||
conaco.load(loadImageTask, key, row.imageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelLoadTask(SimpleGridLayout simpleGridLayout, Conaco conaco) {
|
||||
for (LoadImageTask loadImageTask : mLoadImageTasks) {
|
||||
conaco.cancel(loadImageTask);
|
||||
}
|
||||
mLoadImageTasks.clear();
|
||||
}
|
||||
|
||||
class LoadImageTask implements Unikery {
|
||||
|
||||
private int mTaskId;
|
||||
private Row mRow;
|
||||
private ImageView[] mImageViews;
|
||||
|
||||
public LoadImageTask(Row row, ImageView[] imageViews) {
|
||||
mRow = row;
|
||||
mImageViews = imageViews;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBitmap(BitmapHolder bitmapHolder, Conaco.Source source) {
|
||||
bitmapHolder.obtain();
|
||||
Bitmap bitmap = bitmapHolder.getBitmap();
|
||||
int maxWidth = bitmap.getWidth();
|
||||
int maxHeight = bitmap.getHeight();
|
||||
|
||||
int size = mRow.itemArray.size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
Item item = mRow.itemArray.get(i);
|
||||
if (item.xOffset + item.width > maxWidth) {
|
||||
item.width = maxWidth - item.xOffset;
|
||||
if (item.width <= 0) {
|
||||
// Bad area
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (item.yOffset + item.height > maxHeight) {
|
||||
item.height = maxHeight - item.yOffset;
|
||||
if (item.height <= 0) {
|
||||
// Bad area
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap previewBitmap = Bitmap.createBitmap(bitmap, item.xOffset,
|
||||
item.yOffset, item.width, item.height);
|
||||
|
||||
if (source != Conaco.Source.MEMORY) {
|
||||
Drawable[] layers = new Drawable[2];
|
||||
layers[0] = new ColorDrawable(Color.TRANSPARENT);
|
||||
layers[1] = new BitmapDrawable(mImageViews[i].getResources(), previewBitmap);
|
||||
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
||||
mImageViews[i].setImageDrawable(transitionDrawable);
|
||||
transitionDrawable.startTransition(300);
|
||||
} else {
|
||||
mImageViews[i].setImageBitmap(previewBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
bitmapHolder.release();
|
||||
|
||||
mLoadImageTasks.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawable(Drawable drawable) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTaskId(int id) {
|
||||
mTaskId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTaskId() {
|
||||
return mTaskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
// TODO
|
||||
mLoadImageTasks.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
class Row {
|
||||
|
||||
public String imageUrl;
|
||||
public List<Item> itemArray = new ArrayList<>();
|
||||
public int imageIndex;
|
||||
|
||||
public Row(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
|
||||
int index1 = imageUrl.lastIndexOf('-');
|
||||
int index2 = imageUrl.lastIndexOf('.');
|
||||
|
||||
try {
|
||||
imageIndex = Integer.parseInt(imageUrl.substring(index1 + 1, index2)) - 1;
|
||||
} catch (Exception e) {
|
||||
Log.w("Can't get normal preview index", e);
|
||||
imageIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(int xOffset, int yOffset, int width, int height,
|
||||
String url) {
|
||||
itemArray.add(new Item(xOffset, yOffset, width, height, url));
|
||||
}
|
||||
}
|
||||
|
||||
class Item {
|
||||
|
||||
public int xOffset;
|
||||
public int yOffset;
|
||||
public int width;
|
||||
public int height;
|
||||
public String url;
|
||||
|
||||
public Item(int xOffset, int yOffset, int width, int height, String url) {
|
||||
this.xOffset = xOffset;
|
||||
this.yOffset = yOffset;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
|
||||
public abstract class PreviewSet {
|
||||
|
||||
private int mStartIndex;
|
||||
private int mGid;
|
||||
|
||||
public void setStartIndex(int startIndex) {
|
||||
mStartIndex = startIndex;
|
||||
}
|
||||
|
||||
public int getStartIndex() {
|
||||
return mStartIndex;
|
||||
}
|
||||
|
||||
public abstract int size();
|
||||
|
||||
public void setGid(int gid) {
|
||||
mGid = gid;
|
||||
}
|
||||
|
||||
public int getGid() {
|
||||
return mGid;
|
||||
}
|
||||
|
||||
public abstract void bindView(SimpleGridLayout simpleGridLayout,
|
||||
LayoutInflater inflater, Conaco conaco);
|
||||
|
||||
protected void ensureViewGroup(SimpleGridLayout simpleGridLayout, LayoutInflater inflater) {
|
||||
int size = size();
|
||||
int diff = size - simpleGridLayout.getChildCount();
|
||||
|
||||
if (diff > 0) {
|
||||
for (int i = 0; i < diff; i++) {
|
||||
inflater.inflate(R.layout.item_preview, simpleGridLayout, true);
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
diff = -diff;
|
||||
for (int i = 0; i < diff; i++) {
|
||||
simpleGridLayout.removeViews(size, diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void cancelLoadTask(SimpleGridLayout simpleGridLayout, Conaco conaco);
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
package com.hippo.ehviewer.client.data;
|
||||
|
||||
public class UnsupportedSearchException extends Exception {
|
||||
|
||||
@@ -13,7 +13,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.data.Comment;
|
||||
import com.hippo.ehviewer.client.data.Comment;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.AppbarScene;
|
||||
|
||||
@@ -39,26 +39,36 @@ import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.data.Comment;
|
||||
import com.hippo.ehviewer.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.TagGroup;
|
||||
import com.hippo.ehviewer.client.EhException;
|
||||
import com.hippo.ehviewer.client.OffensiveException;
|
||||
import com.hippo.ehviewer.client.data.Comment;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.TagGroup;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.ehviewer.widget.PreviewLayout;
|
||||
import com.hippo.ehviewer.widget.RatingView;
|
||||
import com.hippo.miscellaneous.StartActivityHelper;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.RippleCurtain;
|
||||
import com.hippo.scene.Scene;
|
||||
import com.hippo.scene.SimpleDialog;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.URLImageGetter;
|
||||
import com.hippo.util.UiUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.AccurateClick;
|
||||
import com.hippo.widget.AutoWrapLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
import static com.hippo.ehviewer.R.id.no_tags;
|
||||
|
||||
public class GalleryDetailScene extends Scene implements View.OnClickListener,
|
||||
AccurateClick.OnAccurateClickListener {
|
||||
|
||||
public static final String KEY_GALLERY_INFO = "gallery_info";
|
||||
|
||||
@@ -88,8 +98,10 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
private TextView mShare;
|
||||
private TextView mRate;
|
||||
private LinearLayout mTag;
|
||||
private TextView mNoTags;
|
||||
private LinearLayout mComment;
|
||||
private TextView mCommentMore;
|
||||
private PreviewLayout mPreviewLayout;
|
||||
|
||||
private View mProgressBar;
|
||||
|
||||
@@ -97,6 +109,12 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
|
||||
private GalleryDetail mGalleryDetail;
|
||||
|
||||
private void requestGalleryDetail(GalleryInfo gi) {
|
||||
EhClient.getInstance().getGalleryDetail(Config.getEhSource(),
|
||||
EhClient.getDetailUrl(Config.getEhSource(), gi.gid, gi.token, 0),
|
||||
new EhDetailListener());
|
||||
}
|
||||
|
||||
private void handleAnnouncer(Announcer announcer) {
|
||||
GalleryInfo gi;
|
||||
|
||||
@@ -112,9 +130,7 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
mCategory.setText(EhUtils.getCategory(gi.category));
|
||||
mCategory.setTextColor(EhUtils.getCategoryColor(gi.category));
|
||||
|
||||
EhClient.getInstance().getGalleryDetail(Config.getEhSource(),
|
||||
EhClient.getDetailUrl(Config.getEhSource(), gi.gid, gi.token, 0),
|
||||
new EhDetailListener());
|
||||
requestGalleryDetail(gi);
|
||||
}
|
||||
|
||||
Context context = getStageActivity();
|
||||
@@ -146,7 +162,8 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
mTorrent.setOnClickListener(this);
|
||||
mShare.setOnClickListener(this);
|
||||
mRate.setOnClickListener(this);
|
||||
mCommentMore.setOnClickListener(this);
|
||||
|
||||
AccurateClick.setOnAccurateClickListener(mComment, this);
|
||||
|
||||
RippleSalon.addRipple(mRead, false);
|
||||
RippleSalon.addRipple(mDownload, false);
|
||||
@@ -187,8 +204,10 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
mShare = (TextView) mContent.findViewById(R.id.share);
|
||||
mRate = (TextView) mContent.findViewById(R.id.rate);
|
||||
mTag = (LinearLayout) mContent.findViewById(R.id.tag);
|
||||
mNoTags = (TextView) mTag.findViewById(no_tags);
|
||||
mComment = (LinearLayout) mContent.findViewById(R.id.comment);
|
||||
mCommentMore = (TextView) mContent.findViewById(R.id.comment_more);
|
||||
mPreviewLayout = (PreviewLayout) mContent.findViewById(R.id.preview);
|
||||
|
||||
mProgressBar = findViewById(R.id.progress_bar);
|
||||
|
||||
@@ -220,10 +239,23 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
} else if (v == mShare) {
|
||||
StartActivityHelper.share(getStageActivity(),
|
||||
EhClient.getDetailUrl(Config.getEhSource(), gd.gid, gd.token, 0));
|
||||
} else if (v == mCommentMore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccurateClick(View v, float x, float y) {
|
||||
GalleryDetail gd = mGalleryDetail;
|
||||
if (gd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == mComment) {
|
||||
int[] position = new int[2];
|
||||
ViewUtils.getLocationInAncestor(mComment, position, getSceneView());
|
||||
Announcer announcer = new Announcer();
|
||||
announcer.setObject(mGalleryDetail.comments);
|
||||
startScene(CommentScene.class, announcer);
|
||||
startScene(CommentScene.class, announcer,
|
||||
new RippleCurtain((int) x + position[0], (int) y + position[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,31 +304,34 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
}
|
||||
|
||||
private void fillTags(List<TagGroup> tags) {
|
||||
Context context = getStageActivity();
|
||||
LayoutInflater inflater = getStageActivity().getLayoutInflater();
|
||||
int x = UiUtils.dp2pix(context, 2);
|
||||
int y = UiUtils.dp2pix(context, 4);
|
||||
if (tags.size() != 0) {
|
||||
mNoTags.setVisibility(View.GONE);
|
||||
|
||||
for (TagGroup tagGroup : tags) {
|
||||
LinearLayout tagGroupLayout = new LinearLayout(context);
|
||||
tagGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
AutoWrapLayout tagLayout = new AutoWrapLayout(context);
|
||||
Context context = getStageActivity();
|
||||
LayoutInflater inflater = getStageActivity().getLayoutInflater();
|
||||
int x = UiUtils.dp2pix(context, 2);
|
||||
int y = UiUtils.dp2pix(context, 4);
|
||||
|
||||
// Group name
|
||||
@SuppressLint("InflateParams")
|
||||
TextView groupNameView = (TextView) inflater.inflate(R.layout.tag_group, null);
|
||||
groupNameView.setText(tagGroup.groupName);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
lp.setMargins(x, y, x, y);
|
||||
tagGroupLayout.addView(groupNameView, lp);
|
||||
for (TagGroup tagGroup : tags) {
|
||||
LinearLayout tagGroupLayout = new LinearLayout(context);
|
||||
tagGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
AutoWrapLayout tagLayout = new AutoWrapLayout(context);
|
||||
|
||||
int count = tagGroup.getTagCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
// Group name
|
||||
@SuppressLint("InflateParams")
|
||||
TextView tagView = (TextView) inflater.inflate(R.layout.tag, null);
|
||||
tagView.setText(tagGroup.getTagAt(i));
|
||||
TextView groupNameView = (TextView) inflater.inflate(R.layout.tag_group, null);
|
||||
groupNameView.setText(tagGroup.groupName);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
lp.setMargins(x, y, x, y);
|
||||
tagGroupLayout.addView(groupNameView, lp);
|
||||
|
||||
int count = tagGroup.getTagCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
@SuppressLint("InflateParams")
|
||||
TextView tagView = (TextView) inflater.inflate(R.layout.tag, null);
|
||||
tagView.setText(tagGroup.getTagAt(i));
|
||||
/*
|
||||
tagView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -312,17 +347,21 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
}
|
||||
});
|
||||
*/
|
||||
AutoWrapLayout.LayoutParams alp = new AutoWrapLayout.LayoutParams();
|
||||
alp.setMargins(x, y, x, y);
|
||||
tagLayout.addView(tagView, alp);
|
||||
AutoWrapLayout.LayoutParams alp = new AutoWrapLayout.LayoutParams();
|
||||
alp.setMargins(x, y, x, y);
|
||||
tagLayout.addView(tagView, alp);
|
||||
}
|
||||
tagGroupLayout.addView(tagLayout);
|
||||
mTag.addView(tagGroupLayout);
|
||||
}
|
||||
tagGroupLayout.addView(tagLayout);
|
||||
mTag.addView(tagGroupLayout);
|
||||
} else {
|
||||
mNoTags.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private View createCommentView(Comment comment) {
|
||||
View view = LayoutInflater.from(getStageActivity()).inflate(R.layout.item_comment, null);
|
||||
View view = LayoutInflater.from(getStageActivity()).inflate(R.layout.item_comment, null);
|
||||
((TextView) view.findViewById(R.id.user)).setText(comment.user);
|
||||
((TextView) view.findViewById(R.id.time)).setText(comment.time);
|
||||
TextView commentText = (TextView) view.findViewById(R.id.comment);
|
||||
@@ -364,11 +403,13 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
|
||||
int commentNum = galleryDetail.comments.size();
|
||||
if (commentNum == 0) {
|
||||
mCommentMore.setText("暂无评论");
|
||||
mCommentMore.setText(R.string.no_comments);
|
||||
// Remove padding interval
|
||||
mCommentMore.setPadding(0, 0, 0, 0);
|
||||
} else if (commentNum <= 2){
|
||||
mCommentMore.setText("暂无更多评论");
|
||||
mCommentMore.setText(R.string.no_more_comments);
|
||||
} else {
|
||||
mCommentMore.setText("更多评论");
|
||||
mCommentMore.setText(R.string.more_comment);
|
||||
}
|
||||
int maxShown = Math.min(2, commentNum);
|
||||
for (int i = 0; i < maxShown; i++) {
|
||||
@@ -377,13 +418,30 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
mPreviewLayout.setData(galleryDetail.previewSetArray,
|
||||
getStageActivity().getLayoutInflater(),
|
||||
EhApplication.getConaco(getStageActivity()));
|
||||
mPreviewLayout.selectPreviewAt(0);
|
||||
|
||||
mViewTransition.showView(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
e.printStackTrace();
|
||||
// TODO
|
||||
if (e instanceof OffensiveException) {
|
||||
|
||||
} else if (e instanceof EhException) {
|
||||
new SimpleDialog.Builder(getStageActivity()).setTitle("Error")
|
||||
.setMessage(e.getMessage())
|
||||
.setNegativeButton(android.R.string.cancel)
|
||||
.setOnCloseListener(new SimpleDialog.OnCloseListener() {
|
||||
@Override
|
||||
public void onClose(SimpleDialog dialog, boolean cancel) {
|
||||
finish();
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,9 @@ import com.hippo.ehviewer.EhImageKeyFactory;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.GalleryListParser;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.data.UnsupportedSearchException;
|
||||
import com.hippo.ehviewer.client.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.data.UnsupportedSearchException;
|
||||
import com.hippo.ehviewer.ui.ContentActivity;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
|
||||
@@ -7,13 +7,13 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.hippo.conaco.BitmapHolder;
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.widget.FixedAspectImageView;
|
||||
|
||||
public class LoadImageView extends ImageView implements Unikery {
|
||||
public class LoadImageView extends FixedAspectImageView implements Unikery {
|
||||
|
||||
private int mTaskId = Unikery.INVAILD_ID;
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.data.LargePreviewSet;
|
||||
import com.hippo.ehviewer.client.data.PreviewSet;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.widget.SimpleGridLayout;
|
||||
|
||||
public final class PreviewLayout extends LinearLayout implements View.OnClickListener {
|
||||
|
||||
private GestureDetector mGestureDetector;
|
||||
private PreviewSet[] mPreviewSets;
|
||||
private Conaco mConaco;
|
||||
private LayoutInflater mInflater;
|
||||
private int mPreviewSetCount;
|
||||
private int mCurrentPreviewIndex = -1;
|
||||
|
||||
private SimpleGridLayout mSimpleGridLayout;
|
||||
private View mTopPrevious;
|
||||
private TextView mTopSelection;
|
||||
private View mTopNext;
|
||||
private View mBottomPrevious;
|
||||
private TextView mBottomSelection;
|
||||
private View mBottomNext;
|
||||
|
||||
private int mWidth;
|
||||
|
||||
public PreviewLayout(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public PreviewLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public PreviewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.widget_preview_layout, this);
|
||||
|
||||
ViewGroup viewGroup = (ViewGroup) getChildAt(0);
|
||||
mTopPrevious = viewGroup.getChildAt(0);
|
||||
mTopSelection = (TextView) viewGroup.getChildAt(2);
|
||||
mTopNext = viewGroup.getChildAt(4);
|
||||
mSimpleGridLayout = (SimpleGridLayout) getChildAt(1);
|
||||
viewGroup = (ViewGroup) getChildAt(2);
|
||||
mBottomPrevious = viewGroup.getChildAt(0);
|
||||
mBottomSelection = (TextView) viewGroup.getChildAt(2);
|
||||
mBottomNext = viewGroup.getChildAt(4);
|
||||
|
||||
RippleSalon.addRipple(mTopPrevious, false);
|
||||
RippleSalon.addRipple(mTopSelection, false);
|
||||
RippleSalon.addRipple(mTopNext, false);
|
||||
RippleSalon.addRipple(mBottomPrevious, false);
|
||||
RippleSalon.addRipple(mBottomSelection, false);
|
||||
RippleSalon.addRipple(mBottomNext, false);
|
||||
|
||||
mTopPrevious.setOnClickListener(this);
|
||||
mTopSelection.setOnClickListener(this);
|
||||
mTopNext.setOnClickListener(this);
|
||||
mBottomPrevious.setOnClickListener(this);
|
||||
mBottomSelection.setOnClickListener(this);
|
||||
mBottomNext.setOnClickListener(this);
|
||||
|
||||
GestureListener gestureListener = new GestureListener();
|
||||
mGestureDetector = new GestureDetector(context, gestureListener);
|
||||
mGestureDetector.setIsLongpressEnabled(false);
|
||||
}
|
||||
|
||||
public void setData(PreviewSet[] previewSets, LayoutInflater inflater, Conaco conaco) {
|
||||
mPreviewSets = previewSets;
|
||||
mPreviewSetCount = previewSets.length;
|
||||
mInflater = inflater;
|
||||
mConaco = conaco;
|
||||
}
|
||||
|
||||
private boolean isLargePreview() {
|
||||
for (PreviewSet previewSet : mPreviewSets) {
|
||||
if (previewSet != null) {
|
||||
return previewSet instanceof LargePreviewSet;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
|
||||
int width = r - l;
|
||||
if (mWidth != width) {
|
||||
mWidth = width;
|
||||
int itemWidth = getResources().getDimensionPixelOffset(
|
||||
isLargePreview() ? R.dimen.gallery_large_preview_item_width :
|
||||
R.dimen.gallery_normal_preview_item_width);
|
||||
int columnCount = Math.round(
|
||||
(width - getPaddingLeft() - getPaddingRight()) / (float) itemWidth);
|
||||
columnCount = Math.max(columnCount, 1);
|
||||
mSimpleGridLayout.setColumnCount(columnCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
return handleTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
||||
return handleTouchEvent(event);
|
||||
}
|
||||
|
||||
private boolean handleTouchEvent(MotionEvent event) {
|
||||
return mGestureDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
public int getPreviewPageCount() {
|
||||
return mPreviewSetCount;
|
||||
}
|
||||
|
||||
public void selectPreviewAt(int index) {
|
||||
if (index < 0 || index >= mPreviewSetCount) {
|
||||
throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + mPreviewSetCount);
|
||||
}
|
||||
|
||||
mCurrentPreviewIndex = index;
|
||||
|
||||
PreviewSet previewSet = mPreviewSets[index];
|
||||
if (previewSet != null) {
|
||||
previewSet.bindView(mSimpleGridLayout, mInflater, mConaco);
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
|
||||
String showText = (index + 1) + "/" + mPreviewSetCount;
|
||||
mTopSelection.setText(showText);
|
||||
mBottomSelection.setText(showText);
|
||||
}
|
||||
|
||||
public void tryNextPreview() {
|
||||
if (mCurrentPreviewIndex < mPreviewSetCount - 1) {
|
||||
selectPreviewAt(mCurrentPreviewIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void tryPreviousPreview() {
|
||||
if (mCurrentPreviewIndex > 0) {
|
||||
selectPreviewAt(mCurrentPreviewIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
|
||||
class GestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
|
||||
private boolean mHasScrollX = false;
|
||||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent e) {
|
||||
mHasScrollX = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2,
|
||||
float distanceX, float distanceY) {
|
||||
if (Math.abs(distanceX) > Math.abs(distanceY)) {
|
||||
if (!mHasScrollX) {
|
||||
mHasScrollX = true;
|
||||
if (distanceX > 0) {
|
||||
tryNextPreview();
|
||||
} else {
|
||||
tryPreviousPreview();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.client.data.ListUrlBuilder;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.scene.SimpleDialog;
|
||||
import com.hippo.util.UiUtils;
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.hippo.animation.DurationInterpolator;
|
||||
import com.hippo.animation.SimpleAnimatorListener;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class RippleCurtain extends Curtain {
|
||||
|
||||
private static final String TAG = RippleCurtain.class.getSimpleName();
|
||||
|
||||
private static long ANIMATE_TIME = 300L;
|
||||
|
||||
private int mStartX;
|
||||
private int mStartY;
|
||||
|
||||
private AnimatorSet mAnimatorSet;
|
||||
|
||||
public RippleCurtain(int startX, int startY) {
|
||||
mStartX = startX;
|
||||
mStartY = startY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRebirth() {
|
||||
mStartX = 0;
|
||||
mStartY = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(@NonNull final Scene enter, @NonNull final Scene exit) {
|
||||
final Set<Animator> animatorCollection = new HashSet<>();
|
||||
|
||||
final SceneView enterView = enter.getSceneView();
|
||||
enterView.setStartPoint(mStartX, mStartY);
|
||||
ViewUtils.setVisibility(enterView, View.INVISIBLE);
|
||||
|
||||
// Canvas.clipPath() not work for pre-JELLY_BEAN_MR2 when hardware accelerated
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
ViewUtils.removeHardwareAccelerationSupport(enterView);
|
||||
}
|
||||
|
||||
enterView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
ViewUtils.removeOnGlobalLayoutListener(enterView.getViewTreeObserver(), this);
|
||||
|
||||
final View sceneContentView = enter.getSceneView().getChildAt(0);
|
||||
if (sceneContentView != null) {
|
||||
sceneContentView.setVisibility(View.INVISIBLE);
|
||||
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(sceneContentView, "alpha", 0f, 1f);
|
||||
alphaAnim.setDuration(ANIMATE_TIME * 2);
|
||||
alphaAnim.setInterpolator(new DurationInterpolator(0.3f));
|
||||
alphaAnim.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
sceneContentView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
animatorCollection.add(alphaAnim);
|
||||
} else {
|
||||
Log.w(TAG, "Can't get enter scene content view");
|
||||
}
|
||||
|
||||
PropertyValuesHolder circlePercentPvh = PropertyValuesHolder.ofFloat("circlePercent", 0f, 1f);
|
||||
ObjectAnimator animFrame = ObjectAnimator.ofPropertyValuesHolder(enterView, circlePercentPvh);
|
||||
animFrame.setDuration(ANIMATE_TIME);
|
||||
animatorCollection.add(animFrame);
|
||||
|
||||
mAnimatorSet = new AnimatorSet();
|
||||
mAnimatorSet.playTogether(animatorCollection);
|
||||
mAnimatorSet.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
ViewUtils.setVisibility(enterView, View.VISIBLE);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
dispatchOpenFinished(enter, exit);
|
||||
hideSceneOnOpen(exit);
|
||||
mAnimatorSet = null;
|
||||
|
||||
// Canvas.clipPath() not work for pre-JELLY_BEAN_MR2 when hardware accelerated
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
ViewUtils.addHardwareAccelerationSupport(enterView);
|
||||
}
|
||||
}
|
||||
});
|
||||
mAnimatorSet.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(@NonNull final Scene enter, @NonNull final Scene exit) {
|
||||
showSceneOnClose(enter);
|
||||
|
||||
final Set<Animator> animatorCollection = new HashSet<>();
|
||||
|
||||
final SceneView exitView = exit.getSceneView();
|
||||
exitView.setStartPoint(mStartX, mStartY);
|
||||
|
||||
// Canvas.clipPath() not work for pre-JELLY_BEAN_MR2 when hardware accelerated
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
ViewUtils.removeHardwareAccelerationSupport(exitView);
|
||||
}
|
||||
|
||||
PropertyValuesHolder circlePercentPvh = PropertyValuesHolder.ofFloat("circlePercent", 1f, 0f);
|
||||
ObjectAnimator animFrame = ObjectAnimator.ofPropertyValuesHolder(exitView, circlePercentPvh);
|
||||
animFrame.setDuration(ANIMATE_TIME);
|
||||
animatorCollection.add(animFrame);
|
||||
|
||||
mAnimatorSet = new AnimatorSet();
|
||||
mAnimatorSet.playTogether(animatorCollection);
|
||||
mAnimatorSet.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation, boolean canceled) {
|
||||
super.onAnimationEnd(animation, canceled);
|
||||
dispatchCloseFinished(enter, exit);
|
||||
mAnimatorSet = null;
|
||||
|
||||
// Canvas.clipPath() not work for pre-JELLY_BEAN_MR2 when hardware accelerated
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
ViewUtils.addHardwareAccelerationSupport(exitView);
|
||||
}
|
||||
}
|
||||
});
|
||||
mAnimatorSet.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimation() {
|
||||
if (mAnimatorSet != null) {
|
||||
mAnimatorSet.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInAnimation() {
|
||||
return mAnimatorSet != null;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Path;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
@@ -27,6 +29,12 @@ public class SceneView extends AbsoluteLayout {
|
||||
|
||||
private boolean mEnableTouch = true;
|
||||
|
||||
private Path mPath;
|
||||
private float mRadius;
|
||||
private float mCirclePercent = 1f;
|
||||
private float mStartX = -1f;
|
||||
private float mStartY = -1f;
|
||||
|
||||
public SceneView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
@@ -44,6 +52,7 @@ public class SceneView extends AbsoluteLayout {
|
||||
|
||||
private void init() {
|
||||
setClickable(true);
|
||||
mPath = new Path();
|
||||
}
|
||||
|
||||
public void setEnableTouch(boolean enableTouch) {
|
||||
@@ -64,4 +73,65 @@ public class SceneView extends AbsoluteLayout {
|
||||
public boolean dispatchGenericMotionEvent(@NonNull MotionEvent event) {
|
||||
return mEnableTouch && super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
private void updateRadius() {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
if ((mStartX != -1f || mStartY != -1f) && width != 0 && height != 0) {
|
||||
float h = Math.max(mStartX, width - mStartX);
|
||||
float v = Math.max(mStartY, height - mStartY);
|
||||
mRadius = (float) Math.hypot(h, v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t,
|
||||
int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
updateRadius();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
float circlePercent = mCirclePercent;
|
||||
int saved = 0;
|
||||
|
||||
if (circlePercent != 1f && mRadius != 0f) {
|
||||
mPath.rewind();
|
||||
mPath.addCircle(mStartX, mStartY, circlePercent * mRadius, Path.Direction.CW);
|
||||
saved = canvas.save();
|
||||
canvas.clipPath(mPath);
|
||||
}
|
||||
|
||||
super.draw(canvas);
|
||||
|
||||
if (circlePercent != 1f && mRadius != 0f && saved != 0) {
|
||||
canvas.restoreToCount(saved);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void setCirclePercent(float circlePercent) {
|
||||
float largeCirclePercent = Math.max(mCirclePercent, circlePercent);
|
||||
mCirclePercent = circlePercent;
|
||||
|
||||
if (largeCirclePercent == 1f) {
|
||||
invalidate();
|
||||
} else {
|
||||
float radius = mRadius * largeCirclePercent;
|
||||
invalidate((int) (mStartX - radius), (int) (mStartY - radius),
|
||||
(int) (mStartX + radius), (int) (mStartY + radius));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public float getCirclePercent() {
|
||||
return mCirclePercent;
|
||||
}
|
||||
|
||||
public void setStartPoint(float x, float y) {
|
||||
mStartX = x;
|
||||
mStartY = y;
|
||||
updateRadius();
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ public class SimpleDialogCurtain extends Curtain {
|
||||
final Set<Animator> animatorCollection = new HashSet<>();
|
||||
|
||||
// Handle background
|
||||
int bgColor = enter.getBackgroundColor();
|
||||
int bgColor = exitDialog.getBackgroundColor();
|
||||
int endBgColor = bgColor & 0xffffff;
|
||||
ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", endBgColor);
|
||||
colorAnim.setEvaluator(ArgbEvaluator.getInstance());
|
||||
|
||||
@@ -274,6 +274,16 @@ public final class MathUtils {
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static int ceilDivide(int a, int b) {
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return is a and b is in the same side to standard.
|
||||
* If one of a and b equals standard, return true.
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.view.ViewTreeObserver;
|
||||
|
||||
public final class ViewUtils {
|
||||
|
||||
public static final int MAX_SIZE = Integer.MAX_VALUE & ~(0x3 << 30);
|
||||
|
||||
/**
|
||||
* Get view center location in window
|
||||
*
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.hotspot.HotspotTouchHelper;
|
||||
import com.hippo.hotspot.Hotspotable;
|
||||
|
||||
public final class AccurateClick {
|
||||
|
||||
public static void setOnAccurateClickListener(@NonNull View view, @NonNull OnAccurateClickListener listener) {
|
||||
AccurateClickHelper accurateClickHelper = new AccurateClickHelper();
|
||||
view.setTag(R.id.view_tag_accurate_click_helper, accurateClickHelper);
|
||||
view.setTag(R.id.view_tag_on_accurate_click_listener, listener);
|
||||
view.setOnTouchListener(new HotspotTouchHelper(accurateClickHelper));
|
||||
view.setOnClickListener(new DelegateClickListener());
|
||||
}
|
||||
|
||||
static class DelegateClickListener implements View.OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object accurateClickHelper = v.getTag(R.id.view_tag_accurate_click_helper);
|
||||
Object listener = v.getTag(R.id.view_tag_on_accurate_click_listener);
|
||||
if (accurateClickHelper instanceof AccurateClickHelper && listener instanceof OnAccurateClickListener) {
|
||||
AccurateClickHelper ach = (AccurateClickHelper) accurateClickHelper;
|
||||
((OnAccurateClickListener) listener).onAccurateClick(v, ach.x, ach.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class AccurateClickHelper implements Hotspotable {
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
@Override
|
||||
public void setHotspot(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnAccurateClickListener {
|
||||
void onAccurateClick(View v, float x, float y);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,13 @@ public class CardButton extends Button implements CardViewDelegate {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPadding(int left, int top, int right, int bottom) {
|
||||
if (mCardHelper != null) {
|
||||
mCardHelper.setPadding(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRawPadding(int left, int top, int right, int bottom) {
|
||||
super.setPadding(left, top, right, bottom);
|
||||
|
||||
@@ -45,7 +45,9 @@ public class CardLinearLayout extends LinearLayout implements CardViewDelegate {
|
||||
|
||||
@Override
|
||||
public void setPadding(int left, int top, int right, int bottom) {
|
||||
mCardHelper.setPadding(left, top, right, bottom);
|
||||
if (mCardHelper != null) {
|
||||
mCardHelper.setPadding(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.MathUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
/**
|
||||
* not scrollable
|
||||
*
|
||||
* @author Hippo
|
||||
*
|
||||
*/
|
||||
public class SimpleGridLayout extends ViewGroup {
|
||||
|
||||
private static final int DEFAULT_COLUMN_COUNT = 3;
|
||||
|
||||
private int mColumnCount;
|
||||
private int mItemMargin;
|
||||
|
||||
private int[] mRowHeights;
|
||||
private int mItemWidth;
|
||||
|
||||
public SimpleGridLayout(Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public SimpleGridLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public SimpleGridLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public void init(Context context, AttributeSet attrs) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SimpleGridLayout);
|
||||
mColumnCount = a.getInteger(R.styleable.SimpleGridLayout_columnCount, DEFAULT_COLUMN_COUNT);
|
||||
mItemMargin = a.getDimensionPixelOffset(R.styleable.SimpleGridLayout_itemMargin, 0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void setItemMargin(int itemMargin) {
|
||||
if (mItemMargin != itemMargin) {
|
||||
mItemMargin = itemMargin;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public void setColumnCount(int columnCount) {
|
||||
if (columnCount <= 0) {
|
||||
throw new IllegalStateException("Column count can't be " + columnCount);
|
||||
}
|
||||
|
||||
if (mColumnCount != columnCount) {
|
||||
mColumnCount = columnCount;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int maxRowCount = MathUtils.ceilDivide(getChildCount(), mColumnCount);
|
||||
if (mRowHeights == null || mRowHeights.length != maxRowCount) {
|
||||
mRowHeights = new int[maxRowCount];
|
||||
}
|
||||
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED) {
|
||||
maxWidth = 300;
|
||||
}
|
||||
if (heightMode == MeasureSpec.UNSPECIFIED) {
|
||||
maxHeight = ViewUtils.MAX_SIZE;
|
||||
}
|
||||
|
||||
// Get item width MeasureSpec
|
||||
mItemWidth = Math.max(
|
||||
(maxWidth - getPaddingLeft() - getPaddingRight() - ((mColumnCount - 1) * mItemMargin)) / mColumnCount, 1);
|
||||
int itemWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mItemWidth, MeasureSpec.EXACTLY);
|
||||
int itemHeightMeasureSpec = MeasureSpec.UNSPECIFIED;
|
||||
|
||||
int measuredWidth = maxWidth;
|
||||
int measuredHeight = 0;
|
||||
int rowHeight = 0;
|
||||
int row = 0;
|
||||
int count = getChildCount();
|
||||
for (int index = 0, indexInRow = 0; index < count; index++, indexInRow++) {
|
||||
final View child = getChildAt(index);
|
||||
if (child.getVisibility() == View.GONE) {
|
||||
indexInRow--;
|
||||
continue;
|
||||
}
|
||||
|
||||
child.measure(itemWidthMeasureSpec, itemHeightMeasureSpec);
|
||||
|
||||
if (indexInRow == mColumnCount) {
|
||||
// New row
|
||||
indexInRow = 0;
|
||||
rowHeight = 0;
|
||||
row++;
|
||||
}
|
||||
|
||||
rowHeight = Math.max(rowHeight, child.getMeasuredHeight());
|
||||
|
||||
if (indexInRow == mColumnCount - 1 || index == count - 1) {
|
||||
mRowHeights[row] = rowHeight;
|
||||
measuredHeight += rowHeight + mItemMargin;
|
||||
}
|
||||
}
|
||||
measuredHeight -= mItemMargin;
|
||||
measuredHeight = Math.min(measuredHeight + getPaddingTop() + getPaddingBottom(), maxHeight);
|
||||
|
||||
setMeasuredDimension(measuredWidth, measuredHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int itemWidth = mItemWidth;
|
||||
int itemMargin = mItemMargin;
|
||||
int paddingLeft = getPaddingLeft();
|
||||
int left = paddingLeft;
|
||||
int top = getPaddingTop();
|
||||
int row = 0;
|
||||
int count = getChildCount();
|
||||
for (int index = 0, indexInRow = 0; index < count; index++, indexInRow++) {
|
||||
final View child = getChildAt(index);
|
||||
if (child.getVisibility() == View.GONE) {
|
||||
indexInRow--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (indexInRow == mColumnCount) {
|
||||
// New row
|
||||
left = paddingLeft;
|
||||
top += mRowHeights[row] + itemMargin;
|
||||
|
||||
indexInRow = 0;
|
||||
row++;
|
||||
}
|
||||
|
||||
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
|
||||
|
||||
left += itemWidth + itemMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user