Android: Making a Button Display Silly Text - java

I am creating an app in Android where I have a button that displays silly phrases when pressed. I figured out how to get it to say two phrases but I can't figure out how to make it do more. I also want to add in a feature to have the button pick phrases at random instead of going in the order I set. I am thinking of using an arraylist for this. How do I set the button to cycle through different methods in Andrido Studio?
I also want you to know that I am a beginner so please don't be too hard on me.
This is my XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/funny_imageview"
android:scaleType="fitCenter" />
<TextView
android:id="#+id/funny_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text=""/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/funny_sayings_button"
android:text="Click Me!"
android:layout_marginTop="8dp"
android:onClick="changeFunnySayingsButton"/>
</LinearLayout>
This is my Java:
package com.example.android.funnysayingsbutton;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
boolean clicked = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* This method changes the funny text and image on the screen when the button is clicked.
*/
public void changeFunnySayingsButton (View view){
if (clicked){
funnySayingOne();
clicked = false;
}
else {
funnySayingTwo();
clicked = true;
}
}
/**
* This method is for the first funny expression.
*/
public void funnySayingOne(){
displayAnswer("Time to Monkey Around");
displayImage(R.drawable.monkey);
}
/**
* This method is for the second funny expression.
*/
public void funnySayingTwo(){
displayAnswer("Penguin Party Time");
displayImage(R.drawable.penguin);
}
/**
* This method is for the third funny expression.
*/
public void funnySayingThree(){
displayAnswer("It's Rabbit Season.");
displayImage(R.drawable.rabbit);
}
/**
* This method displays the funny text on the screen.
*/
private void displayAnswer(String answer) {
TextView questionTextView = (TextView) findViewById(R.id.funny_textview);
questionTextView.setText(answer);
}
/**
* This method displays the funny image on the screen.
*/
private void displayImage(int picture) {
ImageView questionTextView = (ImageView) findViewById(R.id.funny_imageview);
questionTextView.setImageResource(picture);
}
}

I think that you're on the right track thinking about using a data structure like an ArrayList.
I'd start by making a class to represent each funny thing, e.g.
public class FunnyThing {
private String phrase; // I'd use a resource ID here
private int drawableResourceId;
}
Then it's a matter of initializing the set of FunnyThing objects and storing them in your data structure. You could do this in the onCreate method of your activity, but you may want to consider writing a factory method somewhere else (e.g. the FunnyThing class) that your activity just calls to keep the code from getting cluttered when there are more than 2-3 funny things.
Finally, on each button press you can choose a random index in your collection of FunnyThings and display that, e.g.
private void displayRandomFunnyThing() {
// assumes you have a java.util.Random instance vairable named mRandom
FunnyThing ft = mFunnyThings.get( mRandom.nextInt( mFunnyThings.size());
displayAnswer( ft.phrase );
displayImage( ft.drawableResourceId);
}
Of course you'll need to add an onClickListener to your button, but I'm assuming that you left that code out for brevity.
You'll also have the problem that the phrase selection is random, so you may get the same phrase many times before you see all of them. If you want to prevent duplicates, well, that will take more code.

First of all, where is your button onClick listener? This is where you should add your methods.
Button button = (Button)this.findViewById(R.id.funny_sayings_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
changeFunnySayingsButton (v);
}
});
To continue with you could create an ArrayList of Strings. You add all of your strings and then simply pick one at random from the list. Hint:
//will choose a random number between 0 and the length of the list - 1
int i = rand.nextInt(yourList.size());
String yourFunnyString=yourList.get(i);
If you also want to display an image alongside with the String you should also create a map. Use the String as a key. When you select from yourList then use this key to select the value (your image) from the map.
It should be fairly straightforward to do.

Related

Using Street View VR in my app

I'm using Android Studio and trying to show some chosen Street View paths in VR. I already have Street View running well and now I'm trying to show it in VR.
I have put the com.google.vr.sdk.widgets.pano.VrPanoramaView in the layout and, inside onCreate in my class, referenced it to a VrPanoramaView variable through findViewById. Now I'm trying to show an image calling a method which I've defined in this class, loadPanoImage. This method loads an image from the storage and shows it through loadImageFromBitmap.
The problem is that it isn't able to show anything, even though I've followed a guide and I've done everything as showed. I've even tryed calling it in different parts of the code (before doing any other action, on clicking a button, before and after showing streetview) but I can't understand why it isn't working and how will I be able to use it to show images taken from StreetView (I don't know if I will be able to do it dinamically or I should download them and put them in the storage).
I'm putting part of the code for reference:
public class VrExperience extends FragmentActivity {
Button buttonCitta;
Button buttonMare;
Button buttonMontagna;
TextView titleTextView;
// George St, Sydney
private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
// LatLng with no panorama
private static final LatLng INVALID = new LatLng(-45.125783, 151.276417);
//VrPanoramaView is inserted in the layout
private VrPanoramaView panoWidgetView;
//StreetViewPanorama is another class in my project which shows Street View
private StreetViewPanorama mStreetViewPanorama;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vrexperiences);
panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);
panoWidgetView.setEventListener(new VrPanoramaEventListener());
//download image and show it, but it doesn't show anything
loadPanoImage();
titleTextView = (TextView) findViewById(R.id.titleTextView);
buttonCitta = (Button) findViewById(R.id.buttonCitta);
buttonCitta.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!checkReady()) {
return;
}
titleTextView.setVisibility(View.GONE);
buttonCitta.setVisibility(View.GONE);
buttonMare.setVisibility(View.GONE);
buttonMontagna.setVisibility(View.GONE);
loadPanoImage(); //it doesn't show anything
mStreetViewPanorama.setPosition(SYDNEY);
loadPanoImage(); //it doesn't show anything
}
}};
//code for buttonMontagna and buttonMare as well, it's identical
SupportStreetViewPanoramaFragment streetViewPanoramaFragment =
(SupportStreetViewPanoramaFragment)
getSupportFragmentManager().findFragmentById(R.id.streetviewpanorama);
streetViewPanoramaFragment.getStreetViewPanoramaAsync(
new OnStreetViewPanoramaReadyCallback() {
#Override
public void onStreetViewPanoramaReady(StreetViewPanorama panorama) {
mStreetViewPanorama = panorama;
// Only set the panorama to INVALID on startup (when no panoramas have been
// loaded which is when the savedInstanceState is null).
if (savedInstanceState == null) {
mStreetViewPanorama.setPosition(INVALID);
}
}
});
}
/**
* When the panorama is not ready the PanoramaView cannot be used. This should be called on
* all entry points that call methods on the Panorama API.
*/
private boolean checkReady() {
if (mStreetViewPanorama == null)
return false;
return true;
}
/**
* Called when the Animate To Invalid button is clicked.
*/
public void onGoToInvalid(View view) {
if (!checkReady()) {
return;
}
mStreetViewPanorama.setPosition(INVALID);
}
//retrieves image from the assets folder and loads it into the VrPanoramaView
private void loadPanoImage() {
VrPanoramaView.Options options = new VrPanoramaView.Options();
InputStream inputStream = null;
AssetManager assetManager = getAssets();
try {
inputStream = assetManager.open("demo2.jpg");
options.inputType = VrPanoramaView.Options.TYPE_MONO;
panoWidgetView.loadImageFromBitmap(
BitmapFactory.decodeStream(inputStream), options
);
inputStream.close();
} catch (IOException e) {
Log.e("Fail", "Exception in loadPanoImage" + e.getMessage());
}
}
#Override
protected void onPause() {
panoWidgetView.pauseRendering();
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
panoWidgetView.resumeRendering();
}
#Override
protected void onDestroy() {
panoWidgetView.shutdown();
super.onDestroy();
}
}
This is my layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/vrExperienceActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.vr.sdk.widgets.pano.VrPanoramaView
android:id="#+id/pano_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_weight="5"
android:scrollbars="none" />
<TextView
android:id="#+id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:text="VR Experience"
android:textAlignment="center"
android:textAppearance="#android:style/TextAppearance.Large"
android:textColor="#0000F0"
android:visibility="visible" />
<Button
android:id="#+id/buttonCitta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Città" />
<fragment
class="com.google.android.gms.maps.SupportStreetViewPanoramaFragment"
android:id="#+id/streetviewpanorama"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
EDIT: #LucioB
a) those are the places I've tried to call loadPanoImage, but neither of them showed anything. It acts as nothing happens calling that method, the program keeps going to the other tasks. I'd like for images to be shown directly in VR when a button is clicked, or if that isn't possible to add the classic cardboard button in Street View mode to pass to VR view.
b) I mean the code isn't doing what I expected it to do. I thought that once I created VrPanoramaView in the layout and used it to show an image through .loadImageFromBitmap it would have shown the image I loaded from asset (I have an image saved on the virtual SD), and that once I was able to do that for a single image I would have found a way to do it for a whole path.
The code doesn't give any exception, I think I'm making a logic mistake or I didn't understand how VR api work.
EDIT: I've found that the java code is working, the problem was in the layout which didn't permit to see VrPanoramaView because it was obscured by StreetViewPanorama

Making a button that creates an object and displays it when clicked

I have a program that handles song objects with some fields and playlist objects that are arrays of the songs. I have a perfectly functioning java programming that does what I need it to do but I'm trying to convert it into an Android app and it's making me want to throw my computer out the window. I don't really know XML but I've gotten the basics such as creating buttons etc.
I have a button in the layout file that I implemented as follows:
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="#string/Button"
android:onClick="newPlaylist"/>
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/button1"
android:layout_below="#+id/button1" />
In my main file I have:
public void newPlaylist(View view){
Playlist list1 = new Playlist("First Playlist");
TextView first = (TextView) findViewById(R.id.textView1);
first.setText(list1.getName());
}
Edit: I was able to add a little to the newPlaylist method. Now when I click the button it displays the name of the playlist, but I still want to edit it and be able to have multiple playlists on the screen to manipulate.
All I want to do is display the playlist name as either a text or label that is clickable so that the name can be changed and I can move on from here.
The Android documentation on the button component might help you with your problem.
I assume that your Playlist class looks something like this
public class Playlist {
private String name;
public Playlist(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
If it does, then your method for handling the button click should look like this.
public void newPlaylist(View view) {
Playlist playlist = new Playlist("My First Playlist!"); // Create our playlist object
// Since button is the only component that uses 'newPlaylist' as a click listener, the view will always be the button
Button button = (Button) view; // We cast the view to button
button.setText(playlist.getName()); // This edits the button text, might want to create a TextView for this
}

Android: Linking Edit Text field to button

I am creating a times tables app, in which one of the activities allows the user to enter which times tables they would like to view, then the app will bring up that times tables.(e.g. 6x5=30) etc.
Below is the xml layout I have created for the activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp">
<TextView
android:id="#+id/tvTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I want to see the: "
android:textSize="25dp" />
<EditText
android:id="#+id/etEnterNumber"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Number..."
>
</EditText>
<TextView
android:id="#+id/tvBottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Times tables!"
android:textSize="25dp" />
<Button
android:id="#+id/btnGo"
android:layout_width="50dp"
android:layout_height="50dp"
android:text="Go"
android:layout_gravity="center"/>r
</LinearLayout>
And this it the java class I have created thus far for the classes functionalitiy:
public class ViewTimesTables extends Activity implements View.OnClickListener {
// Declaring Vars
Button go;
EditText enterNumber;
TextView top;
TextView bottom;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setting equal to text layout View
setContentView(R.layout.view);
// calling method to intialise vars
initialiseVars();
}// on create end
/**
* method to initialise all of the buttons, textviews etc used to clean up
* the onCreate.
*/
private void initialiseVars() {
// Setting up (initialising) all the buttons text views etc from the xml
// (vid 25)
go = (Button) findViewById(R.id.btnGo);
enterNumber = (EditText) findViewById(R.id.etEnterNumber);
top = (TextView) findViewById(R.id.tvTop);
bottom = (TextView) findViewById(R.id.tvBottom);
}
/**
* Method with on click listener that adds functionality for all of the
* buttons, text views etc
*
* #param v
*/
public void onClick(View view) {
// switch statement which determines what is clicked
switch ((view).getId()) {
case R.id.etEnterNumber:
// code to read user number (i.e. between 1 and 12)
//And possibly link to go button
break;
case R.id.btnGo:
// code to bring up new activity/screen with times table
// of the number that was entered in edit text
break;
}
}
}
I am unsure how to add the correct functionality (probably within switch statement) so that when e.g. "6" is entered in the edit text box and the "go" button is pressed then the 6 times tables will be brought up in a new activity?
I would begin by looking at Intents to start a new activity and pass data to it.
A relevant tutorial is this Android Intents Tutorial
Getting the text from a edit text is a simple as enterNumber.getText().getString()
You could then use a conditional statement to call the designated class.
Something like this would allow you to pass two values to the SixTimesTables class with the values 5 and 6 passed in.
if(enterNumber.getText().getString().equals("6")){
Intent i = new Intent(this, SixTimesTables.class);
i.putExtra("Value1", 5);
i.putExtra("Value2", 6);
// set the request code to any code you like,
// you can identify the callback via this code
startActivityForResult(i, REQUEST_CODE);
}
You probably want a dynamic layout for next activity.
It may help you.
http://www.dreamincode.net/forums/topic/130521-android-part-iii-dynamic-layouts/
Then you can switch between activities as AndyGable mentioned.
Hopefully it'll help you.
You really dont need the onClick for the editText you can handle if data is entered in the editText or not from the button click only like this:
public void onClick(View view) {
// switch statement which determines what is clicked
switch ((view).getId()) {
case R.id.btnGo:
// code to bring up new activity/screen with times table
// of the number that was entered in edit text
// check if editText has values or not
if(TextUtils.isEmpty(mEditText.getText().toString())) {
mEditText.setError("Please enter a number");
}else {
int number = Integer.parseInt(mEditText.getText().toString());
Intent intent = new Intent(YourCurrentActivity.this, NextActivity.class);
intent.putExtra("value", number);
startActivity(intent);
// it is always good to check if the value entered is a number only or not
// add inputType tag in the xml
// android:inputType="number" for the editText.
}
break;
}
}
Now, in order to get value in the next activity do this:
// write this inside the onCreate of the Activity.
int number;
if(getIntent().getExtras() != null) {
number = getIntent().getIntExtra("value");
}
// use the number then to display the tables

Seeking some insight understanding how a simpleCursorAdapter works

Hey guys I was just hoping someone could shed some light on how this code is working and more specifically the simpleCursorAdapter. The full program is an app that is a to-do list, it's a very simple tutorial the user can input data or "notes" and save to a sqlite data base using cursors and loaders.
So my problem is that there is a specific method that I'm having trouble grasping how it works and as a result I cannot manipulate the way the data is displayed. I think the problem lies in the fact that I just don't understand how the adapter is taking in a different layout than what is displayed and showing it all in a list view.
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
// Fields on the UI to which we map
int[] to = new int[] { R.id.label }; //I don't quite understand but I know it's just a value for the adapter
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from,
to, 0); /*This line specifically I don't understand how it is working.
R.layout.todo_row is a near blank xml, used when there are no "todos"
with no listviews. R.layout.todo_list has the listview's but when
assigned in the adapter it doesn't work.
setListAdapter(adapter);
}
Overall I'm trying to make 3 listviews side by side to read data from the DB and just play around. If anyone could help me out it would be very much so appreciated, thank you.
R.layout.todo_row
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/icon"
android:layout_width="30dp"
android:layout_height="24dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:src="#drawable/reminder" >
</ImageView>
<TextView
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:lines="1"
android:text="#+id/TextView01"
android:textSize="24dp"
>
</TextView>
</LinearLayout>
and R.layout.todo_list
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="110dp"
android:layout_height="200dp" >
</ListView>
<ListView
android:id="#+id/listMiddle"
android:layout_width="110dp"
android:layout_height="200dp"
android:layout_toRightOf="#android:id/list" >
</ListView>
<ListView
android:id="#+id/listRight"
android:layout_width="110dp"
android:layout_height="200dp"
android:layout_toRightOf="#id/listMiddle" >
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_todos" />
</RelativeLayout>
The entire class is below
package de.vogella.android.todos;
import android.app.ListActivity;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import de.vogella.android.todos.contentprovider.MyTodoContentProvider;
import de.vogella.android.todos.database.TodoTable;
/*
* TodosOverviewActivity displays the existing todo items
* in a list
*
* You can create new ones via the ActionBar entry "Insert"
* You can delete existing ones via a long press on the item
*/
public class TodosOverviewActivity extends ListActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private static final int DELETE_ID = Menu.FIRST + 1;
// private Cursor cursor;
private SimpleCursorAdapter adapter;
private SimpleCursorAdapter middleAdapter;
private SimpleCursorAdapter rightAdapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.todo_list);
this.getListView().setDividerHeight(2);
fillData();
registerForContextMenu(getListView());
}
// Create the menu based on the XML defintion
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.listmenu, menu);
return true;
}
// Reaction to the menu selection
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.insert:
createTodo();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
.getMenuInfo();
Uri uri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/"
+ info.id);
getContentResolver().delete(uri, null, null);
fillData();
return true;
}
return super.onContextItemSelected(item);
}
private void createTodo() {
Intent i = new Intent(this, TodoDetailActivity.class);
startActivity(i);
}
// Opens the second activity if an entry is clicked
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(this, TodoDetailActivity.class);
Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
startActivity(i);
}
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
String[] middleId = new String[] { TodoTable.COLUMN_ID };
// Fields on the UI to which we map
int[] to = new int[] { R.id.label };
int[] two = new int[] { R.id.label };
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from,
to, 0);
middleAdapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, middleId,
two, 0);
setListAdapter(adapter);
// setListAdapter(middleAdapter);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
// Creates a new loader after the initLoader () call
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
CursorLoader cursorLoader = new CursorLoader(this,
MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
So my problem is that there is a specific method that I'm having trouble grasping how it works and as a result I cannot manipulate the way the data is displayed.
The method:
adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from, to, 0);
Well, let's break this constructor down by each parameter:
this, a Context. The Adapter needs a Context to inflate each row's layout.
R.layout.todo_row, the row's layout. Every record in your Cursor will be displayed in this layout. (Exactly how the Cursor is displayed depends on from and to.)
null, a Cursor. This holds all of the data that will be shown in your ListView.
from, an array of the essential Views in the rows layout.
to, an array of the essential columns from your Cursor.
0, flags for when and why the data should be refreshed.
The trick behind every thing is this: the ids in the fourth (from) must each match a View in the second parameter (R.layout.todo_row). The Strings in fifth parameter must each match a column name in your Cursor. The fourth (from) and fifth parameters (to) must match one-to-one, because each column is displayed in one View. That's it really.
As you may have realized by now, this note:
R.layout.todo_row is a near blank xml, used when there are no "todos" with no listviews.
is wrong, sorry. If you want to display a note when the Cursor is empty add:
<TextView android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
to todo_list.xml as described in ListActivity's documenation. By using this "magic id" in your TextView, the note should automatically be shown or hidden when appropriate.
All of this only interacts view the first ListView (with the id: `android:id="#android:id/list"), you need to create new Cursors and Adapters to use the other ListViews. Hope that helps!
I haven't looked at the source code for SimpleCursorAdapter. However, it appears that it is mostly doing two things:
The query for your data, based on the params you provide in fillData.
Looping through the results and populating the list using your template.
In my debuggin, I did notice that it's pretty efficient about filling the list - it only allocates as many rows as are needed to display. As you scroll, it recycles them rather than free reallocate them.
It looks like your fillData code is good. You don't say what isn't working so perhaps it's elsewhere. I've never used onCreateLoader (but probably should), so can't comment on that.
I saw one minor problem: in your R.layout.todo_row, you forgot the orientation attribute.
I'm assuming that the code compiles and runs fine and you just want to know what's going on. Well, there are a few things you need to be aware of. The first one is that the ListView doesn't take a layout parameter, your activity does in setContentView. Your R.layout.todo_list is only used by the TodosOverviewActivity to create the "screen" or "look" of the activity, that is, 3 ListView views side by side. Since the activity is a ListActivity it will automatically look for an entry of type ListView with an id of #android:id/list to automatically hook up the list listeners (just saves you a bit of typing), so your other lists will pretty much just sit there until you hook them up yourself (don't use the same id for items on the same layout). If you need to access these other lists you'll need to use the findViewById method in your activity and search for the id of the list you want. For example, we can access the middle list using this:
ListView middleList = (ListView)this.findById(R.id.listMiddle);
Now that we have the list, we need something to show. The lists are completely empty and you need to bring in data from somewhere. In your case, the data comes from a Cursor object you get from a ContentProvider. The cursor contains only one column that matters to us, the TodoTable.COLUMN_SUMMARY column that has the text we want to display in the list. The problem is that a list doesn't have a clue of what to do with a Cursor since the only thing it does is put a view on the screen and scroll it up and down. The Cursor, on the other hand, has all the data you want to show but doesn't have a clue of what a View is, much less how to put all the data it contains inside one for the list to show. Now you have the SimpleCursorAdapter which is, like the name says, an adapter. It is used to make incompatible things work together. On one side you have a list that needs a view, on the other side you have a cursor with the data you want to show, so now you need an adapter that will map each piece of data to part of a view. The SimpleCursorAdapter will ask you for 4 things in particular. The first is the layout of the view to show on the list, that is, what should a list item look like. This is the R.layout.todo_row that tells the adapter what views should be created. In this case we only have an icon and a TextView with the id R.id.label. Second, it will ask you for the cursor that contains the data, which is being set inside the onLoadFinished method (it is null when the adapter is created). Third, it wants to know what columns on the cursor matter. This is the String[] from array that says it should look for the data in the TodoTable.COLUMN_SUMMARY. Last, it needs to know where in the view to put this data, and this is the int[] to that contains the id of the TextView you'll be using to display the text, R.id.label.
In summary, the adapter is like a map between the data from the cursor and the layout for the view. Now, when the list needs a view to show on screen it will ask the adapter to give it one. The adapter then either recycles or creates a view form the layout you provided, fetches the data for each piece of the layout from the cursor and gives it all ready to go to the list to put it on the screen.

Automatic Checkbox list with 5 sec. delay in android

I want to show automatic checklist in android. For example I can have 4 list of item with unchecked check box adjutant to that.
After 5 sec. delay I want to check the first item then move on to second. At the end of 20 sec. I should have all 4 check box checked one by one.
Any idea how should I go on doing this ? I can use list view with checkbox opeion on ..right ??
I am a .net programmer and this is new experience for me so any comment / advise is appreciated.
Here is a basic example I've just written:
public class AutoChecker extends Activity {
private CheckBox checkbox1;
private CheckBox checkbox2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
checkbox1 = (CheckBox) findViewById(R.id.checkbox_1);
checkbox2 = (CheckBox) findViewById(R.id.checkbox_2);
new CheckerAsync(AutoChecker.this).execute(checkbox1, checkbox2);
}
private class CheckerAsync extends AsyncTask<CheckBox, CheckBox, Void>{
private Activity mActivity;
private CheckerAsync(Activity activity) {
mActivity = activity;
}
#Override
protected Void doInBackground(final CheckBox... checkboxes) {
try {
for(int i = 0, j = checkboxes.length; i < j; i++ ){
Thread.sleep(5000);
publishProgress(checkboxes[i]);
}
} catch (InterruptedException e) {}
return null;
}
#Override
public void onProgressUpdate(final CheckBox... checkboxes){
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
checkboxes[0].setChecked(true);
}
});
}
}
}
This is the XML layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<CheckBox
android:id="#+id/checkbox_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Checkbox 1"
/>
<CheckBox
android:id="#+id/checkbox_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Checkbox 2"
/>
</LinearLayout>
Explanation
It uses a class that extends AsyncTask which allows you to use threading in a easy to use/understand way. The way this class is executed is kind of simple:
new CheckerAsync(AutoChecker.this).execute(checkbox1, checkbox2);
You can add as many checkboxes as you want. For instance:
new CheckerAsync(AutoChecker.this).execute(checkbox1, checkbox2, checkbox4, checkbox3);
By the way, I don't know why you are trying to do this. But, if it's for testing purposes, you better take a look at the instrumentation framework.
For the automatic checking with delay, you should use an AsyncTask, like a thread where you can modify things within the Android main UI thread, i.e. like checking the checkboxes.
http://developer.android.com/resources/articles/painless-threading.html
http://www.xoriant.com/blog/mobile-application-development/android-async-task.html
http://developer.android.com/reference/android/os/AsyncTask.html
The checkboxes can be part of a listview, but don't have to be. You can also add them into a LinearLayout with vertical orientation one by one.

Categories

Resources