Currently I have a custom SurfaceView for a specific size of Panels that I used for my project. But I'm looking into expanding it hence I need a ScrollView to scroll it accordingly. But I'm not sure how do I merge the 2 together.
My SurfaceView is using a .java file to create its layout. It is not using .xml to create the layout.
//MySurfaceView.class
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback , Runnable{
private SurfaceHolder surfaceHolder;
private boolean isDestroyed = false;
private Canvas canvas;
private Paint paint;
private int maxWidth;
private int maxHeight;
private Resources resources;
int offset;
final byte ON=1;
final byte OFF=0;
int[] ledPositionControl = new int[97];
int ledBmpSize;
int positionControlSize;
int maxControl=96;
int sizeControl=0;
int row;
int col;
public MySurfaceView(Context context) {
super(context);
resources = context.getResources();
init(); //load pictures
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
paint =new Paint();
}
This is the class that runs the SurfaceView.
//Class that runs the SurfaceView Layout
public class drawingMode extends Activity implements OnClickListener {
public static int screenWidth;
public static int screenHeight;
private SharedPreferences sPrefs;
final byte ON = 1;
final byte OFF = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(new MySurfaceView(this));
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
screenWidth = metric.widthPixels;
screenHeight = metric.heightPixels;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Now how do I merge this SurfaceView into a ScrollView Layout? I have a .xml file that has a ScrollView inside but I tried to put the SurfaceView via tag wise through .xml but it didn't worked. I also tried the .addView and it didn't work too gave me some errors.
//I put this in a the onCreate of a class.
myScrollView = new ScrollView(getApplicationContext());
myScrollView.addView(new MySurfaceView(this));
setContentView(R.layout.scrollsurfaceview);
Firstly, you didn't specify LayoutParams. Secondly, you had a wrong setContentView. The best way is to place ScrollView in layout.xml. If you rather prefer to do in in the code, here is a hint:
ScrollView myScrollView = new ScrollView(this);
myScrollView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, MATCH_PARENT));
MySurfaceView myView = new MySurfaceView(this);
myView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, myHeight));
myScrollView.addView(myView);
setContentView(myScrollView); // !!!!!!
Related
I know this should be easy but I am still learning and I am unsure how to get the AdMob banner to display at the top (stretched in width to fill the screen) without overlaying the game. This is written without any XML files and below is the code the I have that just displays the ad at the top of the screen overlaying the game.
Thank you guys in advance for any help you can provide.
public class Screen extends Activity implements Runnable, OnTouchListener, SensorEventListener {
private SurfaceHolder holder;
private boolean locker = true, initialised = false;
private Thread thread;
//public WakeLock WL;
private int width = 0, height = 0;
public float cameraX = 0, cameraY = 0;
public Activity activity = this;
public boolean debug_mode = false;
private long now = SystemClock.elapsedRealtime(), lastRefresh, lastfps;
public SurfaceView surface;
private int fps = 0, frames = 0, runtime = 0, drawtime = 0;
//sensor
SensorManager sm;
Sensor s;
float sensorx, calibratex = 0;
float sensory, calibratey = 0;
private boolean default_lanscape = false;
private int default_lanscape_rotation = 0;
//world origin
public final int TOP_LEFT = 0, BOTTOM_LEFT = 1;
public int origin = TOP_LEFT;
//layout
public RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
//full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//create surface
layout = new RelativeLayout(this);
surface = new SurfaceView(this);
setContentView(layout);
layout.addView(surface);
AdView ad = new AdView(this, AdSize.BANNER, "XXXXXXXX");
//layout
layout.addView(ad);
AdRequest request = new AdRequest();
AdRequest adRequest = new AdRequest();
adRequest.addTestDevice("xxxxxxxxxxxxxxxxx");
ad.loadAd(request);
holder = surface.getHolder();
//listeners
surface.setOnTouchListener(this);
// start game loop
thread = new Thread(this);
thread.start();
onCreate();
}
You really need to read about and understand how Android layouts or you aren't going to understand any help that is offered. http://developer.android.com/guide/topics/ui/declaring-layout.html
Having said that, start by replacing the RelativeLayout with a LinearLayout. And I strongly recommend you use an XML layout. You are far less likely to get lost especially since you are new to this.
i want to call the start method defined in Gameview class from the NewGame activity.basically i want to add onclicklistener and want to perform task specified inthe start() method whenever the button is clicked
activity:
public class NewGame extends Activity implements OnClickListener {
GameView gameview;
#Override
public void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//gameview=new GameView(this);
setContentView(R.layout.activity_new_game);
View startbutton=findViewById(R.id.start_button);
startbutton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_button:
gameview.start(this);
}
}
view:
public class GameView extends View {
Path circle;
Paint cPaint;
Paint tPaint;
String z;
GameView a;
int i=65,strt,arc,leftx,topy,rightx,bottomy,maxx,maxy,minx,miny;
boolean flag1,flag2,flag3;
double n1,n2;
int n,n3=180,n4,n5=90;
float f1=180,f2=90;
int width;
int height;
Random r=new Random();
RectF oval;
public GameView(Context context,AttributeSet attrs ) {
super(context,attrs);
leftx=0;
topy=60;
rightx=150;
bottomy=120;
z= String.valueOf(Character.toChars(i));
cPaint = new Paint();
cPaint.setColor(Color.RED);
strt=45;
arc=315;
n1=Math.random()*600;
Log.d("random",z);
this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// cPaint.setStrokeWidth(2);
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setColor(Color.BLACK);
float scale = getResources().getDisplayMetrics().scaledDensity;
tPaint.setTextSize(20 * scale);
}
public void start(Context context)
{
if (flag2==false)
new DrawThread(this);
}
Your gameView object is currently null. If you have it in your XML layout file, you should instantiate it in onCreate with a line like this:
gameView = (GameView) findViewById(R.id.gameView);//where gameView is the id specified in your layout file (R.layout.main, or something)
If it is not in your layout file, you need to instantiate it and add it to your layout:
gameView = new GameView(this);
gameView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
ViewGroup content = (ViewGroup) findViewById(android.R.id.content).getRootView();
content.addView(gameView);
now you will not get null pointer exceptions, and your gameview will fill the screen.
class PlayAreaView extends View{
private static final String DEBUG_TAG = "PlayAreaView";
private SeekBar sizeSlider;
private int xMin = 0;
private int xMax;
private int yMin = 0;
private int yMax;
private Rect rect;
private GestureDetector gestures;
private Paint p = new Paint();
private int side = 50;
public PlayAreaView(Context context){
super(context);
rect = new Rect(0,0,side,side);
p.setARGB(255, 255, 255, 255);
GestureListener listener = new GestureListener(this);
gestures = new GestureDetector(listener);
sizeSlider = (SeekBar) findViewById(R.id.seek);
//sizeSlider.setOnSeekBarChangeListener(listener);
}
I am new to developing on Android and am having trouble figuring out what is wrong here. I am getting a NullPointerException at the commented out line. I believe it is because I am asking to findViewById in a class that is not the main activity. If this is indeed the problem how can I access UI elements from this class.
As you have set up, findViewById(R.id.seek) will search for a subview with ID equal to R.id.seek within PlayAreaView, which does not exist since you seem to have the SeekBar in your main layout.
If you must access The SeekBar from within this view, pass in a reference to it while instantiating it, e.g., in the main activity
SeekBar sizeSlider = (SeekBar)findViewById(R.id.seek);
PlayAreaView areaView = new PlayAreaView(this, sizeSlider);
and in PlayAreaView,
SeekBar sizeSlider;
public PlayAreaView(Context context, SeekBar seekBar) {
super(context);
sizeSlider = seekBar;
...
seekBar.setOnSeekBarChangeListener(...);
}
then, the SeekBar instance can be accessed through the instance variable sizeSlider from PlaAreaView.
I have a FrameLayout containing a subclassed SurfaceView and an ImageView. I want to do a TranslateAnimation on the ImageView. The only way I can make it work is to add a vacuous View to the FrameLayout. Otherwise, the ImageView gets clipped (to the bounds of the ImageView's position at the start of the animation) during the animation.
I'm curious as to why the empty sibling View allows the ImageView to animate correctly. The line that makes it work is marked with a comment in the code below.
public class Test5 extends Activity {
private static final String TAG = "Test5";
private MySurfaceView mMSV;
private ImageView mRectView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMSV = new MySurfaceView(this);
mRectView = new ImageView(this);
ShapeDrawable sd = new ShapeDrawable(new RectShape());
sd.getPaint().setColor(Color.RED);
sd.setIntrinsicWidth(300);
sd.setIntrinsicHeight(100);
mRectView.setImageDrawable(sd);
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
// I don't know why the following line prevents clipping during
// animation. It simply adds a vacuous View.
frameLayout.addView(new View(this));
setContentView(frameLayout);
} // onCreate
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas can = mMSV.getHolder().lockCanvas();
can.drawColor(Color.GRAY);
mMSV.getHolder().unlockCanvasAndPost(can);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
Log.v(TAG, String.format("ACTION_UP, w=%d, h=%d", mRectView
.getWidth(), mRectView.getHeight()));
Animation an = new TranslateAnimation(0f, 200f, 0f, 200f);
// Animation an = new RotateAnimation(0f, 90f);
an.setStartOffset(200);
an.setDuration(1000);
mRectView.startAnimation(an);
}
return true;
}
} // MySurfaceView
} // Test5
This is interesting... I guess that the size of the FrameLayout is changed when a vacuous view is added. Your frame layout does not fill the parent, I wonder if you change the layout params to fill parent, what would happen?
I simplified your code to this:
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, 50, 50);
frameLayout.addView(new View(this)); //expands frame layout
It seems that the FrameLayout size itself equal to the last added child view. If you set addView(new View(this)) before adding a rectangle then it reduces to 50 x 50 and animation is clipped. I assume that addView(new View(this)); expands FrameLayout to the full screen.
I don't know how you figured that out, but it seemed to work for me, too. I had just switched to using a SurfaceView, and noticed that the animations were getting clipped. Adding an empty View stopped the clipping.
the trick was setting setClipChildren to the
layout that enclosed the view.
When I comment out setContentView(boardView); in my Game.java my custom view in BoardView works fine and displays everything nicely... but onSizeChanged never gets called in BoardView.java... so I can't read the device width and height at runtime. If I leave setContentView uncommented onSizeChanged works... but the screen is blank!
I want to be able to read the screen width and height at runtime and set the sizes of my ImageViews at creation so they are the optimal size.
public class Game extends Activity implements OnClickListener{
private BoardView boardView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boardView = new BoardView(this);
setContentView(boardView); // when this line disabled, it looks ok
boardView.requestFocus();
}
public class BoardView extends View {
private final Game game;
private float width; // width of one unit
private float height; // height of one unit
public BoardView(Context context){
super(context);
this.game = (Game)context;
setFocusable(true);
setFocusableInTouchMode(true);
LinearLayout maincontainer = new LinearLayout(game);
maincontainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
maincontainer.setGravity(Gravity.CENTER);
maincontainer.setOrientation(LinearLayout.VERTICAL);
maincontainer.setBackgroundColor(Color.BLACK);
LinearLayout innercontainer = new LinearLayout(game);
innercontainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
innercontainer.setGravity(Gravity.CENTER);
innercontainer.setOrientation(LinearLayout.HORIZONTAL);
// declare a new table
TableLayout layout = new TableLayout(game);
layout.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
// build a grid of ImageViews in a TableLayout
for (int f=1; f<=7; f++) {
TableRow tr = new TableRow(game);
for (int c=1; c<=7; c++) {
ImageView b = new ImageView(game);
b.setImageResource(R.drawable.neworb);
b.setOnClickListener(game);
tr.addView(b, 30,30); // I'd like to not use fixed values here
} // for
layout.addView(tr);
} // for
innercontainer.addView(layout);
maincontainer.addView(innercontainer);
game.setContentView(maincontainer);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
width = w/9f;
height = width;
super.onSizeChanged(w, h, oldw, oldh);
}
}
}
Thought I solved my own problem. I was neglecting to place my my view building code withing the Overriden onDraw method. i.e.:
#Override
protected void onDraw(Canvas canvas)
{
LinearLayout maincontainer = new LinearLayout(this.game);
// etc..
I was just including it within the main class and not Overriding onDraw... which you gotta do when you extend View.