how to smooth scroll listview like ios in android? - android-listview

I am use data from web using XML parser and setting data using custom adapter for this use asyncTask .
My problem is that some devices like Samsang duos,gallaxy work perfectly but on micromax devices it will not work properly.
My adapter is
public class HallBookingAdapter extends ArrayAdapter<MyHall> {
private Context context;
private ArrayList<MCCIAHall> halls;
private int resource;
MyHall objHall;
public int count;
View view;
public static Boolean isScrollingHalls=true;
LayoutInflater inflater;
static class HallBookingHolder
{
public TextView txtTitle,txtLocation,txtCapacity,txtCapacityTitle;
public ImageView imgHall;
public LinearLayout hallBookingLayout;
}
public HallBookingAdapter(Context context, int resource, ArrayList<MyHall> halls) {
super(context, resource, halls);
this.context=context;
this.halls=halls;
this.resource=resource;
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
count=halls.size();
return halls.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
view=convertView;
objHall=halls.get(position);
HallBookingHolder holder=new HallBookingHolder();
if (convertView==null) {
view = inflater.inflate(resource, null);
holder.txtTitle=(TextView)view.findViewById(R.id.txtListHallTitle);
holder.txtLocation=(TextView)view.findViewById(R.id.txtListHallLocation);
holder.txtCapacity=(TextView)view.findViewById(R.id.txtListHallCapacity);
holder.txtCapacityTitle=(TextView)view.findViewById(R.id.txtListHallCapacityHeadding);
holder.imgHall=(ImageView)view.findViewById(R.id.imgListHall);
view.setTag(holder);
}
else
{
holder = (HallBookingHolder)convertView.getTag();
}
//Creating the Font to the text
Typeface tfLight = Typeface.createFromAsset(context.getAssets(),"OpenSans-Light.ttf");
Typeface tfRegular = Typeface.createFromAsset(context.getAssets(),"OpenSans-Regular.ttf");
Typeface tfsemiBold = Typeface.createFromAsset(context.getAssets(),"OpenSans-Semibold.ttf");
//Setting the font
holder.txtTitle.setTypeface(tfRegular);
holder.txtLocation.setTypeface(tfLight);
holder.txtCapacity.setTypeface(tfsemiBold);
holder.txtCapacityTitle.setTypeface(tfLight);
//Setting data to textview and image
holder.txtTitle.setText(objHall.hallName);
holder.txtLocation.setText(objHall.location);
holder.txtCapacity.setText(objHall.capacity);
//Using Guild Library Image Load using image web url
String imgurl=objHall.getImageUrl();
Glide.load(imgurl).centerCrop().into(holder.imgHall);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(context, HallDetailsActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
});
return view;
}
}

read it listview smooth-scrolling
Using a background thread ("worker thread") removes strain from the
main thread so it can focus on drawing the UI. In many cases, using
AsyncTask provides a simple way to perform your work outside the main
thread. AsyncTask automatically queues up all the execute() requests
and performs them serially. This behavior is global to a particular
process and means you don’t need to worry about creating your own
thread pool.
check this too http://www.itworld.com/development/380008/how-make-smooth-scrolling-listviews-android

Put all your font styles in the if (convertView==null) {} block to set them only once. Now you are setting them every time a new row is created.

Here is a list of quick tips to help you.
Reduce the number of conditions used in the getView of your adapter.
Check and reduce the number of garbage collection warnings that you get in the logs
If you're loading images while scrolling, get rid of them.
Set scrollingCache and animateCache to false (more on this later)
Simplify the hierarchy of the list view row layout
Use the view holder pattern
Here is a link to help you implement these tips. Link

Related

JavaFX8 TreeTableView notifications for scrolled items

I am writing an application that is using a JavaFX8 TreeTableView. The tree table has three columns, two of which are String properties (name and value) and one which has a Canvas widget in it that draws a picture from from data from a database (waveforms). There is also a control on the application that allows the display (of all of the drawings) to be zoomed out or in (or for that matter scrolled left and right).
The name and value columns use StringProperty values from my data model so there are CellValueFactory set for those columns. The drawing column uses both a CellFactory and CellValueFactory like this:
// Waveform column
TreeTableColumn<DrawRow, WaveformTraceBox> waveColumn = new TreeTableColumn<>();
waveColumn.setCellFactory(new Callback<TreeTableColumn<DrawRow, WaveformTraceBox>, TreeTableCell<DrawRow, WaveformTraceBox>>() {
#Override
public TreeTableCell<DrawRow, WaveformTraceBox> call(TreeTableColumn<DrawRow, WaveformTraceBox> param) {
return new WaveformTraceBoxTreeTableViewCell<>();
}
});
waveColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox>, ObservableValue<WaveformTraceBox>>() {
#Override
public ObservableValue<WaveformTraceBox> call(TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox> param) {
return new ReadOnlyObjectWrapper<>(new WaveformTraceBox());
}
});
Where WaveformTraceBoxTreeTableViewCell is:
protected static class WaveformTraceBoxTreeTableViewCell<T> extends TreeTableCell<DrawRow, T> {
public WaveformTraceBoxTreeTableViewCell() {
super();
}
#Override
protected void updateItem(T value, boolean empty) {
super.updateItem(value, empty);
setText(null);
setGraphic(null);
if (!empty && getTreeTableRow().getItem() != null) {
getTreeTableRow().getItem().setTraceBox((WaveformTraceBox)value);
setGraphic((WaveformTraceBox) value);
}
}
DrawRow is my data model. When the user zooms out or in via the controls on the window the draw row model will notify it's associated Canvas drawing item to re-draw its display. The drawing of the display can take some time to do because of the large amount of data that needs to be processed to generate the display.
Now my problem: As the TreeTableView widget is scrolled it will ask for new Canvas widgets -- which get associated with DrawRow items from the data model. However widgets from the list that get scrolled off the screen will get thrown away by the tree widget.
I have found no way to tell if the item I am working with has been thrown away or is not being used any more. So the code is doing much more work than it needs to because it is trying to draw cells that are no longer being used or shown. Eventually this will cause other problems because of garbage collection I think.
So my real question is how can I tell if a cell has been abandoned by the tree table so I can stop trying to update it? Any help with this would greatly be appreciated. I am not able to find this anywhere on the various web searches I have done.
Do you need to worry here? What is still "drawing cells that are no longer being used"? Are you running some kind of update in a background thread on the WaveformTraceBox?
In any event, you've structured this pretty strangely.
First, (less important) why is your WaveformTraceBoxTreeTableViewCell generic? Surely you want
protected static class WaveformTraceBoxTreeTableViewCell extends TreeTableCell<DrawRow, WaveformTraceBox>
and then you can replace T with WaveformTraceBox throughout and get rid of the casts, etc.
Second: if I understand this correctly, WaveformTraceBox is a custom Node subclass of some kind; i.e. it's a UI component. The cell value factory shouldn't really return a UI component - it should return the data to display. The cell factory should then use some UI component to display the data.
That way, you can create a single WaveFormTraceBox in the cell implementation, and update the data it displays in the updateItem(...) method.
So something like:
// Waveform column
TreeTableColumn<DrawRow, WaveformData> waveColumn = new TreeTableColumn<>();
waveColumn.setCellFactory(new Callback<TreeTableColumn<DrawRow, WaveformData>, TreeTableCell<DrawRow, WaveformData>>() {
#Override
public TreeTableCell<DrawRow, WaveformData> call(TreeTableColumn<DrawRow, WaveformData> param) {
return new WaveformTraceBoxTreeTableViewCell();
}
});
waveColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<DrawRow, WaveformData>, ObservableValue<WaveformData>>() {
#Override
public ObservableValue<WaveformTraceBox> call(TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox> param) {
return new ReadOnlyObjectWrapper<>(getDataToDisplayForItem(param.getValue()));
}
});
protected static class WaveformTraceBoxTreeTableViewCell extends TreeTableCell<DrawRow, WaveFormData> {
private WaveformTraceBox traceBox = new WaveformTraceBox();
public WaveformTraceBoxTreeTableViewCell() {
super();
}
#Override
protected void updateItem(WaveFormData value, boolean empty) {
super.updateItem(value, empty);
setText(null);
setGraphic(null);
if (!empty && getTreeTableRow().getItem() != null) {
traceBox.setData(value);
setGraphic(traceBox);
} else {
setGraphic(null);
}
}
}
Obviously you need to define the WaveFormData class to encapsulate the data your WaveFormTraceBox will display, and give the WaveFormTraceBox a setData(WaveFormData) method. If you are using any resources that need to be cleaned up, the invocation of setData(...) will indicate that the previous data is no longer being accessed by that WaveformTraceBox.

retain searchView state on orientation change in a Fragment

I am trying use the actionbarcompat (with the android support library) following the android developer's blog entry.
Basically, I am trying create a Fragment extending the ListFragment. I am using an ArrayAdapter for the listview. I was able to successfully integrate the actionbar compat with a search menu item and could get the search working as well.
I now want to retain the state of the fragment on orientation change as well. I haven't set the setRetainInstance(true) in my fragment. Inorder to retain the state of the search view, i tried the following:
save the text in the SearchView in onSaveInstanceState()
in onCreateView, retrieve the searchText if available
in onCreateOptionsMenu (which would be invoked on every orientation change), I am trying to set the search query to the SearchView instance mSearchView.setQuery(mSearchText, false);
There are 2 issues that I see with this approach:
the onQueryTextChange() is called twice on orientation change - once with the searchText that has been retained (because of mSearchView.setQuery(mSearchText, false);) and again, with an empty String value. This second call with the empty String value updates the list adapater to have all the items without any filtering. I am also not really sure why this is happening.
mSearchView.setQuery(mSearchText, false); isn't setting the query in the SearchView and is not visible in the UI as well (on orientation change, the search view is expanded by default and is focused without any text value though I have set the query).
Outline of my Fragment is as follows:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create and initialize list adapter
....
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.plainlist, container, false);
if (savedInstanceState != null) {
mSearchText = savedInstanceState.getString(RetainDataKeySearchText, null);
}
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (isAdded()) {
if (mSearchView != null) {
String searchText = mSearchView.getQuery().toString();
if (!TextUtils.isEmpty(searchText))
outState.putString(RetainDataKeySearchText, searchText);
}
}
super.onSaveInstanceState(outState);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.search_item_list, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setOnQueryTextListener(this);
if (!TextUtils.isEmpty(mSearchText))
mSearchView.setQuery(mSearchText, false);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed.
searchItems(newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String searchText) {
return true;
}
private void searchItems(String searchText) {
// filter results and update the list adapter
}
The menu xml (search_item_list) file is as follows:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sprinklr="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_search"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/search"
android:orderInCategory="0"
sprinklr:showAsAction="ifRoom|collapseActionView"
sprinklr:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
I would like to know if there is anything that I am missing or if there is a better alternate to retain the state of the SearchView (android.support.v7.widget.SearchView) on orientation change in a ListFragment with actionbarcompat.
As a workaround, replace your
mSearchView.setQuery(mSearchText, false);
with:
final String s = mSearchText;
mSearchView.post(new Runnable() {
#Override
public void run() {
mSearchView.setQuery(s, false);
}
});
It will set the saved string after the system has set the empty string.
I did it with AppCompatActivity rather than with Fragment. I used the equivalent solution as above but the search text wasn't visible even with the post on the search view. I added the menu item expansion before:
mSearchView.post(() -> {
searchItem.expandActionView();
mSearchView.setQuery(mSearchText, false);
mSearchView.clearFocus();
});

Setting a drag image in GWT 2.4

I need to implement drag and drop for cells in a CellTable. Following the example from the MobileWebApp I implemented a custom draggable cell:
public class DraggableCell extends AbstractCell<ProductProxy>{
interface Templates extends SafeHtmlTemplates {
#SafeHtmlTemplates.Template("<div draggable=\"true\">{0}</div>")
SafeHtml simpleTextTemplate(String text);
}
protected Templates templates = GWT.create(Templates.class);
public DraggableCell() {
super("dragstart");
}
#Override
public void render(Context context, ProductProxy value, SafeHtmlBuilder sb){
sb.append(templates.simpleTextTemplate(value.getName()));
}
#Override
public void onBrowserEvent(Context context, Element parent,
ProductProxy value, NativeEvent event,
ValueUpdater<ProductProxy> valueUpdater) {
final Integer cursorOffsetX = 0;
final Integer cursorOffsetY = 0;
if ("dragstart".equals(event.getType())) {
// Save the ID of the entity
DataTransfer dataTransfer = event.getDataTransfer();
dataTransfer.setData("text", value.getId());
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendEscaped(value.getSn());
Element element = DOM.createDiv();
element.setInnerHTML(sb.toSafeHtml().asString());
// Set the helper image.
dataTransfer.setDragImage(element, cursorOffsetX, cursorOffsetY);
}
}
I use a new element for the drag image (in the MobileWebApp they just use the parent element), but unfortunately no image is displayed during the drag. I thought that maybe the new element needs to be attached to the DOM first, so I created a helperPanel and attached the element to it:
DOM.getElementById("dragHelperPanel").appendChild(element);
// Set the helper image.
dataTransfer.setDragImage(element, cursorOffsetX, cursorOffsetY);
This works fine in Firefox 6, but no luck in Chrome (using the latest stable version), so maybe this isn't the right way to do it. Any ideas? Thanks!
You can try the GWT Drag & Drop API. I have used it and its a good one even in mobile devices.
http://code.google.com/p/gwt-dnd/
Try the Demo here,
http://allen-sauer.com/com.allen_sauer.gwt.dnd.demo.DragDropDemo/DragDropDemo.html
Its quite simple to implement and don't have any issues so far for me

Render view based on another view in Eclipse plugin

I am developing an Eclipse plug-in that has currently 2 views. In my first view I have a list of connections displayed in a TableViewer (name and connection status).In my second view I want to load the tables in a database (the connection). This loading will be done by clicking a menu item on a connection ("view details"). These tables will be displayed in a TreeViewer because they can also have children. I have tried to do it this way:
My View class:
public class DBTreeView extends ViewPart {
private TreeViewer treeViewer;
private Connection root = null;
public DBTreeView() {
Activator.getDefault().setDbTreeView(this);
}
public void createPartControl(Composite parent) {
treeViewer = new TreeViewer(parent);
treeViewer.setContentProvider(new DBTreeContentProvider());
treeViewer.setLabelProvider(new DBTreeLabelProvider());
}
public void setInput(Connection conn){
root = conn;
treeViewer.setInput(root);
treeViewer.refresh();
}
}
I made a setInput method that is called from the action registered with the menu item in the connections view with the currently selected connection as argument:
MViewContentsAction class:
public void run(){
selectedConnection = Activator.getDefault().getConnectionsView().getSelectedConnection();
Activator.getDefault().getDbTreeView().setInput(selectedConnection);
}
In my ContentProvider class:
public Object[] getChildren(Object arg0) {
if (arg0 instanceof Connection){
return ((Connection) arg0).getTables().toArray();
}
return EMPTY_ARRAY;
}
where EMPTY_ARRAY is an...empty array
The problem I'm facing is that when in debug mode, this piece of code is not executed somehow:
Activator.getDefault().getDbTreeView().setInput(selectedConnection);
And also nothing happens in the tree view when clicking the menu item. Any ideas?
Thank you
Huh. Ok, what you're doing here is.. not really the right way. What you should be doing is registering your TableViewer as a selection provider.
getSite().setSelectionProvider(tableViewer);
Then, define a selection listener and add it to the view with the tree viewer like this:
ISelectionListener listener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection sel) {
if (!(sel instanceof IStructuredSelection))
return;
IStructuredSelection ss = (IStructuredSelection) sel;
// rest of your code dealing with checking whether selection is what is
//expected and if it is, setting it as an input to
//your tree viewer
}
};
public void createPartControl(Composite parent) {
getSite().getPage().addSelectionListener(listener);
}
Now your tree viewer's input will be changed according to what is selected in the table viewer (btw, don't forget to call treeviewer.refresh() after you set new input).
See an example here.

GWT displaying widgets with asynchronous calls on RootPanel

I am having problems while adding my widget into the RootPanel of another container class. I think that it may be related to the Asynchronous call that I make during the creation of the widget. I have a main class named ImageView which implements EntryPoint. In this class, I am creating an instance of my widget named NewWidget by clicking on a button. However, I cannot display it with the traditional methods:
Here is the EntryPoint class (ImageView):
import com.mycompany.project.client.widgets.NewWidget;
public class ImageViewer implements EntryPoint {
public void onModuleLoad() {
Button b = new Button("Button");
RootPanel.get().add(b);
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
NewWidget w = new NewWidget();
RootPanel.get().add(w);
}
});
}
And here is my widget (NewWidget):
public class NewWidget extends Composite {
final static DataServiceAsync service = (DataServiceAsync) GWT.create(DataService.class);
final FlowPanel mainPanel = new FlowPanel();
public NewWidget() {
fillImagePath();
}
public void fillImagePath(){
ServiceDefTarget endpoint = (ServiceDefTarget) service;
endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "data");
service.getAllDocuments(new AsyncCallback<ArrayList<String>>() {
#Override
public void onFailure(Throwable e) {
Window.alert("Server call failed.");
}
#Override
public void onSuccess(ArrayList<String> paths) {
process(paths);
}
});
}
public void process(ArrayList<String> paths){
ArrayList<String> imagePath = paths;
Image img = new Image(imagePath.get(4));
mainPanel.add(img);
initWidget(mainPanel);
}
}
In this NewWidget, I am making an asynchronous call to my server in order to receive a String ArrayList, which contains 10 Strings that refer to the file path of 10 different images (i.e, "images/01.jpg", "images/02.jpg", and so on). I am pretty sure that I successfully and correctly receive these image paths. I have arbitrarily chosen index number 4 to display in my NewWidget.
The problem is that I cannot display this NewWidget in my ImageView main panel. I can easily display other widgets with this method. With many attempts, I have realized that I can display the image if I add the line RootPanel.get().add(mainPanel) at the end of NewWidget. However, I do not want to make a call that refers to the parent container (RootPanel in ImageView). Why can't I display this image with only instantiating it in my container panel, like I can display any other widget? I am pretty sure that it is related to the Asynchronous call not getting completed before I attempt to add the widget. But I don't know how to fix this.
I would be very glad if people would share their ideas. Thanks.
Move the initWidget(mainPanel) call to the first line the constructor.