Android ActionBar error - android-activity

package mavilla.paavaiinstitutions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class MainActivity extends Activity {
int mPosition = -1;
String mTitle = "";
// Array of strings storing country names
String[] mCountries ;
// Array of integers points to images stored in /res/drawable-ldpi/
int[] mFlags = new int[]{
R.drawable.home,
R.drawable.about,
R.drawable.ins,
R.drawable.campus,
R.drawable.compass,
R.drawable.gallery,
R.drawable.cap,
R.drawable.alumini,
R.drawable.tieup,
R.drawable.contact
};
// Array of strings to initial counts
String[] mCount = new String[]{
"", "", "", "", "",
"", "", "", "", "" };
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private LinearLayout mDrawer ;
private List<HashMap<String,String>> mList ;
private SimpleAdapter mAdapter;
final private String COUNTRY = "country";
final private String FLAG = "flag";
final private String COUNT = "count";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Getting an array of country names
mCountries = getResources().getStringArray(R.array.countries);
// Title of the activity
mTitle = (String)getTitle();
// Getting a reference to the drawer listview
mDrawerList = (ListView) findViewById(R.id.drawer_list);
// Getting a reference to the sidebar drawer ( Title + ListView )
mDrawer = ( LinearLayout) findViewById(R.id.drawer);
// Each row in the list stores country name, count and flag
mList = new ArrayList<HashMap<String,String>>();
for(int i=0;i<10;i++){
HashMap<String, String> hm = new HashMap<String,String>();
hm.put(COUNTRY, mCountries[i]);
hm.put(COUNT, mCount[i]);
hm.put(FLAG, Integer.toString(mFlags[i]) );
mList.add(hm);
}
// Keys used in Hashmap
String[] from = { FLAG,COUNTRY,COUNT };
// Ids of views in listview_layout
int[] to = { R.id.flag , R.id.country , R.id.count};
// Instantiating an adapter to store each items
// R.layout.drawer_layout defines the layout of each item
mAdapter = new SimpleAdapter(this, mList, R.layout.drawer_layout, from, to);
// Getting reference to DrawerLayout
mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
// Creating a ToggleButton for NavigationDrawer with drawer event listener
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer , R.string.drawer_open,R.string.drawer_close){
/** Called when drawer is closed */
public void onDrawerClosed(View view) {
highlightSelectedCountry();
supportInvalidateOptionsMenu();
}
/** Called when a drawer is opened */
public void onDrawerOpened(View drawerView) {
getSupportActionBar().setTitle("Select a Country");
supportInvalidateOptionsMenu();
}
};
// Setting event listener for the drawer
mDrawerLayout.setDrawerListener(mDrawerToggle);
// ItemClick event handler for the drawer items
mDrawerList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
// Increment hit count of the drawer list item
incrementHitCount(position);
if(position < 5) { // Show fragment for countries : 0 to 4
showFragment(position);
}else{ // Show message box for countries : 5 to 9
Toast.makeText(getApplicationContext(), mCountries[position], Toast.LENGTH_LONG).show();
}
// Closing the drawer
mDrawerLayout.closeDrawer(mDrawer);
}
});
// Enabling Up navigation
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
// Setting the adapter to the listView
mDrawerList.setAdapter(mAdapter);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
public void incrementHitCount(int position){
HashMap<String, String> item = mList.get(position);
String count = item.get(COUNT);
item.remove(COUNT);
if(count.equals("")){
count = " 1 ";
}else{
int cnt = Integer.parseInt(count.trim());
cnt ++;
count = " " + cnt + " ";
}
item.put(COUNT, count);
mAdapter.notifyDataSetChanged();
}
public void showFragment(int position){
//Currently selected country
mTitle = mCountries[position];
// Creating a fragment object
CountryFragment cFragment = new CountryFragment();
// Creating a Bundle object
Bundle data = new Bundle();
// Setting the index of the currently selected item of mDrawerList
data.putInt("position", position);
// Setting the position to the fragment
cFragment.setArguments(data);
// Getting reference to the FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
// Creating a fragment transaction
FragmentTransaction ft = fragmentManager.beginTransaction();
// Adding a fragment to the fragment transaction
ft.replace(R.id.content_frame, cFragment);
// Committing the transaction
ft.commit();
}
// Highlight the selected country : 0 to 4
public void highlightSelectedCountry(){
int selectedItem = mDrawerList.getCheckedItemPosition();
if(selectedItem > 4)
mDrawerList.setItemChecked(mPosition, true);
else
mPosition = selectedItem;
if(mPosition!=-1)
getSupportActionBar().setTitle(mCountries[mPosition]);
}
}
i have extended Main Activity from Activity as shown to apply custom theme.
But I'm getting error below in actionBar code:
getSupportActionBar()
// Enabling Up navigation
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
Please help me as i am very new in stackoverflow and android..thanks in advance.

You are no longer using the support ActionBarActivity, but the normal Android Activity.
Thats why instead of
getSupportActionBar() you have to call getActionBar()
supportInvalidateOptionsMenu() you have to call invalidateOptionsMenu()
getSupportFragmentManager() you have to call getFragmentManager()
and so on..

Related

Showing contact from the contact loader Manager

I am showing the contact list from the contact table but not able to get the phone number using the same on RecyclerView.My code is -
package com.oodles.oodlesapprtc;
import android.annotation.SuppressLint;
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.provider.ContactsContract;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.ArrayList;
/**
* Created by ankita on 13/4/17.
*/
public class LoginUserActivity extends AppCompatActivity {
public static final int CONTACT_LOADER_ID = 78;
RecyclerView loginUserRecycler;
ArrayList<ContactBeans> contactBeanses;
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
" COLLATE LOCALIZED ASC";
private static final String[] PROJECTION2 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI,ContactsContract.Contacts.HAS_PHONE_NUMBER
};
private static final String[] PROJECTION3 = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.Contacts.PHOTO_URI, ContactsContract.Contacts.LOOKUP_KEY
};
private static final String[] PROJECTION = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER
};
// private static final String[] PROJECTION1 = {
// ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
// ContactsContract.CommonDataKinds.Phone.NUMBER
// };
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_user_activity);
initViews();
}
private void initViews() {
getLoaderManager().initLoader(0, null, contactLoaderManager);
initRecycler();
}
private void initRecycler() {
loginUserRecycler = (RecyclerView) findViewById(R.id.loginUserRecycler);
loginUserRecycler.setLayoutManager(new LinearLayoutManager(this));
loginUserRecycler.setItemAnimator(new DefaultItemAnimator());
}
LoaderManager.LoaderCallbacks<Cursor> contactLoaderManager = new LoaderManager.LoaderCallbacks<Cursor>() {
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// String[] projectionFields = new String[]{ContactsContract.Contacts._ID,
// ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.PhoneLookup.NORMALIZED_NUMBER,
// ContactsContract.Contacts.PHOTO_URI};
// Construct the loader
// Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
// ContactsContract.Contacts.CONTENT_URI
// Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
// Uri.encode(phoneNumber));
CursorLoader cursorLoader = new CursorLoader(LoginUserActivity.this,
ContactsContract.Contacts.CONTENT_URI, // URI
PROJECTION2, // projection fields
null, // the selection criteria
null, // the selection args
sortOrder // the sort order
);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
loginUserRecycler.setAdapter(new CursorRecyclerAdapter(LoginUserActivity.this, data));
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
};
}
My Adapter is -
package com.oodles.oodlesapprtc;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by ankita on 13/4/17.
*/
public class CursorRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> {
private Cursor mCursor;
private final int mNameColIdx,
mIdColIdx;
int phoneNumber;
int hasPhoneNumber;
private Context mContext;
public CursorRecyclerAdapter(Context context, Cursor cursor) {
mCursor = cursor;
this.mContext = context;
mNameColIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
mIdColIdx = cursor.getColumnIndex(ContactsContract.Contacts._ID);
hasPhoneNumber = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
}
#Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View listItemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_row, parent, false);
return new ContactViewHolder(listItemView);
}
#Override
public void onBindViewHolder(ContactViewHolder contactViewHolder, int pos) {
mCursor.moveToPosition(pos);
String contactName = mCursor.getString(mNameColIdx);
long contactId = mCursor.getLong(mIdColIdx);
Contact c = new Contact();
Log.e("ddhdhdhhdhdhdhd",hasPhoneNumber+"");
c.name = contactName;
c.number = getPhoneNumberFromContactId(contactId);
c.profilePic = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
getPhoneNumberFromContactId(contactId);
contactViewHolder.bind(c);
}
private String getPhoneNumberFromContactId(long contactId) {
String contactNumber = "8874675724";
return contactNumber;
}
#Override
public int getItemCount() {
return mCursor.getCount();
}
}
How can I get the phone number for the same i am getting a cursorindexoutofbound exception and has phone number value as 3 but it can be only 0 or 1 why it is 3 i don't understand this.
Can Anyone please explain this to me also please explain how the contact fetch works
You have a few issues in the code:
You're querying on the Contacts table, but sorting using a CommonDataKinds.Phone table field, that's not good, you can sort using Contacts.DISPLAY_NAME_PRIMARY instead.
cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER) gives you a column index, not the value of the field, that's why you're getting 3 (it's the 4rd field defined in PROJECTION2), change hasPhoneNumber to mHasPhoneNumberIdx to avoid confusion.
add hasPhoneNumber = mCursor.getInt(mHasPhoneNumberIdx); to your onBindViewHolder method, to get the actual value.
Running a long command like a real implementation of getPhoneNumberFromContactId within onBindViewHolder is really bad... you should change your main query so you do two big queries, one for all contacts, one for all phones, and then use some HashMap to get a phone using a contact-id.

FXML, JavaFX 8, TableView: Make a delete button in each row and delete the row accordingly

I am working on a TableView (FXML) where I want to have all the rows accompanied with a delete button at the last column.
Here's a video that shows what I mean: YouTube Delete Button in TableView
Here's what I have in my main controller class:
public Button del() {
Button del = new Button();
del.setText("X");
del.setPrefWidth(30);
del.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
int i = index.get();
if(i > -1) {
goals.remove(i);
list.getSelectionModel().clearSelection();
}
}
});
return del;
}
private SimpleIntegerProperty index = new SimpleIntegerProperty();
#Override
public void initialize(URL location, ResourceBundle resources){
//DateFormat df = new SimpleDateFormat("dd MMM yyyy");
sdate.setValue(LocalDate.now());
edate.setValue(LocalDate.now());
seq.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("id"));
gol.setCellValueFactory(new PropertyValueFactory<Goals, String>("goal"));
sdt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("sdte"));
edt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("edte"));
prog.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("pb"));
del.setCellValueFactory(new PropertyValueFactory<Goals, Button>("x"));
list.setItems(goals);
list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
#Override
public void changed(ObservableValue<?> observable,
Object oldValue, Object newValue) {
index.set(goals.indexOf(newValue));
System.out.println("Index is: "+goals.indexOf(newValue));
}
});
}
Each time I launch the application, I will try to click the delete button from random rows but it always delete the first row. I guess the addListener method I use for list is not properly implemented and indexOf(newValue) is always 0 at every initialisation.
However, it will work if I click a row first and then click the delete button. But this is not what I want. I want users to be able to delete any row if they press the delete button without selecting the row.
Appreciate your help guys!
You need a custom cell factory defined for the column containing the delete button.
TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setCellValueFactory(
param -> new ReadOnlyObjectWrapper<>(param.getValue())
);
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
private final Button deleteButton = new Button("Unfriend");
#Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (person == null) {
setGraphic(null);
return;
}
setGraphic(deleteButton);
deleteButton.setOnAction(
event -> getTableView().getItems().remove(person)
);
}
});
Here is a sample app. It doesn't use FXML, but you could adapt it to work with FXML very easily. Just click on an "Unfriend" button in the "Anti-social" column to delete a friend. Do it a lot and you will soon run out of friends.
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class GestureEvents extends Application {
private TableView<Person> table = new TableView<>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final Label label = new Label("Friends");
label.setFont(new Font("Arial", 20));
final Label actionTaken = new Label();
TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setMinWidth(40);
unfriendCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
private final Button deleteButton = new Button("Unfriend");
#Override
protected void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (person == null) {
setGraphic(null);
return;
}
setGraphic(deleteButton);
deleteButton.setOnAction(event -> data.remove(person));
}
});
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<>("lastName"));
table.setItems(data);
table.getColumns().addAll(unfriendCol, firstNameCol, lastNameCol);
table.setPrefHeight(250);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 10, 10, 10));
vbox.getChildren().addAll(label, table, actionTaken);
VBox.setVgrow(table, Priority.ALWAYS);
stage.setScene(new Scene(vbox));
stage.show();
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private Person(String fName, String lName) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
}

ActionBarActivity with fragment and Tab Bar how to implement it

As you see my Code, it dont have error when run debug, I put the tabhost into my fragment, but when app run. It dont show the tabhost
package com.example.phamxuanson.myapplication;
import android.app.Activity;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private NavigationDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in {#link #restoreActionBar()}.
*/
private CharSequence mTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
mTitle = getTitle();
}
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
.commit();
}
public void onSectionAttached(int number) {
switch (number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
case 2:
mTitle = getString(R.string.title_section2);
break;
case 3:
mTitle = getString(R.string.title_section3);
break;
}
}
public void restoreActionBar() {
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
}
}
}
Please see my piuctures
i.imgur.com/AuPA4GO.png
i.imgur.com/Vlrxuhz.png
i.imgur.com/or8m6Mj.png
Why wasn’t tabhost shown?

My Custom CursorAdapter doesn't update my ListView

I'm having troubles with my Custom CursorAdapter and my ListView, the fact is, I can save data in my sqlite Database in my custom ContentProvider but my ListView is not populated.
I know DB Operations are heavy long operations, therefore I do it in another thread and furthermore CursorLoader is a subclass of AsyncTaskLoader, so it should be prepared for that.
With SimpleCursorAdapter works fine but with this Custom CursorAdapter not.
Can anyone tell me what is wrong and how could I solve it?
Thanks in advance.
My code is the following
public class TextNoteAdapter extends CursorAdapter {
/*********** Declare Used Variables *********/
private Cursor mCursor;
private Context mContext;
private static LayoutInflater mInflater=null;
/************* TextNoteAdapter Constructor *****************/
public TextNoteAdapter (Context context, Cursor cursor, int flags) {
super(context, cursor,flags);
mInflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
mCursor = cursor;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
//LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = mInflater.inflate(R.layout.textnote_info, parent, false);
ViewHolder holder = new ViewHolder();
holder.note_name = (TextView)view.findViewById(R.id.note_name);
holder.creation_date = (TextView)view.findViewById(R.id.creation_date);
holder.modification_date = (TextView)view.findViewById(R.id.modification_date);
holder.label_creation_date = (TextView)view.findViewById(R.id.label_creation_date);
holder.label_modification_date = (TextView)view.findViewById(R.id.label_modification_date);
view.setTag(holder);
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// here we are setting our data what means, take the data from the cursor and put it in views
View vi = view;
ViewHolder holder = (ViewHolder)view.getTag();
if(view==null){
/****** Inflate textnote_info.xml file for each row ( Defined below ) *******/
vi = mInflater.inflate(R.layout.textnote_info, null);
/************ Set holder with LayoutInflater ************/
vi.setTag( holder );
} else
holder=(ViewHolder)vi.getTag();
/************ Set Model values in Holder elements ***********/
holder.note_name.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_NOTE_NAME)));
holder.creation_date.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_CREATION_DATE)));
holder.modification_date.setText(cursor.getString(cursor.getColumnIndex(TextNotesDb.KEY_MODIFICATION_DATE)));
holder.label_creation_date.setText(Constants.LABEL_CREATION_DATE);
holder.label_modification_date.setText(Constants.LABEL_MODIFICATION_DATE);
}
#Override
protected void onContentChanged() {
// TODO Auto-generated method stub
super.onContentChanged();
notifyDataSetChanged();
}
/********* Create a holder Class to contain inflated xml file elements *********/
public static class ViewHolder{
public TextView note_name;
public TextView creation_date;
public TextView modification_date;
public TextView label_creation_date;
public TextView label_modification_date;
}
}
And here my MainActivity
import android.app.Activity;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor>{
private Cursor cursor;
private Button addButton;
private ListView listView;
private TextNoteAdapter dataAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
displayListView();
addButton = (Button)findViewById(R.id.add_textnote);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// starts a new Intent to add a Note
Intent intent = new Intent(getBaseContext(), TextNoteEdit.class);
Bundle bundle = new Bundle();
bundle.putString("mode", "add");
intent.putExtras(bundle);
startActivity(intent);
}
});
}
#Override
protected void onResume() {
super.onResume();
Log.i("TAG", "MainActivity:: onResume");
/** Starts a new or restarts an existing Loader in this manager **/
getLoaderManager().restartLoader(0, null, this);
}
private void displayListView() {
// That ensures a loader is initialized and active.
// If the loader specified by the ID already exists, the last created loader is reused.
// else initLoader() triggers the LoaderManager.LoaderCallbacks method onCreateLoader().
// This is where you implement the code to instantiate and return a new loader
getLoaderManager().initLoader(0, null, this);
// We get ListView from Layout and initialize
listView = (ListView) findViewById(R.id.textnote_list);
// DB takes long, therefore this operation should take place in a new thread!
new Handler().post(new Runnable() {
#Override
public void run() {
dataAdapter = new TextNoteAdapter(MainActivity.this, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(dataAdapter);
Log.i("TAG", "MainActivity:: Handler... Run()");
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
/** Get the cursor, positioned to the corresponding row in the result set **/
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// display the selected note
String noteName = cursor.getString(cursor.getColumnIndexOrThrow(TextNotesDb.KEY_NOTE_NAME));
Toast.makeText(getApplicationContext(), noteName, Toast.LENGTH_SHORT).show();
String rowId = cursor.getString(cursor.getColumnIndexOrThrow(TextNotesDb.KEY_ROWID));
// starts a new Intent to update/delete a Textnote
// pass in row Id to create the Content URI for a single row
Intent intent = new Intent(getBaseContext(), TextNoteEdit.class);
Bundle bundle = new Bundle();
bundle.putString("mode", "update");
bundle.putString("rowId", rowId);
intent.putExtras(bundle);
startActivityForResult(intent, 1);
}
});
}
/** This is called when a new Loader needs to be created.**/
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.i("TAG", "MainActivity:: onCreateLoader");
String[] projection = {
TextNotesDb.KEY_ROWID,
TextNotesDb.KEY_GUID,
TextNotesDb.KEY_NOTE_NAME,
TextNotesDb.KEY_NOTE,
TextNotesDb.KEY_CREATION_DATE,
TextNotesDb.KEY_MODIFICATION_DATE
};
CursorLoader cursorLoader = new CursorLoader(this, MyContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
dataAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
dataAdapter.swapCursor(null);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
As in comment below my Question, I could solve it by adding 2 lines. Now it should look like this
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
dataAdapter.notifyDataSetChanged(); // <-
listView.setAdapter(dataAdapter); // <-
dataAdapter.swapCursor(data);
}

How to create Drag n Drop for Cells in a DataGrid

I'm trying to add drag-n-drop to cell widgets. More specifically, I want to drag and drop ClickableTextCells, but they don't have the specific methods and not even .addDomHandler, so I can't just create something like .addDomHandler(new DragStartHandler() { ... }
Can someone give some help on how to DnD cells, preferably with pure GWT?
I do not know how to implement a DnD with GWT, but I know how to implement a CnC (Clic 'n Clic), which might interest you. DnD are cool, fun and beautiful, but I think that some times they are not very convenient. For instance if you have a big screen requiring a scroll, and if you want to DnD an item from the top to the bottom, it is not so convenient to have to hold the mouse... But this just a personnal feeling...
Anyway, I would recommand you to use a ListDataProvider along with simple events, in order to move your items: the first clic selects the source item, and the second clic selects the destination. Once the source and the destination are known, you can move your item.
It works well for me... and if you add some styles to highlight source and destination, it is very nice.
Example:
This is the main class:
import java.util.ArrayList;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
public class Clic_Clic {
private static final Integer LEFT = 0;
private static final Integer CENTER = 1;
private static final Integer RIGHT = 2;
private ClicClicSelectionModel<Item> selectionModel = new ClicClicSelectionModel<Item>();
ListDataProvider<Item> leftLDP = new ListDataProvider<Item>();
ListDataProvider<Item> centerLDP = new ListDataProvider<Item>();
ListDataProvider<Item> rightLDP = new ListDataProvider<Item>();
FocusPanel left = new FocusPanel(), center = new FocusPanel(), right = new FocusPanel();
Item selected = null;
public Clic_Clic() {
// --- Builds the GUI
DialogBox clic_clic = buildGUI();
clic_clic.center();
clic_clic.show();
// --- Initializes data
configureSelectionManagement();
initCellLists();
configureAddAndRemove();
// --- Fills the left LDP
leftLDP.getList().add(new Item("Fraternité", LEFT));
leftLDP.refresh();
// --- Fills the center LDP
centerLDP.getList().add(new Item("Egalité", LEFT));
centerLDP.refresh();
// --- Fills the right LDP
rightLDP.getList().add(new Item("Liberté", RIGHT));
rightLDP.refresh();
}
private DialogBox buildGUI() {
DialogBox db = new DialogBox();
db.setText("A simple example for Clic 'n Clic");
db.setSize("300px", "200px");
db.setGlassEnabled(true);
db.setModal(true);
FlowPanel fp = buildContent();
db.add(fp);
return db;
}
private FlowPanel buildContent() {
Grid g = new Grid(1, 3);
g.setSize("300px", "200px");
g.setWidget(0, 0, left);
left.setSize("100px", "100px");
left.getElement().getStyle().setBackgroundColor("blue");
g.setWidget(0, 1, center);
center.setSize("100px", "100px");
g.setWidget(0, 2, right);
right.setSize("100px", "100px");
right.getElement().getStyle().setBackgroundColor("red");
FlowPanel fp = new FlowPanel();
fp.setSize("300px", "200px");
fp.add(new Label("Do you know the correct order ?"));
fp.add(g);
return fp;
}
private void initCellLists() {
// --- Associates the left panel with the leftLDP ListDataProvider
CellList<Item> cellListLeft = new CellList<Item>(new MyCell());
cellListLeft.setSelectionModel(selectionModel);
left.add(cellListLeft);
leftLDP = new ListDataProvider<Item>(new ArrayList<Item>());
leftLDP.addDataDisplay(cellListLeft);
// --- Associates the center panel with the centerLDP ListDataProvider
CellList<Item> cellListCenter = new CellList<Item>(new MyCell());
cellListCenter.setSelectionModel(selectionModel);
center.add(cellListCenter);
centerLDP = new ListDataProvider<Item>(new ArrayList<Item>());
centerLDP.addDataDisplay(cellListCenter);
// --- Associates the right panel with the rightLDP ListDataProvider
CellList<Item> cellListRight = new CellList<Item>(new MyCell());
cellListRight.setSelectionModel(selectionModel);
right.add(cellListRight);
rightLDP = new ListDataProvider<Item>(new ArrayList<Item>());
rightLDP.addDataDisplay(cellListRight);
}
private void configureAddAndRemove() {
// --- If the user clic on the left
left.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (selected != null) {
// --- If the selected item comes from the right
if (selected.getContainerIndex() == RIGHT) {
rightLDP.getList().remove(selected);
rightLDP.refresh();
selected.setContainerIndex(LEFT);
leftLDP.getList().add(selected);
leftLDP.refresh();
selected = null;
}
// --- If the selected item comes from the center
if (selected.getContainerIndex() == CENTER) {
centerLDP.getList().remove(selected);
centerLDP.refresh();
selected.setContainerIndex(LEFT);
leftLDP.getList().add(selected);
leftLDP.refresh();
selected = null;
}
}
}
});
// --- If the user clic on the center
center.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (selected != null) {
// --- If the selected item comes from the right
if (selected.getContainerIndex() == RIGHT) {
rightLDP.getList().remove(selected);
rightLDP.refresh();
selected.setContainerIndex(CENTER);
centerLDP.getList().add(selected);
centerLDP.refresh();
selected = null;
}
// --- If the selected item comes from the left
if (selected.getContainerIndex() == LEFT) {
leftLDP.getList().remove(selected);
leftLDP.refresh();
selected.setContainerIndex(CENTER);
centerLDP.getList().add(selected);
centerLDP.refresh();
selected = null;
}
}
}
});
// --- If the user clic on the right
right.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// --- If the selected item comes from the left
if (selected.getContainerIndex() == LEFT) {
leftLDP.getList().remove(selected);
leftLDP.refresh();
selected.setContainerIndex(RIGHT);
rightLDP.getList().add(selected);
rightLDP.refresh();
selected = null;
}
// --- If the selected item comes from the center
if (selected.getContainerIndex() == CENTER) {
centerLDP.getList().remove(selected);
centerLDP.refresh();
selected.setContainerIndex(RIGHT);
rightLDP.getList().add(selected);
rightLDP.refresh();
selected = null;
}
}
});
}
#SuppressWarnings("hiding")
class ClicClicSelectionModel<Item> extends SingleSelectionModel<Item> {
#Override
public void setSelected(Item object, boolean selected) {
if (getSelectedObject() != null && getSelectedObject().equals(object)) {
super.setSelected(object, !selected);
} else {
super.setSelected(object, selected);
}
};
}
private void configureSelectionManagement() {
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
Item selected = selectionModel.getSelectedObject();
updateSelected(selected);
}
});
}
private void updateSelected(Item item) {
// --- If no item has been selected, update the selected item
if (selected == null) {
selected = item;
}
}
}
You also need this one:
public class Item {
private String label;
private Integer containerIndex;
public Item(String l, Integer id) {
this.label = l;
this.containerIndex = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getContainerIndex() {
return containerIndex;
}
public void setContainerIndex(Integer containerIndex) {
this.containerIndex = containerIndex;
}
}
And finally, this one:
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
public class MyCell extends AbstractCell<Item> {
#Override
public void render(com.google.gwt.cell.client.Cell.Context context, Item value, SafeHtmlBuilder sb) {
if (value != null) {
// --- If the value comes from the user, we escape it to avoid XSS
// attacks.
SafeHtml safeValue = SafeHtmlUtils.fromString(value.getLabel());
sb.append(safeValue);
}
}
}
Here you go.
Next time I'll try to make a fun example :)
Hope it helps.