I am making a grid-based game that will be much larger than the screen, and the user would scroll around in it. I basically put a bunch on ImageViews inside of a custom class that extends a relative layout. The problem is that even though RelativeLayout.LayoutParams is set to the correct size I want (1280*1280). The images are crammed against the sides of the screen and don’t extend past it. I have got the scrolling logic working, and when I scroll, I can see it is a rectangle of images the size of one screen. How can I make it so the images extend past the screen?
The class that extends a relative layout:
public class GameGrid extends RelativeLayout {
ImageView[][] subViews;
int rows=0, cols=0, cellsize=0;
int width, height;
//Dragging variables
float startX;
float startY;
float lastX;
float lastY;
boolean touching;
boolean dragging;
int clickedChild;
public GameGrid(Context context) {
super(context);
init();
}
public GameGrid(Context context, int rws, int cls, int clsze) {
super(context);
rows=rws;
cols=cls;
cellsize=clsze;
init();
}
public GameGrid(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GameGrid(Context context, AttributeSet attrs, int defaultStyles) {
super(context, attrs, defaultStyles);
init();
}
public void init() {
rows=10;
cols=10;
cellsize=128;
startX = 0;
startY = 0;
lastX=0;
lastY=0;
touching = false;
dragging = false;
clickedChild = -1;
subViews = new ImageView[cols][rows];
setLayoutParams(new RelativeLayout.LayoutParams(cellsize*cols,cellsize*rows));
width=this.getLayoutParams().width;
height=this.getLayoutParams().height;
this.setMinimumWidth(width);
this.setMinimumHeight(height);
Log.i("info","****************");
Log.i("info","GameGrid Made.");
Log.i("info","width: "+width+"\nheight: "+height);
Log.i("info","****************");
makeGrid();
// this.setOnTouchListener()
}
public boolean getDragging(){
return dragging;
}
public void makeGrid() {
for(int y=0;y<rows;y++){
for(int x=0;x<cols;x++){
ImageView temp = new ImageView(getContext());
temp.setImageResource(R.drawable.water1);
temp.setScaleType(ImageView.ScaleType.FIT_XY);
RelativeLayout.LayoutParams temp2 = new RelativeLayout.LayoutParams(width/cols,height/rows);
if (x == 0 && y == 0){ //If this is the first view being made, set it relative to the parent.
temp2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
temp2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
else if (x == 0){ //If this is in the first column, set it below the one above.
temp2.addRule(RelativeLayout.ALIGN_LEFT,subViews[0][y-1].getId());
temp2.addRule(RelativeLayout.BELOW,subViews[0][y-1].getId());
}
else { //Align the bottom with first one of that row.
temp2.addRule(RelativeLayout.RIGHT_OF,subViews[x-1][y].getId());
temp2.addRule(RelativeLayout.ALIGN_BOTTOM,subViews[0][y].getId());
}
temp.setLayoutParams(temp2);
subViews[x][y]=temp;
subViews[x][y].setId(x+y*cols+1);
// Toast.makeText(getContext(), "" + v.getId(), Toast.LENGTH_SHORT).show();
subViews[x][y].setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v,MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
clickedChild = v.getId();
return false;
}
});
addView(temp);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{ // when the user touches the screen
startX = event.getX();
startY = event.getY();
lastX = event.getX();
lastY = event.getY();
touching = true;
dragging = false;
return true;
}
else if (event.getAction() == MotionEvent.ACTION_MOVE)
{ // when the user moves the touch
if (!dragging)
dragging = true;
int distX = (int)(event.getX()-lastX);
int distY = (int)(event.getY()-lastY);
this.scrollBy(-distX, -distY);
lastX = event.getX();
lastY = event.getY();
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{ // when the user lifts the touch
if (!dragging){
if (clickedChild>0){
Toast.makeText(getContext(), "getHeight()= " + getHeight(), Toast.LENGTH_SHORT).show();
clickedChild = -1;
}
}
touching = false;
dragging = false;
return true;
}
else if (event.getAction() == MotionEvent.ACTION_CANCEL)
{ // if something gets lost in translation
startX = 0;
startY = 0;
lastX=0;
lastY=0;
touching = false;
dragging = false;
return true;
}
return false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth, parentHeight);
}
The Activity:
public class Attacktics2 extends Activity {
/** Called when the activity is first created. */
GameGrid grid;
int rows, cols, cellsize;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
}
public void start(View view) {
view.setVisibility(View.GONE);
grid = new GameGrid(this,10,10,128);
setContentView(grid);
}
}
Since you’re already doing the heavy lifting of managing all the scrolling, I’d suggest that you implement your entire layout logic yourself and not rely on RelativeLayout. Except for ScrollView and HorizontalScrollView, the stock layout classes are going to restrict their children to be within the parent bounds. Those, in turn, will be restricted to the screen dimensions. If you handle the layout logic yourself, you can position child views so that they extend off screen. It then forms a viewport into a larger grid and can just render those children that are visible within the viewport.