@@ -0,0 +1,48 @@
|
||||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.ui.drawables.SawtoothTearDrawable;
|
||||
|
||||
// Mind the gap!
|
||||
public class GapStatusDisplayItem extends StatusDisplayItem{
|
||||
public boolean loading;
|
||||
|
||||
public GapStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment){
|
||||
super(parentID, parentFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(){
|
||||
return Type.GAP;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<GapStatusDisplayItem>{
|
||||
public final ProgressBar progress;
|
||||
public final TextView text;
|
||||
|
||||
public Holder(Context context, ViewGroup parent){
|
||||
super(context, R.layout.display_item_gap, parent);
|
||||
progress=findViewById(R.id.progress);
|
||||
text=findViewById(R.id.text);
|
||||
itemView.setForeground(new SawtoothTearDrawable(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(GapStatusDisplayItem item){
|
||||
text.setVisibility(item.loading ? View.GONE : View.VISIBLE);
|
||||
progress.setVisibility(item.loading ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
item.parentFragment.onGapClick(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ public abstract class StatusDisplayItem{
|
||||
case ACCOUNT_CARD -> new AccountCardStatusDisplayItem.Holder(activity, parent);
|
||||
case ACCOUNT -> new AccountStatusDisplayItem.Holder(activity, parent);
|
||||
case HASHTAG -> new HashtagStatusDisplayItem.Holder(activity, parent);
|
||||
case GAP -> new GapStatusDisplayItem.Holder(activity, parent);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -112,6 +113,8 @@ public abstract class StatusDisplayItem{
|
||||
}
|
||||
if(addFooter){
|
||||
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
||||
if(status.hasGapAfter)
|
||||
items.add(new GapStatusDisplayItem(parentID, fragment));
|
||||
}
|
||||
int i=1;
|
||||
for(StatusDisplayItem item:items){
|
||||
@@ -142,7 +145,8 @@ public abstract class StatusDisplayItem{
|
||||
FOOTER,
|
||||
ACCOUNT_CARD,
|
||||
ACCOUNT,
|
||||
HASHTAG
|
||||
HASHTAG,
|
||||
GAP
|
||||
}
|
||||
|
||||
public static abstract class Holder<T extends StatusDisplayItem> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.joinmastodon.android.ui.drawables;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class SawtoothTearDrawable extends Drawable{
|
||||
private final Paint topPaint, bottomPaint;
|
||||
|
||||
private static final int TOP_SAWTOOTH_HEIGHT=5;
|
||||
private static final int BOTTOM_SAWTOOTH_HEIGHT=3;
|
||||
private static final int STROKE_WIDTH=2;
|
||||
private static final int SAWTOOTH_PERIOD=14;
|
||||
|
||||
public SawtoothTearDrawable(Context context){
|
||||
topPaint=makeShaderPaint(makeSawtoothTexture(context, TOP_SAWTOOTH_HEIGHT, SAWTOOTH_PERIOD, false, STROKE_WIDTH));
|
||||
bottomPaint=makeShaderPaint(makeSawtoothTexture(context, BOTTOM_SAWTOOTH_HEIGHT, SAWTOOTH_PERIOD, true, STROKE_WIDTH));
|
||||
Matrix matrix=new Matrix();
|
||||
//noinspection IntegerDivisionInFloatingPointContext
|
||||
matrix.setTranslate(V.dp(SAWTOOTH_PERIOD/2), 0);
|
||||
bottomPaint.getShader().setLocalMatrix(matrix);
|
||||
}
|
||||
|
||||
private Bitmap makeSawtoothTexture(Context context, int height, int period, boolean fillBottom, int strokeWidth){
|
||||
int actualStrokeWidth=V.dp(strokeWidth);
|
||||
int actualPeriod=V.dp(period);
|
||||
int actualHeight=V.dp(height);
|
||||
Bitmap bitmap=Bitmap.createBitmap(actualPeriod, actualHeight+actualStrokeWidth*2, Bitmap.Config.ARGB_8888);
|
||||
Canvas c=new Canvas(bitmap);
|
||||
Path path=new Path();
|
||||
//noinspection SuspiciousNameCombination
|
||||
path.moveTo(-actualPeriod/2f, actualStrokeWidth);
|
||||
path.lineTo(0, actualHeight+actualStrokeWidth);
|
||||
//noinspection SuspiciousNameCombination
|
||||
path.lineTo(actualPeriod/2f, actualStrokeWidth);
|
||||
path.lineTo(actualPeriod, actualHeight+actualStrokeWidth);
|
||||
//noinspection SuspiciousNameCombination
|
||||
path.lineTo(actualPeriod*1.5f, actualStrokeWidth);
|
||||
if(fillBottom){
|
||||
path.lineTo(actualPeriod*1.5f, actualHeight*20);
|
||||
path.lineTo(-actualPeriod/2f, actualHeight*20);
|
||||
}else{
|
||||
path.lineTo(actualPeriod*1.5f, -actualHeight);
|
||||
path.lineTo(-actualPeriod/2f, -actualHeight);
|
||||
}
|
||||
path.close();
|
||||
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(UiUtils.getThemeColor(context, R.attr.colorWindowBackground));
|
||||
c.drawPath(path, paint);
|
||||
paint.setColor(UiUtils.getThemeColor(context, R.attr.colorPollVoted));
|
||||
paint.setStrokeWidth(actualStrokeWidth);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
c.drawPath(path, paint);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private Paint makeShaderPaint(Bitmap bitmap){
|
||||
BitmapShader shader=new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
|
||||
Paint paint=new Paint();
|
||||
paint.setShader(shader);
|
||||
return paint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas){
|
||||
int strokeWidth=V.dp(STROKE_WIDTH);
|
||||
Rect bounds=getBounds();
|
||||
canvas.save();
|
||||
canvas.translate(bounds.left, bounds.top);
|
||||
canvas.drawRect(0, 0, bounds.width(), V.dp(TOP_SAWTOOTH_HEIGHT)+strokeWidth*2, topPaint);
|
||||
int bottomHeight=V.dp(BOTTOM_SAWTOOTH_HEIGHT)+strokeWidth*2;
|
||||
canvas.translate(0, bounds.height()-bottomHeight);
|
||||
canvas.drawRect(0, 0, bounds.width(), bottomHeight, bottomPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(){
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user