I am working on a small game with touch-motion, bluetooth, and menus. At the moment the code is implemented is in my custom View.
For example vectors of classes that store game-data, vectors for current data and later will there be some threads for animations and timers.
Yet there is no icons for "abilities", but I will implement them too.
Later will there be a process or a service with bluetooth which also calls methods which are at the moment in the custom view class.
I suppose this is a bad design - so I have no concrete idea how I can or should move my functions to for example the activity which holds the custom view and how to let the custom view and activity communicate with each other.
Maybe some of you have advice on what to do.
Here is the activity:
Gamecontroller_Activity:
public class Gamecontroller_Activity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Enter Function","Enter onCreate Gamecontroler_Activity");
setContentView(R.layout.activity_gamecontroller);
}
}
activity_gamecontroller.xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.calma.Gamecontroller_View
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
And the big custom view class (shorted) Gamecontroller_View.java:
public class Gamecontroller_View extends View implements OnGestureListener{
//Touch
private PointF fingerpointer;
private int totalClickt;
private static final int SIZE = 60;
private Paint mPaint;
//Text Flashes
private Paint textPaint;
private Paint textPaintAction;
private String currentMsg;
private boolean currentMsgShow;
//Drawables (Pictures)
private int monsterscale;
private int monsterMinimumBorderX;
private int monsterMinimumBorderY;
private Bitmap bitmap1,bitmap2;
private HashMap<String, Bitmap> hashmapMonsterStandartBitmap;
Display Informations;
private DisplayMetrics displayMetrics;
private int xDisplayMaximum;
private int yDisplayMaximum;
//Monsters
private Vector<Monster> currentMonsters;
private int monsterCountGlobal;
//Player Stats
private Player playerMe;
//Enemy Player Stats
private Player playerEnemy;
public Gamecontroller_View(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public void initView(){
//display
displayMetrics = new DisplayMetrics();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
float displayPixelFactor = displayMetrics.widthPixels/displayMetrics.densityDpi;
xDisplayMaximum = displayMetrics.widthPixels ;
yDisplayMaximum = displayMetrics.heightPixels - (3*getStatusBarSizes());
Log.i("Display","displaywidthpixels/displayMetrics: "+xDisplayMaximum);
//yDisplayMaximum
//Enemy Player
playerEnemy = new Player();
//Monsters
monsterscale =10;
monsterMinimumBorderX= Math.min(xDisplayMaximum,yDisplayMaximum)/monsterscale;
monsterMinimumBorderY= Math.max(xDisplayMaximum,yDisplayMaximum)/monsterscale;
hashmapMonsterStandartBitmap = new HashMap<String,Bitmap>();
currentMonsters = new Vector<Monster>();
monsterCountGlobal = 0;
Log.i("display","Monsterscale: "+monsterscale + " minMonsterBorder: "+monsterMinimumBorderX);
//init Touch detection and draw
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setMaskFilter(new BlurMaskFilter(15, Blur.OUTER));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//init Text wich will be drawn
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(30);
textPaintAction = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaintAction.setTextSize(60);
currentMsg = "";
currentMsgShow = false;
//Futher init stuff
initPlayerMe();
initPlayerEnemy();
enemySpawn();
preloadImages();
showDebug();
}
public void initPlayerMe(){
//Player
playerMe = new Player();
playerMe.setlife(100);
playerMe.setMoney(0);
playerMe.setStrength(1);
}
public void initPlayerEnemy(){
//Player
playerEnemy = new Player();
playerEnemy.setlife(100);
playerEnemy.setMoney(0);
playerEnemy.setStrength(1);
}
public Vector<Dimension> findPlaceForMonsters(int n){
//First Collect allready existing Monster Coordinates
Vector <Dimension> currentPlaces = new Vector<Dimension>();
Vector <Dimension> newPlaces = new Vector<Dimension>();
for(int i = 0; i< currentMonsters.size();i++){
if (currentMonsters.elementAt(i) != null){
currentPlaces.add(currentMonsters.elementAt(i).getDimension());
}
}
for (int i=0; i < n ;i++){
newPlaces.add(new Dimension(getRandomNumberBetween(0, xDisplayMaximum-monsterMinimumBorderX),
getRandomNumberBetween(0, yDisplayMaximum-monsterMinimumBorderY)));
Log.i("randomPlaces","Point xy: " + newPlaces.lastElement().getX()+ " "+newPlaces.lastElement().getY());
}
Log.i("findPlfaceForMonsters",this.monsterMinimumBorderX+" "+this.monsterMinimumBorderY);
return newPlaces;
}
public void enemySpawn(){
int tempCount =0;
Vector<Dimension> newPlaces = findPlaceForMonsters(6);
for(int i=0; i < 2;i++){
currentMonsters.add(new MonsterMedium(monsterCountGlobal));
currentMonsters.lastElement().setDimension(new Dimension(newPlaces.elementAt(tempCount).getX(),newPlaces.elementAt(tempCount).getY(),monsterMinimumBorderX,monsterMinimumBorderY));
monsterCountGlobal++;
tempCount++;
}
for(int i=0; i < 2;i++){
currentMonsters.add(new MonsterSmall(monsterCountGlobal));
currentMonsters.lastElement().setDimension(new Dimension(newPlaces.elementAt(tempCount).getX(),newPlaces.elementAt(tempCount).getY(),monsterMinimumBorderX,monsterMinimumBorderY));
monsterCountGlobal++;
tempCount++;
}
for(int i=0; i < 2;i++){
currentMonsters.add(new MonsterHeavy(monsterCountGlobal));
currentMonsters.lastElement().setDimension(new Dimension(newPlaces.elementAt(tempCount).getX(),newPlaces.elementAt(tempCount).getY(),monsterMinimumBorderX,monsterMinimumBorderY));
monsterCountGlobal++;
tempCount++;
}
}
public void attackMonster(int id){
for (int i=currentMonsters.size()-1; i >= 0; i--){
if (currentMonsters.elementAt(i).getID() == id){
int restlife = currentMonsters.elementAt(i).setDamge(this.playerMe.getStrength());
lifeOfMonsterChanged(currentMonsters.elementAt(i).getID(),i,restlife);
break;
}
}
}
public void lifeOfMonsterChanged(int id,int index, int life){
if (life <= 0){
Log.i("MonsterTouchted", "Monster tot");
currentMonsters.removeElementAt(index);
}
else{
Log.i("MonsterTouchted", "Monster "+id+" restlife: "+life);
//effekte? (shake?) farbE?
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// get pointer index from the event object
int pointerIndex = event.getActionIndex();
// get pointer ID
int pointerId = event.getPointerId(pointerIndex);
Log.i("touch","event.getPointerID(): "+pointerId);
// get masked (not specific to a pointer) action
int maskedAction = event.getActionMasked();
switch (maskedAction) {
//Detection of a finger touch
case MotionEvent.ACTION_DOWN:
totalClickt = totalClickt+1;
//attackTheMonster(currentPlayer.attack());
fingerpointer = new PointF();
fingerpointer.x = event.getX(0);
fingerpointer.y = event.getY(0);
for (int i=currentMonsters.size()-1; i >= 0; i--){
if(currentMonsters.elementAt(i).getDimension().contains((int)fingerpointer.x, (int)fingerpointer.y)){
Log.i("MonsterTouchted","MonsterTouched: index: "+i);
attackMonster(currentMonsters.elementAt(i).getID());
break;
}
}
case MotionEvent.ACTION_POINTER_DOWN:
{
// Optional more than one finger
break;
}
case MotionEvent.ACTION_MOVE:
{ // a pointer was moved
if (fingerpointer != null) {
fingerpointer.x = event.getX(0);
fingerpointer.y = event.getY(0);
}
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL: {
fingerpointer = null;
break;
}
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw all pointers
if (fingerpointer != null){
mPaint.setColor(colors[0]);
canvas.drawCircle(fingerpointer.x, fingerpointer.y, SIZE, mPaint);
}
// draw mosnters
for(int i=0; i < currentMonsters.size();i++){
if( currentMonsters.elementAt(i) != null){
canvas.drawBitmap(hashmapMonsterStandartBitmap.get(currentMonsters.elementAt(i).getImagePath()), currentMonsters.elementAt(i).getDimension().getX(), currentMonsters.elementAt(i).getDimension().getY(), mPaint); //bitmap, abstand left, abstand top, paint
} else{
Log.i("Failure","Draw monster nullpointer bei index: "+i);
}
}
//draw extra texts
if(currentMsgShow){
Log.i("onDraw","enter currenMsgShow");
if(displayMetrics != null){
int textsize = (int) textPaintAction.measureText(currentMsg);
int sidespacing = (displayMetrics.widthPixels - textsize)/2;
canvas.drawText(currentMsg, sidespacing, displayMetrics.heightPixels/5 , textPaintAction);
}
}
//Draw extratext
canvas.drawText( "Total Clickt: " + totalClickt, 10, 40 , textPaint);
}
}
Project:
Make those changes:
1) in your activity_gamecontroller.xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.calma.Gamecontroller_View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/myGameController"/>
</RelativeLayout>
2) in your Gamecontroller_Activity:
public class Gamecontroller_Activity extends Activity {
Gamecontroller_View mGameControllerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Enter Function","Enter onCreate Gamecontroler_Activity");
setContentView(R.layout.activity_gamecontroller);
mGameControllerView = (Gamecontroller_View) findViewById(R.id.myGameController);
}
}
3) now you can call for example mGameControllerView.initPlayerMe(); from any method in your Gamecontroller_Activity .
This is an example:
public class Gamecontroller_Activity extends Activity {
Gamecontroller_View mGameControllerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Enter Function","Enter onCreate Gamecontroler_Activity");
setContentView(R.layout.activity_gamecontroller);
mGameControllerView = (Gamecontroller_View) findViewById(R.id.myGameController);
testMethod();
}
private void testMethod(){
mGameControllerView.enemySpawn();
}
}
Related
I am trying to draw bullets on the screen when the player presses, but
after a few bullets I get the following error: FATAL EXCEPTION: Thread-2
Here is the classes of the bullet and of the gameView
public class Bullet {
private int x;
private int y;
private int speed;
private Bitmap bitmap;
public Bullet(Context context,int PositionX,int PositionY) {
Log.v("i am in bullet"," come on!!!");
speed = 10;
x = PositionX;
y = PositionY;
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.flash);
}
public void update() {
//Log.v("i am in update bullet"," come on!!!");
//animating the star horizontally right side
//by increasing x coordinate with player speed
x += 20;
}
public Bitmap getBitmap(){return bitmap;}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
returns
public class GameView extends SurfaceView implements Runnable {
private long fps;
private long timeThisFrame;
volatile boolean playing;
private Thread gameThread = null;
private Player player;
//a screenX holder
int screenX;
int i=0;
//context to be used in onTouchEvent to cause the activity transition from GameAvtivity to MainActivity.
Context context;
//the score holder
int score;
//the high Scores Holder
int highScore[] = new int[4];
//Shared Prefernces to store the High Scores
SharedPreferences sharedPreferences;
//to count the number of Misses
int countMisses;
//indicator that the enemy has just entered the game screen
boolean flag ;
//an indicator if the game is Over
private boolean isGameOver ;
private Paint paint;
private Canvas canvas;
private SurfaceHolder surfaceHolder;
private Enemy enemies;
//created a reference of the class Friend
private Friend friend;
//private Bullet bullet;
private ArrayList<Star> stars = new
ArrayList<Star>();
private ArrayList<Bullet> bullet = new
ArrayList<Bullet>();
//defining a boom object to display blast
private Boom boom;
//the mediaplayer objects to configure the background music
static MediaPlayer gameOnsound;
final MediaPlayer killedEnemysound;
final MediaPlayer gameOversound;
public GameView(Context context, int screenX, int screenY) {
super(context);
player = new Player(context, screenX, screenY);
surfaceHolder = getHolder();
paint = new Paint();
//initializing context
this.context = context;
int starNums = 20;
for (int i = 0; i < starNums; i++) {
Star s = new Star(context,screenX, screenY);
stars.add(s);
}
enemies = new Enemy(context,screenX,screenY);
//initializing boom object
boom = new Boom(context);
//initializing the Friend class object
friend = new Friend(context, screenX, screenY);
//setting the score to 0 initially
score = 0;
//setting the countMisses to 0 initially
countMisses = 0;
this.screenX = screenX;
isGameOver = false;
//initializing shared Preferences
sharedPreferences = context.getSharedPreferences("SHAR_PREF_NAME",Context.MODE_PRIVATE);
//initializing the array high scores with the previous values
highScore[0] = sharedPreferences.getInt("score1",0);
highScore[1] = sharedPreferences.getInt("score2",0);
highScore[2] = sharedPreferences.getInt("score3",0);
highScore[3] = sharedPreferences.getInt("score4",0);
//initializing the media players for the game sounds
gameOnsound = MediaPlayer.create(context,R.raw.gameon);
killedEnemysound = MediaPlayer.create(context,R.raw.killedenemy);
gameOversound = MediaPlayer.create(context,R.raw.gameover);
//starting the music to be played across the game
gameOnsound.start();
}
#Override
public void run() {
while (playing) {
long startFrameTime = System.currentTimeMillis();
synchronized (surfaceHolder) {
update();
draw();
control();
}
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
private void update() {
//incrementing score as time passes
score++;
player.update();
//setting boom outside the screen
boom.setX(-250);
boom.setY(-250);
for (Star s : stars) {
s.update(player.getSpeed());
}
for (Bullet b : bullet) {
b.update();
}
//setting the flag true when the enemy just enters the screen
if(enemies.getX()==screenX){
flag = true;
}
enemies.update(player.getSpeed(),getFps());
}
private void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.argb(500,135,206,250));
paint.setColor(Color.WHITE);
paint.setTextSize(20);
for (Star s : stars) {
canvas.drawBitmap(
s.getBitmap(),
s.getX(),
s.getY(),
paint);
}
for (Bullet b : bullet) {
canvas.drawBitmap(
b.getBitmap(),
b.getX(),
b.getY(),
paint);
}
canvas.drawBitmap(
player.getBitmap(),
player.getX(),
player.getY(),
paint);
canvas.drawBitmap( enemies.getBitmap(), enemies.getframeToDraw(), enemies.getwhereToDraw(), null);
//drawing the score on the game screen
paint.setTextSize(30);
canvas.drawText("Score:"+score,100,50,paint);
//drawing boom image
canvas.drawBitmap(
boom.getBitmap(),
boom.getX(),
boom.getY(),
paint
);
//draw game Over when the game is over
if(isGameOver){
paint.setTextSize(150);
paint.setTextAlign(Paint.Align.CENTER);
int yPos=(int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
canvas.drawText("Game Over",canvas.getWidth()/2,yPos,paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
private void control() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
gameThread.interrupt();
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
//stop the music on exit
public static void stopMusic(){
gameOnsound.stop();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
player.stopBoosting();
break;
case MotionEvent.ACTION_DOWN:
player.setBoosting();
break;
}
//if touch the player
if (player.getDetectCollision().contains((int)motionEvent.getX(), (int)motionEvent.getY())) {
Bullet b = new Bullet(context,player.getX()+player.getDetectCollision().width()
,player.getY()-(player.getDetectCollision().height()/2));
bullet.add(b);
Log.d("test", "touch not inside myEditText");
}
//if the game's over, tappin on game Over screen sends you to MainActivity
if(isGameOver){
if(motionEvent.getAction()==MotionEvent.ACTION_DOWN){
context.startActivity(new Intent(context,MainActivity.class));
}
}
return true;
}
public long getFps(){
return fps;
}
}
its possible to moving textview with accelometer?
im trying and get forceclose
slidame4.java
public class Slidame4 extends Activity implements SensorEventListener {
private Bitmap bit,bi,bitm;
private TableRow tblrow ;
private ImageView bimg;
private kotak hitam;
private TextView v ;
private List<kotak> tiles = null;
private List<TileView> tileViews = null;
private List<TableRow> tableRow = null;
private TableLayout tbl;
public int ukurangrid;
private SensorManager sensorManager;
private GameBoard coba;
private int lebar;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Resources r = getResources();
tbl = (TableLayout)findViewById(R.id.TableLayout1);
tblrow = new TableRow(this);
v= new TextView(this);
bimg = new ImageView(this);
//sensor
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
//lebar
Display display = getWindowManager().getDefaultDisplay();
lebar = (display.getWidth());
setContentView(R.layout.activity_slidame4);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.slidame4, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()) {
case R.id.hint:
Toast.makeText(getApplicationContext(), ""+lebar, Toast.LENGTH_SHORT).show();
break;
case R.id.highscore:
Toast.makeText(getApplicationContext(), "HIGH SCORE ", 3).show();
break;
case R.id.grid3:
ukurangrid = 3;
createGameBoard();
item.setChecked(true);
break;
case R.id.grid4:
ukurangrid = 4;
createGameBoard();
item.setChecked(true);
break;
case R.id.grid5:
ukurangrid = 5;
createGameBoard();
item.setChecked(true);
break;
default:
return super.onOptionsItemSelected(item);
}
return false;
}
private final void createGameBoard() {
TableLayout gLayout;
gLayout = (TableLayout) findViewById(R.id.TableLayout1);
gLayout.removeAllViews();
bi = BitmapFactory.decodeResource(getResources(), R.drawable.gambar);
coba = new GameBoard(this, bi, gLayout, lebar,ukurangrid);
bi.recycle();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = event.values;
// Movement
int x = (int)values[0];
int y = (int)values[1];
int z = (int)values[2];
coba.gerak(x, y, z);
}
}
protected void onResume() {
super.onResume();
sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
}
gameboard.java
public class GameBoard extends Activity {
private Bitmap bit;
private int layar,lebar_board,grid,x,y,z;
private Context context;
private GamePiece emptyGamePiece;
private SensorManager sensorManager;
private static GameBoard board=null;
private TableLayout gameLayout;
private List<GamePiece> gamePieces = null;
private List<TableRow> tableRow = null;
GameBoard(Context context, Bitmap bit, TableLayout gLayout,int lebar,int grid) {
this.context =context;
this.lebar_board=lebar;
this.bit = Bitmap.createScaledBitmap(bit, this.lebar_board,
this.lebar_board, true);
this.gameLayout = gLayout;
this.grid=grid;
init();
// TODO Auto-generated constructor stub
}
private void init() {
initializeLists();
createGamePieces();
addToGameScreen();
}
private void initializeLists() {
if (gamePieces == null) {
gamePieces = new ArrayList<GamePiece>(grid*grid);
} else {
for (int i = 0; i < gamePieces.size(); i++) {
gamePieces.get(i).getBitmap().recycle();
gamePieces = new ArrayList<GamePiece>(grid*grid);
}
}
tableRow = new ArrayList<TableRow>(grid);
for (int row = 0; row < (grid*grid); row++) {
tableRow.add(new TableRow(context));
}
}
private void createGamePieces() {
int gamePiece_width = bit.getWidth() / grid;
int gamePiece_height = bit.getHeight() / grid;
for (int row = 0; row < grid; row++) {
for (int column = 0; column < grid; column++) {
Bitmap bitm = Bitmap.createBitmap(bit, column
* gamePiece_width, row * gamePiece_height,
gamePiece_width, gamePiece_height);
if ((row == grid - 1) && (column == grid - 1)) {
bitm = Bitmap.createBitmap(gamePiece_width, gamePiece_height,
bitm.getConfig());
bitm.eraseColor(Color.BLACK);
emptyGamePiece = new GamePiece(context, bitm, row, column,row + "-" + column);
gamePieces.add(emptyGamePiece);
} else {
GamePiece tempGamePiece = new GamePiece(context, bitm, row,
column, row + "-" + column);
gamePieces.add(tempGamePiece);
}
} // end column
}// end row
bit.recycle();
}
public void addToGameScreen() {
TextView cek = new TextView(context);
cek.setText(x+" "+y);
Iterator<GamePiece> it = (shuffleGamePieces()).iterator();
for (int row = 0; row < grid; row++) {
for (int column = 0; column < grid; column++) {
tableRow.get(row).addView(it.next());
} // end column
gameLayout.addView(tableRow.get(row));
} // end row
gameLayout.addView(cek);
}
public List<GamePiece> shuffleGamePieces() {
Collections.shuffle(gamePieces);
gamePieces.remove(emptyGamePiece);
gamePieces.add(emptyGamePiece);
for (int row = 0; row < grid; row++) {
for (int column = 0; column < grid; column++) {
gamePieces.get(grid * row + column).setCurrent(row, column);
}
}
//numberOfMoves = 0;
return gamePieces;
}
public static void createGameBoard(Context context, Bitmap bit,
TableLayout gLayout, int lebar, int grid) {
board = new GameBoard(context,bit,gLayout,lebar,grid);
}
public void gerak(int x,int y,int z){
this.x=x;
this.y=y;
this.z=z;
}
}
in this case gerak(x,y,z) is trying to get value of accelometer and i put in gameboard.java
and got forceclose
logcat
05-18 04:22:43.619: E/AndroidRuntime(27662): java.lang.NullPointerException
05-18 04:22:43.619: E/AndroidRuntime(27662): at skripsi.slidame4.Slidame4.onSensorChanged(Slidame4.java:192)
05-18 04:22:43.619: E/AndroidRuntime(27662): at android.hardware.SystemSensorManager$ListenerDelegate$1.handleMessage(SystemSensorManager.java:204)
05-18 04:22:43.619: E/AndroidRuntime(27662): at android.os.Handler.dispatchMessage(Handler.java:99)
05-18 04:22:43.619: E/AndroidRuntime(27662): at android.os.Looper.loop(Looper.java:137)
05-18 04:22:43.619: E/AndroidRuntime(27662): at android.app.ActivityThread.main(ActivityThread.java:4931)
05-18 04:22:43.619: E/AndroidRuntime(27662): at java.lang.reflect.Method.invokeNative(Native Method)
05-18 04:22:43.619: E/AndroidRuntime(27662): at java.lang.reflect.Method.invoke(Method.java:511)
05-18 04:22:43.619: E/AndroidRuntime(27662): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
Look to your coba variable.
You create it only in the createGameBoard(); method.
This method is called only after you press the menu and select some options.
But, you are registering your SensorListener in the OnCreate method.
Look to your OnSensorChanged method:
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = event.values;
// Movement
int x = (int)values[0];
int y = (int)values[1];
int z = (int)values[2];
coba.gerak(x, y, z); // Look here.
}
}
If you are registering your SensorListener in the OnCreate, you have it before you create your coba variable. So, this method (OnSensorChanged) can be called before your GameBoard creation.
The OnSensorChanged is called almost every millisecond after the listener is registered.
What are you doing?
Activity Creation -> Sensor Listener Registered -> GameBoard creation
What is really happening?
Activity Creation -> Sensor Listener Registered -> OnSensorChanged called -> GameBoard creation
What you can do?
only check if the GameBoard is created or create a variable to indicate if the game is started.
Alt 1:
#Override
public void onSensorChanged(SensorEvent event) {
if (coba != null && event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = event.values;
// Movement
int x = (int)values[0];
int y = (int)values[1];
int z = (int)values[2];
coba.gerak(x, y, z);
}
}
Alt 2:
private boolean isGameInitialized = false;
private final void createGameBoard() {
TableLayout gLayout;
gLayout = (TableLayout) findViewById(R.id.TableLayout1);
gLayout.removeAllViews();
bi = BitmapFactory.decodeResource(getResources(), R.drawable.gambar);
coba = new GameBoard(this, bi, gLayout, lebar,ukurangrid);
bi.recycle();
this.isGameInitialized = true;
}
#Override
public void onSensorChanged(SensorEvent event) {
if (this.isGameInitialized && event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float[] values = event.values;
// Movement
int x = (int)values[0];
int y = (int)values[1];
int z = (int)values[2];
coba.gerak(x, y, z);
}
}
I'm developing a simple game like BSD robots. This game contains a rather large board (over 40 cells) and it doesn't look nice even at 10 inch tablet. My decision was to scroll (move) surface view and not to scale each figure which size is like finger spot.
I've read tons articles about surface view but I cannot understand how to move it?
My activity code:
package ru.onyanov.robots;
public class MainActivity extends Activity {
public BoardView board;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
board = new BoardView(this);
setContentView(board);
}
}
Class Board:
package ru.onyanov.robots;
public class BoardView extends SurfaceView {
private GameThread mThread;
private boolean running = false;
public final int sizeX = 50;
public final int sizeY = 35;
public final int cellSize = 64;
private int robotCount = 4;
public ArrayList<Cell> cells = new ArrayList<Cell>();
private ArrayList<Robot> robots = new ArrayList<Robot>();
private Hero hero;
public Bitmap imageCell;
public Bitmap imageRobot;
public Bitmap imageHero;
public BoardView(Context context) {
super(context);
makeGraphic();
constructCells();
constructRobots();
hero = new Hero(this, 3, 2, imageHero);
mThread = new GameThread(this);
getHolder().addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
mThread.setRunning(true);
mThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void makeGraphic() {
Bitmap cellImageSource = BitmapFactory.decodeResource(getResources(),
R.drawable.cell);
imageCell = Bitmap.createScaledBitmap(cellImageSource, cellSize,
cellSize, false);
imageRobot = BitmapFactory.decodeResource(getResources(),
R.drawable.robot);
imageHero = BitmapFactory.decodeResource(getResources(),
R.drawable.hero);
}
private void constructRobots() {
Robot robot;
Random rand = new Random();
for (int r = 0; r < robotCount; r++) {
int x = rand.nextInt(sizeX);
int y = rand.nextInt(sizeY);
robot = new Robot(this, x, y, imageRobot);
robots.add(robot);
}
return;
}
private void constructCells() {
Cell cell;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
cell = new Cell(this, x, y, imageCell);
cells.add(cell);
}
}
return;
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Cell cell;
for (int c = 0; c < cells.size(); c++) {
cell = cells.get(c);
cell.onDraw(canvas);
}
Robot robot;
for (int r = 0; r < robots.size(); r++) {
robot = robots.get(r);
robot.onDraw(canvas);
}
hero.onDraw(canvas);
}
public boolean onTouchEvent(MotionEvent e) {
int shotX = (int) e.getX();
int shotY = (int) e.getY();
if (e.getAction() == MotionEvent.ACTION_MOVE){
//TODO move board
showToast("move Board");
} else if (e.getAction() == MotionEvent.ACTION_UP) {
showToast("touchPoint: " + shotX + ", "+shotY);
hero.moveByDirection(shotX, shotY);
this.scrollTo(shotX, shotY);
}
return true;
}
public void showToast(String mes) {
Toast toast = Toast.makeText(getContext(), mes, Toast.LENGTH_LONG);
toast.show();
}
public class GameThread extends Thread {
private BoardView view;
public GameThread(BoardView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
while (running) {
Canvas canvas = null;
try {
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
onDraw(canvas);
}
canvas.scale(300, 300);
} catch (Exception e) {
} finally {
if (canvas != null) {
view.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
}
Some magic digits here are temporary. Now I just want to move BoardView;
The issue was to add x and y fields to SurfaceView, change them at onTouchEvent and draw all the elements in canvas with x- and y-offset. It's strange that I didn't recieved any answers...
I have a full-screen custom Gallery. Elements of the gallery have buttons and other interactive areas. Some user interface is done through dialog boxes that pop in front of the gallery; when a dialog box is dismissed, the user is taken back to the gallery.
Most of the time, this works fine. However, sometimes, after a dialog box is dismissed, the buttons stop taking user input. The gallery, on the other hand, still scrolls. What's even more bizarre, as soon as I scroll the gallery, the system processes those clicks I thought failed (pops up a dialog, etc.).
It is easy to say that the main UI thread is locked. Why is it locked? How do I unlock it? Any help will be appreciated. Below is the full code of the class.
UPDATE. One of the elements within the Gallery is a HorizontalScrollView. When I try scroll it, mouse messages come through; I stepped through them and saw that the scrollBy() and invalidate() are properly called. Then I printed out the message queue. The only event that passes through the main loop is 1006, which I assume is the Touch event. The Draw event, the 1000, never makes it. Once I scroll the Gallery back and forth -- lo and behold -- the message queue starts receiving the 1000's, so the HorizontalScrollView scrolls fine!
So the question becomes: what stops the Draw events, and how do I make sure they are sent to the queue?
public class PlayerGallery extends Gallery
{
// 4 buttons to display
private final static int BUT_BIRD = 0;
private final static int BUT_SCORE = 1;
private final static int BUT_ROUND = 2;
private final static int BUT_MOVE = 3;
private final static int N_BUTTONS = 4;
// button images
private final static Drawable[] imgButtons =
{
WonDraw.WW.bird,
WonDraw.WW.scores,
WonDraw.WW.moveSumm,
WonDraw.WW.lastMove,
};
// individual player views
private PlayerView[] views;
// card that was clicked in the current player view
private Card clickedCard = null;
// wonder that was clicked in the current player view
private Player clickedWonderPlayer = null;
// one player
private final class PlayerView extends RelativeLayout
implements OnClickListener
{
// base view ID for the buttons
private final static int BUT_VIEW_ID = 200;
// player to display
final Player player;
// drawing data
private PlayerDisplay pd = null;
// the sub-view on top that shows player's hand
private HandView handView = null;
// button that takes user into bird's view
private final GlassButton[] buttons = new GlassButton[N_BUTTONS];
public PlayerView(Player player)
{
super(WonActivity.W.getApplicationContext());
setBackgroundColor(Color.TRANSPARENT);
this.player = player;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
lp.addRule(ALIGN_PARENT_TOP);
handView = new HandView();
addView(handView, lp);
for (int i = 0; i < buttons.length; ++i)
{
lp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
if (i % 2 == 0)
lp.addRule(ALIGN_PARENT_RIGHT);
else
lp.addRule(LEFT_OF, buttons[i - 1].getId());
lp.addRule(BELOW, i / 2 == 0 ? handView.getId() : buttons[i - 2].getId());
GlassButton but = new ImgGlassButton(GlassButton.ROUND, imgButtons[i]);
but.setId(BUT_VIEW_ID + i);
but.setOnClickListener(this);
buttons[i] = but; addView(but, lp);
}
}
// reset for the next player
void reset(boolean useBigCards)
{
pd = WonActivity.W.getDisplay(player.id, useBigCards);
if (useBigCards)
{
handView.pd = pd;
handView.hand = WonActivity.W.getCurrentHand();
handView.setVisibility(VISIBLE);
handView.requestLayout();
handView.scrollTo(0, 0);
}
else
{
handView.pd = null;
handView.hand = null;
handView.setVisibility(GONE);
}
for (int i = BUT_ROUND; i <= BUT_MOVE; ++i)
buttons[i].setEnabled(Table.T.movesAvailable());
invalidate();
}
#Override
protected void dispatchSetPressed(boolean pressed)
{
// if I don't do that, bird button gets pressed when I scroll the gallery!
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
int x = (int)event.getX();
int y = (int)event.getY();
clickedCard = pd.findSmallCard(x, y);
clickedWonderPlayer = clickedCard == null && pd.isInWonder(x, y) ?
player : null;
}
return super.onTouchEvent(event);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(MeasureSpec.makeMeasureSpec(WonActivity.W.getWidth() - 2, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(WonActivity.W.getHeight(), MeasureSpec.EXACTLY));
setBackgroundColor(Color.TRANSPARENT);
setBackgroundDrawable(WonDraw.W.getWood());
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (pd == null) return;
canvas.save();
pd.draw(canvas, handView.hand, true);
canvas.restore();
}
public void onClick(View v)
{
switch (v.getId() - BUT_VIEW_ID)
{
case BUT_BIRD:
WonActivity.W.switchToBird(player.id);
break;
case BUT_SCORE:
WonActivity.W.showScoreDlg();
break;
case BUT_ROUND:
WonActivity.W.showRoundDlg();
break;
case BUT_MOVE:
break;
}
}
};
// custom adapter for the gallery: provides circular functionality
private class PGAdapter extends BaseAdapter
{
public int getCount()
{
return Integer.MAX_VALUE;
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
return views[position % views.length];
}
};
public PlayerGallery()
{
super(WonActivity.W.getApplicationContext());
setSpacing(0);
setBackgroundColor(Color.TRANSPARENT);
views = new PlayerView[Table.T.getPlayerCount()];
for (int i = 0; i < Table.T.getPlayerCount(); ++i)
views[i] = new PlayerView(Table.T.getPlayer(i));
setAdapter(new PGAdapter());
setHorizontalFadingEdgeEnabled(false);
setVerticalFadingEdgeEnabled(false);
}
// reset for the next player
void changeMovingPlayer()
{
for (int i = 0; i < views.length; ++i)
views[i].reset(i == WonActivity.W.getCurrentPlayerID());
setViewedPlayer(Math.max(WonActivity.W.getCurrentPlayerID(), 0));
}
// set the player whose buildings to view
void setViewedPlayer(int index)
{
int pos = Integer.MAX_VALUE / 2;
pos -= pos % views.length;
setSelection(pos + index);
views[index].requestFocus();
views[index].invalidate();
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
int kEvent = e2.getX() > e1.getX() ?
KeyEvent.KEYCODE_DPAD_LEFT :
KeyEvent.KEYCODE_DPAD_RIGHT;
onKeyDown(kEvent, null);
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
boolean b = super.onTouchEvent(event);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
if (event.getEventTime() - event.getDownTime() < WonActivity.CLICK_MS)
{
if (clickedCard != null)
WonActivity.W.showCardDlg(clickedCard);
else if (clickedWonderPlayer != null)
WonActivity.W.showWonderDlg(clickedWonderPlayer);
}
clickedCard = null;
clickedWonderPlayer = null;
break;
}
return b;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
WonActivity.W.resize(w, h);
super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
}
}
Since Android 2.3.1 there is a new feature for ScrollViews and Lists called OverScroll. With
android:overScrollMode="never"
I can turn it off, but if i don't wan't to turn it off how can I change the Color of it?
Afaik there is no way to do this. So I created one; presenting:
Graeme's Amazing Custom List View v2
I've created a custom view which performs overscroll for ListViews and for GridViews (XML example is for slightly more involved GridView but view works for both):
<CustomGlowListView android:id="#+id/searches"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/black"
android:layout_margin="10dp"
android:tag="GridView"
android:numColumns="3"
android:horizontalSpacing="8dp"
android:verticalSpacing="8dp">
</CustomGlowListView>
The CustomGlowListView looks like this:
public class CustomGlowListView extends RelativeLayout{
private ImageView underscrollEdge;
private ImageView underscrollGlow;
private ImageView overscrollGlow;
private ImageView overscrollEdge;
private AbsListView listView;
private final static float MAX_EDGE_SIZE = 11f;
private final static float MAX_GLOW_SIZE = 93f;
private float scrollDistanceSinceBoundary = 0;
private Rect paddingRectangle = new Rect();
GestureDetector listViewGestureDetector;
// Gives the option of short circuiting the overscroll glow fade (Such as by scrolling away from the overscrolled edge)
boolean interruptFade = false;
public CustomGlowListView(Context context, AttributeSet attrs)
{
super(context, attrs);
listViewGestureDetector = new GestureDetector(new ListViewGestureDetector());
if( getTag() == null ||
getTag().toString().equalsIgnoreCase("ListView")) { listView = new ListView(context); }
else if(getTag().toString().equalsIgnoreCase("GridView"))
{
listView = new GridView(context, attrs);
((GridView)listView).getSelector().getPadding(paddingRectangle);
}
listView.setId(android.R.id.list);
listView.setOverScrollMode(OVER_SCROLL_NEVER);
addView(listView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
underscrollEdge = new ImageView(context);
underscrollEdge.setImageResource(R.drawable.underscroll_edge);
underscrollEdge.setScaleType(ScaleType.FIT_XY);
underscrollGlow = new ImageView(context);
underscrollGlow.setImageResource(R.drawable.underscroll_glow);
underscrollGlow.setScaleType(ScaleType.FIT_XY);
overscrollGlow = new ImageView(context);
overscrollGlow.setImageResource(R.drawable.overscroll_glow);
overscrollGlow.setScaleType(ScaleType.FIT_XY);
overscrollEdge = new ImageView(context);
overscrollEdge.setImageResource(R.drawable.overscroll_edge);
overscrollEdge.setScaleType(ScaleType.FIT_XY);
addView(underscrollGlow, getWideLayout(ALIGN_PARENT_TOP));
addView(underscrollEdge, getWideLayout(ALIGN_PARENT_TOP));
addView(overscrollGlow, getWideLayout(ALIGN_PARENT_BOTTOM));
addView(overscrollEdge, getWideLayout(ALIGN_PARENT_BOTTOM));
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN) interruptFade = true;
listViewGestureDetector.onTouchEvent(ev);
if(ev.getAction() == MotionEvent.ACTION_UP) reset();
return super.dispatchTouchEvent(ev);
}
private RelativeLayout.LayoutParams getWideLayout(int alignment)
{
RelativeLayout.LayoutParams returnLayout = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0);
returnLayout.addRule(alignment);
return returnLayout;
}
public void reset()
{
interruptFade = false;
new GlowShrinker().execute(scrollDistanceSinceBoundary);
scrollDistanceSinceBoundary = 0;
}
private class ListViewGestureDetector extends SimpleOnGestureListener
{
#Override
public boolean onScroll(MotionEvent downMotionEvent, MotionEvent currentMotionEvent, float distanceX, float distanceY)
{
float distanceTraveled = downMotionEvent.getY() - currentMotionEvent.getY();
if(listIsAtTop() && distanceTraveled < 0) // At top and finger moving down
{
scrollDistanceSinceBoundary -= distanceY;
scaleEdges(underscrollEdge, underscrollGlow, scrollDistanceSinceBoundary);
}
else if(listIsAtTop() && distanceTraveled > 0 && scrollDistanceSinceBoundary > 0) // At top and finger moving up while in overscroll
{
scrollDistanceSinceBoundary -= distanceY;
scaleEdges(underscrollEdge, underscrollGlow, scrollDistanceSinceBoundary);
}
else if(listIsAtBottom() && distanceTraveled > 0) // At bottom and finger moving up
{
scrollDistanceSinceBoundary += distanceY;
scaleEdges(overscrollEdge, overscrollGlow, scrollDistanceSinceBoundary);
}
else if(listIsAtBottom() && distanceTraveled < 0 && scrollDistanceSinceBoundary > 0) // At bottom and finger moving up while in overscroll
{
scrollDistanceSinceBoundary += distanceY;
scaleEdges(overscrollEdge, overscrollGlow, scrollDistanceSinceBoundary);
}
else if(scrollDistanceSinceBoundary != 0) // Neither over scrolling or under scrolling but was at last check. Reset both graphics.
{
reset();
}
Log.v(CustomGlowListView.class.getSimpleName(), "boundaryDistance = " + scrollDistanceSinceBoundary);
return false;
}
private boolean listIsAtTop() { return listView.getChildAt(0).getTop() - paddingRectangle.top == 0; }
private boolean listIsAtBottom(){ return listView.getChildAt(listView.getChildCount()-1).getBottom() + paddingRectangle.bottom == listView.getHeight(); }
}
private class GlowShrinker extends AsyncTask<Float, Integer, Void>
{
ImageView glow;
ImageView edge;
private final int SHRINK_SPEED = 4;
private final int SHRINK_INCREMENT = 50;
#Override
protected void onPreExecute() {
if(underscrollGlow.getHeight() > 0)
{
glow = underscrollGlow;
edge = underscrollEdge;
}
else if (overscrollGlow.getHeight() > 0)
{
glow = overscrollGlow;
edge = overscrollEdge;
}
else
{
return;
}
}
#Override
protected Void doInBackground(Float... scrollDistanceSinceBoundary) {
if(glow != null && edge != null)
{
int currentSize = (int) scrollDistanceSinceBoundary[0].floatValue();
int shrinkRate = (int) currentSize / SHRINK_INCREMENT;
for(int i=0; i < SHRINK_INCREMENT; i++)
{
if(interruptFade)
{
publishProgress(0);
return null;
}
currentSize -= shrinkRate;
publishProgress(currentSize);
try { Thread.sleep(SHRINK_SPEED); } catch (InterruptedException e) { }
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if(glow != null && edge != null)
CustomGlowListView.scaleEdges(edge, glow, 0);
}
#Override
protected void onProgressUpdate(Integer... values) {
CustomGlowListView.scaleEdges(edge, glow, values[0]);
}
}
private static void scaleEdges(ImageView scrollEdge, ImageView scrollGlow, float scrollBy)
{
float edgeSize = scrollBy / 20;
float glowSize = scrollBy / 2;
if(edgeSize > MAX_EDGE_SIZE) edgeSize = MAX_EDGE_SIZE;
if(glowSize > MAX_GLOW_SIZE) glowSize = MAX_GLOW_SIZE;
setHeight(scrollEdge, edgeSize);
setHeight(scrollGlow, glowSize);
}
private static void setHeight(ImageView viewIn, float height)
{
ViewGroup.LayoutParams params = viewIn.getLayoutParams();
params.height = (int) height;
viewIn.setLayoutParams(params);
}
public AbsListView getListView()
{
return listView;
}
}
The overscroll images you can grab from platforms\android-10\data\res\drawable-mdpi\ and then change Hue & Saturation to change color.
I hope this can be a useful start for other ListView customisations - Be interesting to hear of any.
Actually, instead of using a customized ListView, you can simply "hack" your way to changing the color, the glow effect is actually a Drawable embedded in the OS's resources, you can apply a ColorFilter on that:
int glowDrawableId = context.getResources().getIdentifier("overscroll_glow", "drawable", "android");
Drawable androidGlow = context.getResources().getDrawable(glowDrawableId);
androidGlow.setColorFilter(brandColor, PorterDuff.Mode.MULTIPLY);
Read more about it here: http://evendanan.net/android/branding/2013/12/09/branding-edge-effect/
The following method overrides the standard overscroll color including the edge line.
Calling it once in onCreate is enough.
...
ChangeOverScrollGlowColor(getResources(), R.color.red);
...
public static final void ChangeOverScrollGlowColor( Resources res, int colorID ) {
try {
final int glowDrawableId = res.getIdentifier("overscroll_glow", "drawable", "android");
final Drawable overscrollGlow = res.getDrawable(glowDrawableId);
overscrollGlow.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);
final int edgeDrawableId = res.getIdentifier("overscroll_edge", "drawable", "android");
final Drawable overscrollEdge = res.getDrawable(edgeDrawableId);
overscrollEdge.setColorFilter(res.getColor(colorID), android.graphics.PorterDuff.Mode.SRC_ATOP);
} catch (Exception e) {
}
}