I'am developing a sample android application to learn about drag & drop in android. On start of the app, i'am displaying few images on a grid view. Now i need to drag one image at a time over to the place of another. After dropping an image over another, the images should swap its places. How can i achieve it ? Please guide/help me.
You can easily achieve this by using thquinn's DraggableGridView
You can add your custom layout
public class DraggableGridViewSampleActivity extends Activity {
static Random random = new Random();
static String[] words = "the of and a to in is be that was he for it with as his I on have at by not they this had are but from or she an which you one we all were her would there their will when who him been has more if no out do so can what up said about other into than its time only could new them man some these then two first may any like now my such make over our even most me state after also made many did must before back see through way where get much go well your know should down work year because come people just say each those take day good how long Mr own too little use US very great still men here life both between old under last never place same another think house while high right might came off find states since used give against three himself look few general hand school part small American home during number again Mrs around thought went without however govern don't does got public United point end become head once course fact upon need system set every war put form water took".split(" ");
DraggableGridView dgv;
Button button1, button2;
ArrayList<String> poem = new ArrayList<String>();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dgv = ((DraggableGridView)findViewById(R.id.vgv));
button1 = ((Button)findViewById(R.id.button1));
button2 = ((Button)findViewById(R.id.button2));
setListeners();
}
private void setListeners()
{
dgv.setOnRearrangeListener(new OnRearrangeListener() {
public void onRearrange(int oldIndex, int newIndex) {
String word = poem.remove(oldIndex);
if (oldIndex < newIndex)
poem.add(newIndex, word);
else
poem.add(newIndex, word);
}
});
dgv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long arg3) {
Toast.makeText(getApplicationContext(), "On clicked" +position, Toast.LENGTH_SHORT).show();
dgv.removeViewAt(position);
poem.remove(position);
}
});
button1.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String word = words[random.nextInt(words.length)];
addView();
poem.add(word);
}
});
button2.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String finishedPoem = "";
for (String s : poem)
finishedPoem += s + " ";
new AlertDialog.Builder(DraggableGridViewSampleActivity.this)
.setTitle("Here's your poem!")
.setMessage(finishedPoem).show();
}
});
}
public void addView()
{
LayoutParams mLayoutParams= new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
LinearLayout mLinearLayout= new LinearLayout(DraggableGridViewSampleActivity.this);
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
mLinearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
ImageView mImageView = new ImageView(DraggableGridViewSampleActivity.this);
if(dgv.getChildCount()%2==0)
mImageView.setImageResource(R.drawable.child1);
else
mImageView.setImageResource(R.drawable.child2);
mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mImageView.setLayoutParams(mLayoutParams);
mImageView.setId(dgv.getChildCount());
mImageView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), v.getId()+"clicked ", Toast.LENGTH_SHORT).show();
return dgv.onTouch(v, event);
}
});
TextView mTextView = new TextView(DraggableGridViewSampleActivity.this);
mTextView.setLayoutParams(mLayoutParams);
mTextView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), v.getId()+"clicked text ", Toast.LENGTH_SHORT).show();
return dgv.onTouch(v, event);
}
});
TextView mTextViewLabel = new TextView(DraggableGridViewSampleActivity.this);
mTextViewLabel.setText(((dgv.getChildCount()+1)+""));
mTextViewLabel.setLayoutParams(mLayoutParams);
mTextViewLabel.setId(dgv.getChildCount());
mTextViewLabel.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getApplicationContext(), v.getId()+"clicked text ", Toast.LENGTH_SHORT).show();
return dgv.onTouch(v, event);
}
});
mLinearLayout.setTag(mTextViewLabel);
mLinearLayout.addView(mTextViewLabel);
mLinearLayout.addView(mImageView);
mLinearLayout.addView(mTextView);
dgv.addView(mLinearLayout);
}
}
Related
I am studying Mobile Application Developer and I am just a beginner. So, forgive me if the question is silly.
I am creating a simple Quiz App. I have MainActivity which act as a welcoming screen.
public class MainActivity extends AppCompatActivity {
private Button startBt; //the user will enter this button to go the SecondActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBt = findViewById(R.id.startBt);
startBt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, SecondActivity.class);
startActivity(i);
}
});
}
}
Then, I have a SecondActivity which suppose to ask the user a question and get the answer as a String and then increment the score if the answer is correct. There is 10 question. So, I want to use a loop to iterate through all questions. Also, inside the loop there is OnKeyListener which indicate when the user press Enter and compare the user answer to the saved answer.
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
String[] questions = getResources().getStringArray(R.array.questions);
String[] answers = getResources().getStringArray(R.array.answers);
TextView questionTv = findViewById(R.id.questionTv);
final EditText answerEt = findViewById(R.id.answerPt);
TextView scoreTv = findViewById(R.id.scoreTv);
int scoreCounter = 0;
for (int i=0; i<10; i++) {
answerEt.setText("");
scoreTv.setText(scoreCounter);
questionTv.setText(questions[i]);
answerEt.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (**answerEt**.getText().toString().equals(**answers[i]**)) {
Toast t = Toast.makeText(getApplicationContext(), "Correct",Toast.LENGTH_LONG);
t.show();
**scoreCounter++;**
return true;
}
else
return false;
} else
return false;
}
});
}
}
}
Now, please check the bold part of the code. I cannot access answerEt, scoreCounter, answer[i] because they are not final. They should be final because I am working with an inner class. Here is the problem, if I will make them final, I will not have the ability to modify them. However, scoreCounter should be incremented to show the user score. Also the i should be incremented to iterate through the answer[]. One will say "make them Global". Sadly, I tried this and my program crashed. So, How I can solve this?
Thanks in advance
pass on responsibility to check for correct answer to a separate function.
private boolean checkAnswer(EditText et, final int questionID) {
if (et.getText().toString().equals(answers[questionID])) {
Toast t = Toast.makeText(getApplicationContext(), "Correct", Toast.LENGTH_LONG);
t.show();
scoreCounter++;
return true; // for correct answer.
}
return false; // for incorrect answer.
}
Modify your loop to use above function like this :
for (int i = 0; i < 10; i++) {
final int currentQuestionID = i;
answerEt.setText("");
scoreTv.setText(scoreCounter);
questionTv.setText(questions[i]);
answerEt.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
return checkAnswer((EditText) (v), currentQuestionID);
}
return false;
}
});
}
I currently have a command that will allow the user to proceed to the next page if a button is clicked, this button has a feature android:onClick="advancenext" which I have defined in the .java file to be the following
public void advancenext (View view) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
However, I only want the user to call advancenext if a variable i is greater than 5. This is what I tried
if (i>5) {
public void advancenext (View view) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
However, when I run the app, I can still advance even though i is not greater than 5. Does anyone know how to fix this, or better restrict advancenext in a different way?
EDIT Thanks for the great answers, but I encountered a different error when I changed my statement. When I try:
public void advancenext (View view) {
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
I get the errors Syntax error on token "(", ; expected and Syntax error on token ")", ; expected around the ( and ) of (View view).
EDIT dos Here's my full code
public class Prompt1 extends Activity {
int i; //Variable i stores the touch number
float[] X, Y; //Array that will store the touchpoints
int ultscore1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prompt1);
i=1;
touchLayout.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
i++; //increasing i value
public void advancenext (View view) {
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
}
return true;
}
});
}
I would do this
public class Prompt1 extends Activity implements OnTouchListener{
int i; //Variable i stores the touch number
float[] X, Y; //Array that will store the touchpoints
int ultscore1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prompt1);
i=1;
touchLayout.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event){
i++; //increasing i value
advancenext(v);
return true;
}
public void advancenext (View view) {
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
}
This allows your class to directly handle the touch event (and any other touch events for views contained in the classes set content view) by just adding the on touch listener to the view. You can handle the incrementing of your variable i in onTouch like you were and call your advancenext method with the view passed to onTouch. The method, advancenext, could very easily have its functionality moved to onTouch, that is
#Override
public boolean onTouch(View v, MotionEvent event){
i++; //increasing i value
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
return true;
}
But moving the functionality out of onTouch into it's own method will allow you to use advancenext with other io events (like onClick).
You have to evaluate your if statement inside your function. Be sure you have access to i variable.
public void advancenext(View view) {
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
You've got your statement backwards:
public void advancenext (View view) {
if (i>5) {
Intent intent = new Intent(Prompt1.this, Prompt2.class);
Prompt1.this.startActivity(intent);
}
}
You should call your onClick() function no matter what, THEN check the condition. The way you have it now, you are ignoring the if statement completely.
I am trying to share a flip view content with other apps such as twitter, gmail etc. However the share button works but does not show the flashcard content instead it shows a text that says "android.widget.ViewFlipper#40523fc0". Any help please I have been struggling with for a while. Below is my Java code. The xml code contains only couple buttons and a text view.
public class Jokes extends Activity implements OnClickListener, OnTouchListener {
ViewFlipper flippy;
Random r = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jokes);
flippy = (ViewFlipper) findViewById(R.id.viewFlipper1);
flippy.setOnClickListener(this);
Button b = (Button) findViewById(R.id.bShare);
b.setOnTouchListener(this);
String s [ ]= {"abc", "DEF", "ghi"};
}
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
int i = r.nextInt();
flippy.setDisplayedChild(r.nextInt(4));
flippy.showNext();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, ""+ flippy);
startActivity(Intent.createChooser(intent, "Udir/Share"));
return true;
}
}
I propose you to store the data you want to share as the tag of buttons.
b.setTag("abc"); // Whatever you want to share
This way you can get the data from the button in the event callback.
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.bShare: {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, (String) v.getTag());
startActivity(Intent.createChooser(intent, "Udir/Share"));
break;
}
}
}
I wrote an app with 1 activity and 1 view, so it gives me the coordinates of my fingers i put on the screen. Worked perfectly.
The Problem is now: I Created a new App with more than 1 Activity so i can change between them with intents. also worked fine. But one Activity should be the one wich give me my finger positions. So i Copyed the class and activity put them into the manifest. And made a Button and a intend for to run it.
So when i try to run it it creates the class but doesnt react on my onTouchEvents anymore...
and i have no clue why. i hope i explained my problem well enough for u guys to understand.
So this is my main activity. starts the menu with the option to go to the not working class
public class V1_2 extends Activity implements OnClickListener{
Button btn_1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_v1_2);
btn_1 = (Button) findViewById(R.id.button1);
btn_1.setOnClickListener(this);
}
public void onClick(View v) {
if( btn_1.getId() == ((Button)v).getId() ){
startActivity(new Intent(this,Obj_recog.class));
}
}
This is now the activity wich creates the touchpiont class for the touchevents
public class Obj_recog extends Activity implements OnClickListener{
touchtest TP;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.blank);
TP = new touchtest(this);
}
public void onClick(View v) {
}
And now an example of what doesnt work here but worked at the last project the same way
public class touchtest extends View{
public touchtest(Context context) {
super(context);
Log.d("worked", "worked");
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
Log.d("Touch", "TOUCH!!!!");
return true;
}
}
So i get the message that it "worked" but it doesnt react on touchevents like it used to do...
It will be worked if you add touchtest view as your main view by using setcontentview and then
add touchlistener on that view and call your ontouchevent from your touchtest class. code will be like --
TP = new touchtest(this);
setContentView(TP);
TP.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
TP.onTouchEvent(event);
return false;
}
});
i think should change this approach find an alternative way to implement for which you are going in this way.
In this way you can keep your blank layout and also TP.
RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl);
TP = new touchtest(this);
rl.addView(TP);
TP.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
TP.onTouchEvent(event);
return false;
}
});
I need to create a number of check boxes programmatically using Java, check if one of them is checked and when I click Next Button the control will move to next page. If none of them is checked a toast message has to be displayed. Please suggest as I am new to Android.
Here is my code:
public class TestValidCheckboxActivity extends Activity implements OnCheckedChangeListener{
private RelativeLayout layoutMiddle = null;
private TableLayout layout1;
private CheckBox chk;
private String[] resarr = {"silu", "pinky", "meera"};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
layoutMiddle = (RelativeLayout)findViewById(R.id.layoutMiddleUp);
layout1 = (TableLayout)findViewById(R.id.tableId1);
final Button btnNext = (Button)findViewById(R.id.btnNext);
int i = 0;
for(String res: resarr){
TableRow tr=new TableRow(this);
chk=new CheckBox(this);
chk.setId(i);
chk.setText(res);
chk.setTextColor(Color.BLACK);
tr.addView(chk);
i++;
RelativeLayout.LayoutParams lay = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
lay.addRule(RelativeLayout.BELOW, layoutMiddle.getId());
layout1.addView(tr, lay);
}
chk.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
// TODO Auto-generated method stub
if (arg1)
{
btnNext.setOnClickListener(new View.OnClickListener() {
public void onClick(final View view) {
Log.e("1111111111","111111111");
if(chk.isChecked()){
Intent intent = new Intent(view.getContext(),NextPage.class);
startActivityForResult(intent, 0);
}else{
Toast msg = Toast.makeText(view.getContext(), "please choose at least one option", Toast.LENGTH_LONG);
msg.show();
}
}
});
}else{
Toast msg = Toast.makeText(TestValidCheckboxActivity.this, "please choose at least one option", Toast.LENGTH_LONG);
}
}
});
}
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
// TODO Auto-generated method stub
}
}
this can be easily done
take a boolean flag and set true it on checkbox.isChecked();(inbuilt)
then check if flag is set then navigate to next else TOAST
Can you show us some of your layout code, meaning, are the checkboxes defined in an xml file and do they have IDs?
If they do, you can access each of them with findViewByID and check their status one by one.