Programmatically set random number in images - android

I have 4 speech bubble, which of 2 have question in white speech bubble and another 2 blue bubble have answers . I have done showing random image but how to generate question and answers randomly,i have confusion in that. I did not understand how to programmatically set text in image( speech bubble in this case). These are images cleaging more of my problem.!
next time question display following types.
i have done following code:
public class TestingActivity extends Activity {
ImageView i1, i2, i3, i4;
int TwoArray[][] = new int[6][5];
static int i;
static int j;
static int a = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupVeiw();
setImages();
}
// Shuffle here
private void setupVeiw() {
i1 = (ImageView) findViewById(R.id.imageView1);
i2 = (ImageView) findViewById(R.id.imageView2);
i3 = (ImageView) findViewById(R.id.imageView3);
i4 = (ImageView) findViewById(R.id.imageView4);
}
public int getImage(int val)
{
if (val == 0)
{
// How to set programmatically **questions** numbers in spechh bubble
return R.drawable.speech_white;
}
else
{
// How to set programmatically **answers** numbers in spechh bubble
return R.drawable.speech_blue;
}
}
public void setImages()
{
try {
int numArray[] = { 0, 0,1, 1 };
shuffleList(numArray);
for (i = 0; i < numArray.length - 1; i++)
{
switch (i)
{
case 0:
i1.setImageResource(getImage(numArray[i]));
break;
case 1:
i2.setImageResource(getImage(numArray[i]));
break;
case 2:
i3.setImageResource(getImage(numArray[i]));
break;
case 3:
i4.setImageResource(getImage(numArray[i]));
break;
default:
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
I am waiting for your good advice.
Thank you advance.

Would be nice if you would use TextView instead, you can still set a background image in text view.
First, to generate a question, you can create a class named Question with the following properties.
public static int ADDITION = 1; // for example's sake
double x, y; // your variables
int operation; // operation
public Question(double x, double y, int operation) {
this.x = x;
this.y = y;
this.operation = operation
}
public double returnAnswer() {
double answer = 0;
if(operation == Question.ADDITION) {
answer = x + y;
}
return answer;
}
And then you can generate questions
Question firstQuestion = new Question(Math.random(), Math.random(), Question.ADDITION);
Instead of using ImageViews to display the question, you can use TextViews. Use the setText() method to display the question and the setBackground() method to change the background image.

Related

call method with multiple parameters in onClick() of a button

I am new to Android and I am trying to Build a gallery app with Edit Activity. I have attached the screenshot of edit screen of my app. There is an ImageView, a SeekBar and 4 ImageButtons. The ImageButtons implements 4 edit functionality-Brightness,saturation and etc.. I have all methods for effects. All I want to know is when I click the imageButton(may be brightness), and drag the seekbar, the brightness should increase and similarly, when i click Contrast ImageButton and drag the seekbar, Contrast of Image should Increase. How can I implement it. Could Someone Please help me with it.. I tried using setOnTouchListener() for ImageButtons but that dint work, as it accepts only view as parameter and not Bitmap. Please help me.Thanks in Advance
Below is my Edit Activity
public class EditActivity extends Activity
{
private Bitmap bitmap;
private ImageView image;
private ImageButton bb,sab,shb,cb;
private BitmapDrawable drawable;
private SeekBar seekBar;
#Override
public void onCreate( Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.filters);
// Get intent data
Intent i = getIntent();
// Selected image id
final int position = i.getExtras().getInt("id");
ImageAdapter imageAdapter = new ImageAdapter(this);
image = (ImageView) findViewById(R.id.imageView);
image.setImageResource(imageAdapter.ids[position]);
bb = (ImageButton) findViewById(R.id.brightButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
bb.setImageBitmap(bitmap);
sab=(ImageButton)findViewById(R.id.saturationButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
sab.setImageBitmap(bitmap);
cb=(ImageButton) findViewById(R.id.contrastButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
cb.setImageBitmap(bitmap);
shb=(ImageButton) findViewById(R.id.sharpButton);
drawable = (BitmapDrawable) image.getDrawable();
bitmap = drawable.getBitmap();
shb.setImageBitmap(bitmap);
SeekBar seekBar=(SeekBar)findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
int brightness;
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, final int progress, boolean arg2)
{
brightness = progress;
Bitmap bBitMap = brightClicked(bitmap,progress);
image.setImageBitmap(bBitMap);
Bitmap saBitMap = sharpClicked(bitmap,progress);
image.setImageBitmap(saBitMap);
Bitmap cBitMap = saturationClicked(bitmap,progress);
image.setImageBitmap(cBitMap);
Bitmap shBitMap = contrastClicked(bitmap,progress);
image.setImageBitmap(shBitMap);
}
});
}
public Bitmap brightClicked(Bitmap bbitmap,int value)
{
Bitmap bmOut= Bitmap.createBitmap(bbitmap.getWidth(), bbitmap.getHeight(),bbitmap.getConfig());
int A, R, G, B;
int pixel;
for(int i=0; i<bbitmap.getWidth(); i++){
for(int j=0; j<bbitmap.getHeight(); j++)
{
pixel = bbitmap.getPixel(i, j);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
R += value;
if (R > 255)
{
R = 255;
} else if (R < 0)
{
R = 0;
}
G += value;
if (G > 255)
{
G = 255;
} else if (G < 0)
{
G = 0;
}
B += value;
if (B > 255)
{
B = 255;
} else if (B < 0)
{
B = 0;
}
bmOut.setPixel(i, j, Color.argb(A, R, G, B));
}
}
return bmOut;
}// and other methods of effects like sharpness,contrast..
Below is Screenshot of EditImage
I would begin with defining state so that the SeekBar can quickly determine which attribute it should be modifying (contrast, brightness, sharpness, saturation). Throw these into an enum class (Google recommends avoiding enums in Android) if you like or define them within the class itself as ints. For example:
public class EditActivity extends Activity {
private int currentState;
private static final int SATURATE = 0;
private static final int CONTRAST = 1;
....
}
Now you can just have the state be updated based on the button clicked:
bb = (ImageButton) findViewById(R.id.brightButton);
bb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
currentState = BRIGHTNESS;
}
}
Then use a switch-case statement to quickly determine the state of the Activity and adjust the image accordingly through your image methods.
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
{
#Override
public void onProgressChanged(SeekBar arg0, final int progress, boolean arg2)
{
brightness = progress;
switch (currentState) {
case (SATURATE) :
image.setImageBitmap(saturationClicked(bitmap,progress));
break;
case (CONTRAST) :
image.setImageBitmap(contrastClicked(bitmap,progress));
break;
It looks like your current implementation would run all your filters on the image any time the seek bar is moved, which I imagine would cause horrible performance. A switch case would just help you avoid that.

Android: Ensuring that TextView cannot display a String value the same as its colour?

I am developing a game based on the STROOP EFFECT.
This game is based on the displaying of a string of a certain colour for the user to see.
However this String value cannot be the same as its Colour.
I.e. this is ok (as "RED" is not actually the colour Red, it is blue):
But this is not ok as "RED" actually is the color Red:
How can I ensure that the 2nd option cannot occur within my game?
Specific related code section:
color = (TextView) findViewById(R.id.tvStroopColor);
int randString = new Random().nextInt(stringOnScreen.length);
int randColor = new Random().nextInt(colorsOnScreen.length);
// set the text of the string in textview for user to see
color.setText("" + stringOnScreen[randString]);
color.setTextColor((int) colorsOnScreen[randColor]);
Full Activity:
public class Stroop extends Activity implements View.OnClickListener {
HashMap<String, Integer> colors = new HashMap<>();
// putting the strings and color vals of the hashmap to an array
Object stringOnScreen[];
Object colorsOnScreen[];
// declare vars
TextView color;
Button btn1;
Button btn2;
TextView result;
TextView showScore;
TextView seeMed;
TextView seeAtt;
int score=0;
MediaPlayer tenSecs;
// vars related to neurosky
BluetoothAdapter bluetoothAdapter;
TGDevice device;
TGEegPower eegPower;
final boolean rawEnabled = true;
List<Integer> meditationValues = new ArrayList<Integer>();
int averageMedLevel;
int totalofMedLevels;
int medCount = 0;
int medMax;
// for attention
List<Integer> AttentionValues = new ArrayList<Integer>();
int averageAttLevel;
int totalofAttLevels;
int attCount = 0;
int attMax;
// used for displaying seconds left
EditText countdown;
// in relation to saving values to file
List<TGEegPower> medPoints = new ArrayList<TGEegPower>();
File dir;
int medValueToWrite;
int attValueToWrite;
// in relation to the results display in next activity
ArrayList<Score> singleScore;
Score single;
private Random random = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stroop);
setUpGame();
stringOnScreen = colors.keySet().toArray();
colorsOnScreen = colors.values().toArray();
setUpQuestion();
btn2.setOnClickListener(this);
btn1.setOnClickListener(this);
}// oncreate end
public void setUpQuestion() {
int[] buttons = new int[]{R.id.btnStroop1, R.id.btnStroop2};
int first = random.nextInt(2);
btn1 = (Button) findViewById(buttons[first]); //btnstroop1 or btnstroop2
btn2 = (Button) findViewById(buttons[1-first]); //the opposite btn
int randString = new Random().nextInt(stringOnScreen.length);
int randColor = new Random().nextInt(colorsOnScreen.length);
// set the text of the string in textview for user to see
color.setText("" + stringOnScreen[randString]);
color.setTextColor((int) colorsOnScreen[randColor]);
btn1.setText("" + stringOnScreen[randString]); //Set btn1 to the string val
setBtn2Text();
showScore.setText("Score= " + score);
}
public void setUpGame() {
// setting up the hashmap
colors.put("Green", Color.GREEN);
colors.put("Blue", Color.BLUE);
colors.put("Red", Color.RED);
colors.put("Yellow", Color.YELLOW);
colors.put("Black", Color.BLACK);
// setting up vars
color = (TextView) findViewById(R.id.tvStroopColor);
result = (TextView) findViewById(R.id.tvStroopResults);
showScore = (TextView) findViewById(R.id.tvStroopScore);
seeMed = (TextView) findViewById(R.id.tvStroopSeeMeditation);
seeAtt = (TextView) findViewById(R.id.tvStroopSeeAttention);
tenSecs= MediaPlayer.create(Stroop.this, R.raw.tenseconds);
countdown= (EditText) findViewById(R.id.etStroopCountdown);
}
public void setBtn2Text(){
switch(color.getCurrentTextColor()){
case Color.GREEN:
btn2.setText("Green");
break;
case Color.RED:
btn2.setText("Red");
break;
case Color.BLUE:
btn2.setText("Blue");
break;
case Color.YELLOW:
btn2.setText("Yellow");
break;
case Color.BLACK:
btn2.setText("Black");
break;
}
}
public void onClick(View v) {
if(checkForMatchBtn2((Button) v)){
result.setText("Correct!");
result.setTextColor(Color.GREEN);
score++;
}else{
result.setText("Wrong!");
result.setTextColor(Color.RED);
}
setUpQuestion();
}
public boolean checkForMatchBtn2(Button btn2){
if(color.getCurrentTextColor() == Color.GREEN && btn2.getText().equals("Green"))
return true;
else if(color.getCurrentTextColor() == Color.RED && btn2.getText().equals("Red"))
return true;
else if(color.getCurrentTextColor() == Color.BLACK && btn2.getText().equals("Black"))
return true;
else if(color.getCurrentTextColor() == Color.YELLOW && btn2.getText().equals("Yellow"))
return true;
else if(color.getCurrentTextColor() == Color.BLUE && btn2.getText().equals("Blue"))
return true;
else
return false;
}
public boolean checkForMatchBtn1(Button btn1){
if(color.getCurrentTextColor() == Color.GREEN && btn1.getText().equals("Green"))
return true;
else if(color.getCurrentTextColor() == Color.RED && btn1.getText().equals("Red"))
return true;
else if(color.getCurrentTextColor() == Color.BLACK && btn1.getText().equals("Black"))
return true;
else if(color.getCurrentTextColor() == Color.YELLOW && btn1.getText().equals("Yellow"))
return true;
else if(color.getCurrentTextColor() == Color.BLUE && btn1.getText().equals("Blue"))
return true;
else
return false;
}
}
I would create a Map, fulfill it with every options you don't want where String is your color and int its hex value.
Then you only need to check if the color chosen exists with the hex chosen in your Map.
So if you get White and #FFF, you'll check what's the associated color of "white" in your map and if it's #FFF, that random is forbidden.
There may be a better way but that will do the trick =)
You could set a condition before displaying the text and reload a new color/text if they are the "same", something like:
color = (TextView) findViewById(R.id.tvStroopColor);
int randString = new Random().nextInt(stringOnScreen.length);
int randColor = new Random().nextInt(colorsOnScreen.length);
if(!colors.get(stringOnScreen[randString]).equals(colorsOnScreen[randColor])){
// set the text of the string in textview for user to see
color.setText("" + stringOnScreen[randString]);
color.setTextColor((int) colorsOnScreen[randColor]);
}else{
// recall your function !
}
You should also avoid the findViewById inside your function (it could slow the application) but only retrieve the correct button and then set the text
You could do for example something like this
public void setUpQuestion() {
..
int randString = new Random().nextInt(stringOnScreen.length);
int randColor = new Random().nextInt(colorsOnScreen.length);
//regenerate question if color and string are the same
setUpQuestion()
...
Or you could do make a clone of the colection reduce it and then select a random color from the reduced collection
..
HashMap<String, Integer> colorsReduced = (HashMap<String, Integer>)colors.clone();
colorsReduced.remove(randString);
colorsReduced.get( new Random().nextInt(colorsReduced.size()-1));
...

Smooth scrolling in HorizontalScrollLayout is called, but doesn't work

I have a question to which I haven't found anything. I modified a HorizontalScrollLayout to scroll pagewise. It all works fine with a short problem. If I scroll very slowly, the smoothScrollTo function is called (you can debug through it), but doesn't work, the ScrollLayout stays between two pages. If I change it to the scrollTo function, it works, but looks horrible. I use a HTC One to check the function.
Does anyone know the problem? Is it maybe a HTC problem or is it also existent on other platforms? Is there another smart way to realize the function?
Here is my code:
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class FullscreenActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
final HorizontalScrollView scr = new HorizontalScrollView(this){
int scrollXBegin = 0;
private void setScrollXBegin(int beg){
this.scrollXBegin = beg;
}
#Override
public boolean onTouchEvent(MotionEvent ev){
switch (ev.getActionMasked()){
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_UP:
this.scrollReady(ev);
break;
case MotionEvent.ACTION_DOWN:
this.setScrollXBegin(this.getScrollX());
break;
default:
break;
}
return super.onTouchEvent(ev);
}
#Override
public void fling (int velocityY)
{
/*Scroll view is no longer gonna handle scroll velocity.
* super.fling(velocityY);
*/
}
protected boolean scrollReady(MotionEvent ev){
int actXPos = (int)this.getScrollX();
int motionDirection = actXPos - this.scrollXBegin;
int i = 0;
int sz_act = 0;
int sz_old = 0;
for(i = 0; i < ((LinearLayout)this.getChildAt(0)).getChildCount(); i++){
sz_old = sz_act;
sz_act += ((LinearLayout)this.getChildAt(0)).getChildAt(i).getWidth();
if(sz_act > actXPos)
break;
}
// Fertig scrollen auf den naechsten Child
if (motionDirection >= 0)
this.smoothScrollTo(sz_act, this.getScrollY());
else
this.smoothScrollTo(sz_old, this.getScrollY());
computeScroll();
return true;
}
};
final LinearLayout scrollLayout = new LinearLayout(this);
scrollLayout.setOrientation(LinearLayout.HORIZONTAL);
scr.addView(scrollLayout);
scr.setSmoothScrollingEnabled(true);
LayoutParams imLP = new LayoutParams();
imLP.height = 1024;
imLP.width = 1024;
ImageView im1 = new ImageView(this);
im1.setImageResource(R.drawable.ic_launcher);
im1.setLayoutParams(imLP);
scrollLayout.addView(im1);
ImageView im2 = new ImageView(this);
im2.setImageResource(R.drawable.ic_launcher_r);
im2.setLayoutParams(imLP);
scrollLayout.addView(im2);
im1 = new ImageView(this);
im1.setImageResource(R.drawable.ic_launcher_b);
im1.setLayoutParams(imLP);
scrollLayout.addView(im1);
((FrameLayout)findViewById(R.id.parent_layout)).addView(scr);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
}
}`
and here ist the complete Eclipse Project to test.
https://www.dropbox.com/sh/m2dedsa3w3avgec/CdTX8cFJhk/TestVerticalScroll.rar

Android Gallery freezes screen until scrolled

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));
}
}

Smooth Scroll for GridView

Does smoothScrollToPosition() method for GridView works correctly?
I have found an open bug report and mine is not working correctly either.
setSelection() is working fine but I want a smooth scroll effect.
Do you have any idea about this issue?
If this is a persistent problem, where should I start to implement a good scroll effect?
While I'm not seeing any issues running the example code you posted, if you're not seeing consistent results in your application it's not too tricky to create your own scroll controller. Here's an example implementation you could use:
private class ScrollPositioner {
private static final int SCROLL_DURATION = 20;
private static final int DIR_UP = 1;
private static final int DIR_DOWN = 2;
int mTargetPosition = AdapterView.INVALID_POSITION;
int mDirection = AdapterView.INVALID_POSITION;
int mLastSeenPosition = AdapterView.INVALID_POSITION;
int mExtraScroll;
GridView mGrid;
public ScrollPositioner(GridView grid) {
mGrid = grid;
mExtraScroll = ViewConfiguration.get(mGrid.getContext()).getScaledFadingEdgeLength();
}
Handler mHandler = new Handler();
Runnable mScroller = new Runnable() {
public void run() {
int firstPos = mGrid.getFirstVisiblePosition();
switch(mDirection) {
case DIR_UP: {
if (firstPos == mLastSeenPosition) {
// No new views, let things keep going.
mHandler.postDelayed(mScroller, SCROLL_DURATION);
return;
}
final View firstView = mGrid.getChildAt(0);
if (firstView == null) {
return;
}
final int firstViewTop = firstView.getTop();
final int extraScroll = firstPos > 0 ? mExtraScroll : mGrid.getPaddingTop();
mGrid.smoothScrollBy(firstViewTop - extraScroll, SCROLL_DURATION);
mLastSeenPosition = firstPos;
if (firstPos > mTargetPosition) {
mHandler.postDelayed(mScroller, SCROLL_DURATION);
}
break;
}
case DIR_DOWN: {
final int lastViewIndex = mGrid.getChildCount() - 1;
final int lastPos = firstPos + lastViewIndex;
if (lastViewIndex < 0) {
return;
}
if (lastPos == mLastSeenPosition) {
// No new views, let things keep going.
mHandler.postDelayed(mScroller, SCROLL_DURATION);
return;
}
final View lastView = mGrid.getChildAt(lastViewIndex);
final int lastViewHeight = lastView.getHeight();
final int lastViewTop = lastView.getTop();
final int lastViewPixelsShowing = mGrid.getHeight() - lastViewTop;
final int extraScroll = lastPos < mGrid.getAdapter().getCount() - 1 ? mExtraScroll : mGrid.getPaddingBottom();
mGrid.smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll, SCROLL_DURATION);
mLastSeenPosition = lastPos;
if (lastPos < mTargetPosition) {
mHandler.postDelayed(mScroller, SCROLL_DURATION);
}
break;
}
default:
break;
}
}
};
public void scrollToPosition(int position) {
mTargetPosition = position;
mLastSeenPosition = AdapterView.INVALID_POSITION;
if(position < mGrid.getFirstVisiblePosition()) {
mDirection = DIR_UP;
} else if (position > mGrid.getLastVisiblePosition()) {
mDirection = DIR_DOWN;
} else {
return;
}
mHandler.post(mScroller);
}
}
Here's a snippet from the example you linked that includes where this new class to do the scrolling in place of the framework implementation:
GridView g;
boolean t= false;
#Override
public void onBackPressed() {
//Instantiate and attach the custom positioner
if(mPositioner == null) {
mPositioner = new ScrollPositioner(g);
}
//Use the custom object to scroll the view
mPositioner.scrollToPosition(0);
if(t) {
super.onBackPressed();
}
else {
t = true;
}
}
If you want to add a feature where the selected position is always scrolled to the top even when the scrolling direction is down, you could do that. This is not something the framework's implementation is designed to do, but you could accomplish it by adding some code in DIR_DOWN to continue scrolling until the first visible position matches target (like DIR_UP does). You must also beware of the case where the scrolling ends before the position reaches the top, so you aren't constantly posting the handler in cases where you will never get a different result.
HTH
Had the same issue- I built a simple GridView and for some reason the smoothScrollToPosition() didn't work at all (just bounce from time to time).
after lot of debugging it turn out to be that I need to remove the android:padding parameter from the GridView.
very strange, I really don't know why it is like this, but at least now it works.

Categories

Resources