requestfocus - setvisibility android studio
Pergamino infinito de objetos finitos. (3)
Esta solución se basa en el código fuente de @azizbekian ( gracias por un ejemplo interesante ). Fue muy divertido para mí encontrar algo parecido a lo que me pediste ( ambos al mismo tiempo ). Entonces, aquí está mi código modificado:
public class MainActivity extends AppCompatActivity {
private static final int spanCount = 5;
private static final int totalItemCount = 15;
private GridLayoutManager gridLayoutManager;
private RecyclerView recyclerView;
private int orientation = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler);
recyclerView.setAdapter(new MyAdapter(totalItemCount));
// Shamelessly stolen from devunwired bit.ly/2yCqVIp
recyclerView.addItemDecoration(new GridDividerDecoration(this));
gridLayoutManager = new GridLayoutManager(this, spanCount);
recyclerView.setLayoutManager(gridLayoutManager);
RecyclerView.OnScrollListener listener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recycler, int dx, int dy) {
super.onScrolled(recycler, dx, dy);
if (dx > 0) {
orientation = LinearLayoutManager.HORIZONTAL;
} else if (dx < 0) {
orientation = LinearLayoutManager.VERTICAL;
} else if (dy > 0) {
orientation = LinearLayoutManager.VERTICAL;
} else if (dy < 0) {
orientation = LinearLayoutManager.HORIZONTAL;
}
recycler.post(new Runnable() {
@Override
public void run() {
gridLayoutManager.setOrientation(orientation);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.getAdapter().notifyDataSetChanged();
}
});
}
};
recyclerView.addOnScrollListener(listener);
}
static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final int totalSizeOfItems;
private boolean hasBeenSetup = false;
MyAdapter(int totalSizeOfItems) {
this.totalSizeOfItems = totalSizeOfItems;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
final int cellSize = parent.getMeasuredWidth() / spanCount;
view.setMinimumWidth(cellSize);
view.setMinimumHeight(cellSize);
setupRecyclerHeightIfNeeded(parent, cellSize);
return new MyViewHolder(view);
}
// We need to perform this operation once, not each time `onCreateViewHolder` is called
private void setupRecyclerHeightIfNeeded(final View parent, int cellSize) {
if (hasBeenSetup) return;
hasBeenSetup = true;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
int numOfRows = (int) (totalItemCount / (double) spanCount);
params.height = numOfRows * cellSize + 100; // modified based on my phone height
new Handler().post(new Runnable() {
@Override
public void run() {
parent.requestLayout();
}
});
}
@Override
public void onBindViewHolder(MyViewHolder holder, int pos) {
int position = holder.getAdapterPosition() % totalSizeOfItems;
holder.textView.setText(Integer.toString(position + 1));
}
@Override
public int getItemCount() {
// this will result the list to be "infinite"
return Integer.MAX_VALUE;
}
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
El diseño se desplaza hacia arriba para orientación vertical y se desplaza hacia la izquierda para horizontal. La salida está siguiendo ( perdón por la animación fea ):
Espero que te ayude.
Tengo un GridView
que tiene elementos dentro de 5x50.
Necesito desplazarlos en todas direcciones y en lugar de detenerme cuando llegue al final, simplemente comience desde la parte superior / izquierda.
por ejemplo, desplazamiento de izquierda a derecha
antes de desplazamiento
1 2 3 4 5
6 7 8 9 10
despues desplaza hacia la derecha
5 1 2 3 4
10 6 7 8 9
y de arriba a abajo (o de abajo a arriba)
antes de desplazarse a la parte inferior
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
despues de desplazamiento
6 7 8 9 10
11 12 13 14 15
1 2 3 4 5
Intento que sea suave como el desplazamiento nativo de GridView
.
Habiendo especificado la siguiente jerarquía de vistas en activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Y un elemento de lista básico: un TextView
, dentro de item.xml
:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
Luego en la actividad:
public class MainActivity extends AppCompatActivity {
private static final int spanCount = 5;
private static final int totalItemCount = 15;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recycler);
// Shamelessly stolen from devunwired bit.ly/2yCqVIp
recyclerView.addItemDecoration(new GridDividerDecoration(this));
recyclerView.setLayoutManager(new GridLayoutManager(this, spanCount, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(new MyAdapter(totalItemCount));
}
static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final int totalSizeOfItems;
private boolean hasBeenSetup = false;
MyAdapter(int totalSizeOfItems) {
this.totalSizeOfItems = totalSizeOfItems;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
final int cellSize = parent.getMeasuredWidth() / spanCount;
view.setMinimumWidth(cellSize);
view.setMinimumHeight(cellSize);
setupRecyclerHeightIfNeeded(parent, cellSize);
return new MyViewHolder(view);
}
// We need to perform this operation once, not each time `onCreateViewHolder` is called
private void setupRecyclerHeightIfNeeded(View parent, int cellSize) {
if (hasBeenSetup) return;
hasBeenSetup = true;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
int numOfRows = (int) (totalItemCount / (double) spanCount);
params.height = numOfRows * cellSize;
new Handler().post(parent::requestLayout);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int pos) {
int position = holder.getAdapterPosition() % totalSizeOfItems;
holder.textView.setText(Integer.toString(position + 1));
}
@Override
public int getItemCount() {
// this will result the list to be "infinite"
return Integer.MAX_VALUE;
}
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
En la salida obtendrá:
Cuidar el desplazamiento horizontal requeriría una pequeña cantidad de cambios:
- La orientación de
GridLayoutManager
debe cambiarse aHORIZONTAL
- Los adaptadores de ancho / altura apropiados del adaptador interior deben sustituirse
Aparte de eso, todo debería ser similar.
Here hay otra solución pero con un enfoque de lienzo.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraint_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<nice.fontaine.infinitescroll.CanvasView
android:id="@+id/canvas_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CanvasView canvas = findViewById(R.id.canvas_view);
String[][] labels = new String[][] {
{"5", "8", "2"},
{"4", "7", "1"},
{"3", "6", "9"}
};
int columns = 3;
int rows = 3;
canvas.with(labels, columns, rows);
}
}
CanvasView.java
public class CanvasView extends View {
private final Panning panning;
private final GridManager gridManager;
private Rect bounds;
private Point current = new Point(0, 0);
private List<Overlay> overlays;
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
bounds = new Rect();
panning = new Panning();
overlays = new ArrayList<>();
gridManager = new GridManager(this);
init();
}
public void with(String[][] labels, int columns, int rows) {
gridManager.with(labels, columns, rows);
}
private void init() {
ViewTreeObserver observer = getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = getWidth();
int height = getHeight();
bounds.set(0, 0, width, height);
gridManager.generate(bounds);
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
new Canvas(bitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bounds.offsetTo(-current.x, -current.y);
gridManager.generate(bounds);
canvas.translate(current.x, current.y);
for (Overlay overlay : overlays) {
if (overlay.intersects(bounds)) {
overlay.onDraw(canvas);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
current = panning.handle(event);
invalidate();
return true;
}
public void addChild(Overlay overlay) {
this.overlays.add(overlay);
}
}
GridManager.java
class GridManager {
private final CanvasView canvas;
private int columns;
private int rows;
private String[][] labels;
private final Map<String, Overlay> cache;
GridManager(CanvasView canvas) {
this.canvas = canvas;
cache = new HashMap<>();
}
void with(String[][] labels, int columns, int rows) {
this.columns = columns;
this.rows = rows;
this.labels = labels;
}
void generate(Rect bounds) {
if (columns == 0 || rows == 0 || labels == null) return;
int width = bounds.width();
int height = bounds.height();
int overlayWidth = width / columns;
int overlayHeight = height / rows;
int minX = mod(floor(bounds.left, overlayWidth), columns);
int minY = mod(floor(bounds.top, overlayHeight), rows);
int startX = floorToMod(bounds.left, overlayWidth);
int startY = floorToMod(bounds.top, overlayHeight);
for (int j = 0; j <= rows; j++) {
for (int i = 0; i <= columns; i++) {
String label = getLabel(minX, minY, i, j);
int x = startX + i * overlayWidth;
int y = startY + j * overlayHeight;
String key = x + "_" + y;
if (!cache.containsKey(key)) {
Overlay overlay = new Overlay(label, x, y, overlayWidth, overlayHeight);
cache.put(key, overlay);
canvas.addChild(overlay);
}
}
}
}
private String getLabel(int minX, int minY, int i, int j) {
int m = mod(minX + i, columns);
int n = mod(minY + j, rows);
return labels[n][m];
}
private int floor(double numerator, double denominator) {
return (int) Math.floor(numerator / denominator);
}
private int floorToMod(int value, int modulo) {
return value - mod(value, modulo);
}
private int mod(int value, int modulo) {
return (value % modulo + modulo) % modulo;
}
}
Panning.java
class Panning {
private Point start;
private Point delta = new Point(0, 0);
private Point cursor = new Point(0, 0);
private boolean isFirst;
Point handle(MotionEvent event) {
final Point point = new Point((int) event.getX(), (int) event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
press();
break;
case MotionEvent.ACTION_MOVE:
drag(point);
break;
}
return new Point(cursor.x + delta.x, cursor.y + delta.y);
}
private void press() {
isFirst = true;
}
private void drag(final Point point) {
if (isFirst) {
start = point;
cursor.offset(delta.x, delta.y);
isFirst = false;
}
delta.x = point.x - start.x;
delta.y = point.y - start.y;
}
}
Overlay.java
class Overlay {
private final String text;
private final int x;
private final int y;
private final Paint paint;
private final Rect bounds;
private final Rect rect;
private final Rect textRect;
Overlay(String text, int x, int y, int width, int height) {
this.text = text;
this.bounds = new Rect(x, y, x + width, y + height);
this.rect = new Rect();
this.textRect = new Rect();
paint = new Paint();
paint.setColor(Color.BLACK);
setTextSize(text);
this.x = x + width / 2 - textRect.width() / 2;
this.y = y + height / 2 + textRect.height() / 2;
}
boolean intersects(Rect r) {
rect.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
return rect.intersect(r.left, r.top, r.right, r.bottom);
}
void onDraw(Canvas canvas) {
// rectangle
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(bounds, paint);
// centered text
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
canvas.drawText(text, x, y, paint);
}
private void setTextSize(String text) {
final float testTextSize = 100f;
paint.setTextSize(testTextSize);
paint.getTextBounds(text, 0, text.length(), textRect);
}
}