Cancel scrolling in Layout Manager - user-interface

I can't find solution for the following problem. I have custom list field, which overlaps the boundaries of its layout manager. List field consumes navigation events from manager to highlight currently selected row with special color. Layout manager is configured to support scrolling. When I scroll trackwheel down, layout manager invokes scrolling and then passes navigation event to its child, the list field. It results in inproper scrolling, because manager scrolls the whole list down to its bottom hiding list rows on the top including the selected row.
What I want is to ignore scrolling while currently selected list row is still visible and employ it otherwise.
I'm using JDE 4.2.1

Let's say we have ListField implementation:
class LabelListField extends ListField implements ListFieldCallback {
private Vector mValues;
public LabelListField(Vector values) {
super(0);
setRowHeight(getFont().getHeight() + 10);
setCallback(this);
mValues = values;
setSize(mValues.size());
}
public void drawListRow(ListField listField, Graphics g, int index, int y,
int width) {
g.drawText((String) mValues.elementAt(index), 0, y);
}
public Object get(ListField list, int index) {
return mValues.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int start) {
for (int x = start; x < mValues.size(); ++x) {
String value = (String) mValues.elementAt(x);
if (value.startsWith(prefix)) {
return x;
}
}
return -1;
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
}
If we want to align this list within upper and lower fields this way:
ListField with scroll http://img6.imageshack.us/img6/7025/8800j.png
we can limit it's height using custom manager:
class ListManager extends HorizontalFieldManager {
ListField mListField;
public ListManager(ListField listField) {
super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
mListField = listField;
add(mListField);
}
public int getPreferredHeight() {
int result = Display.getHeight();
Manager manager = getManager();
if (null != manager) {
for (int i = 0, count = manager.getFieldCount(); i < count; i++) {
if (manager.getField(i) != this)
result -= manager.getField(i).getPreferredHeight();
}
}
// size down to fit max rows without splitting
result = result - result % mListField.getRowHeight();
return result;
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(maxWidth, maxHeight);
setExtent(maxWidth, getPreferredHeight());
}
}
Now we can use it:
class Scr extends FullScreen implements FieldChangeListener {
LabelField mHeader;
ListManager mHFMList;
HorizontalFieldManager mHFMButton;
LabelListField mListField;
ButtonField mButton;
public Scr() {
super(DEFAULT_MENU | DEFAULT_CLOSE);
mHeader = new LabelField("List Field", FIELD_HCENTER);
add(mHeader);
Vector values = new Vector();
values.addElement("first");
values.addElement("second");
values.addElement("third");
values.addElement("fourth");
values.addElement("fifth");
values.addElement("sixth");
values.addElement("seventh");
values.addElement("eight");
mListField = new LabelListField(values);
mHFMList = new ListManager(mListField);
add(mHFMList);
mHFMButton = new HorizontalFieldManager(FIELD_HCENTER);
add(mHFMButton);
mButton = new ButtonField("Exit", ButtonField.CONSUME_CLICK);
mButton.setChangeListener(this);
mHFMButton.add(mButton);
}
public void fieldChanged(Field field, int context) {
if (mButton == field)
close();
}
}
Tested on eJDE 4.2.1.17 8800

all here's the solution that helped me. By overriding moveFocus in such specific way I managed to modify default behavior of scrolling in layout manager - it skips first items of list field allowing them to stay on top.
public int moveFocus(int amount, int status, int time) {
invalidate(getSelectedIndex());
int unused = super.moveFocus(amount, status, time);
return Math.abs(unused) + 1;
}

Related

Scroll Index method not firing consistently

In a Xamarin.Forms and Xamarin.Android project I create a Custom Render and Adapter for a ListView.
The adapter implements BaseAdapter and ISectionIndexer. The custom render of this control is using FastScroll feature, in Android when you tap this scroll a bubble with a index letter appears. This works fine, but my idea is to have a way to catch the selected index after releasing scroll and that scroll "bubble" disappears.
I thought with the following class (in the GetSectionForPosition method) could achieve that:
public class ListViewconIndexAdapter : BaseAdapter<string>, ISectionIndexer
{
string[] items;
Activity context;
string[] sections;
Java.Lang.Object[] sectionsObjects;
Dictionary<string, int> alphaIndex;
public ListViewconIndexAdapter(Activity context, string[] items) : base()
{
this.context = context;
this.items = items;
alphaIndex = new Dictionary<string, int>();
for (int i = 0; i < items.Length; i++)
{
var key = items[i][0].ToString();
if (!alphaIndex.ContainsKey(key))
alphaIndex.Add(key, i);
}
sections = new string[alphaIndex.Keys.Count];
alphaIndex.Keys.CopyTo(sections, 0);
sectionsObjects = new Java.Lang.Object[sections.Length];
for (int i = 0; i < sections.Length; i++)
{
sectionsObjects[i] = new Java.Lang.String(sections[i]);
}
}
public override Java.Lang.Object GetItem(int position)
{
return position;
}
public override long GetItemId(int position)
{
return position;
}
public override string this[int position]
{
get { return items[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
return view;
}
//Fill in cound here, currently 0
public override int Count
{
get { return items.Length; }
}
// -- ISectionIndexer --
public int GetPositionForSection(int section)
{
return alphaIndex[sections[section]];
}
public int GetSectionForPosition(int position)
{ // this method isn't called in this example, but code is provided for completeness
int prevSection = 0;
for (int i = 0; i < sections.Length; i++)
{
if (GetPositionForSection(i) > position)
{
break;
}
prevSection = i;
}
Console.WriteLine(prevSection);
Console.WriteLine(sections[prevSection]);
//Toast.MakeText(context, sections[prevSection], ToastLength.Short).Show();
Xamarin.Forms.MessagingCenter.Send<object,string>(this, "CambioSeccion", sections[prevSection]);
return prevSection;
}
}
I put those Console.writeline for checking the index letter and that Message send is a way to send it back to PCL/NET Standard code (to show an DisplayAlert or something).
But the problem is that method firing is not consistent, for example, sometimes you fast scroll down to 'C' but Console doesn't print anything after releasing it there, but after touching it again where you leave it, it fires up. But sometimes it works like i want, it prints after release the scroll at selected index.
ListView has two different scroll listeners, AbsListView.IOnScrollListener and AbsListView.IOnScrollChangeListener (this one was added in API 23) and a touch listener (AbsListView.IOnTouchListener)
I think based upon your use-case, you are looking for the OnScrollStateChanged and when it goes into idle state and you are not touching the listview, do something (or vice versa).
Example (adjust to your needs of course):
public class MyScrollListener : Java.Lang.Object, AbsListView.IOnTouchListener, AbsListView.IOnScrollListener, AbsListView.IOnScrollChangeListener //(API23)
{
bool touching;
bool scrolling;
public void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
}
public void OnScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
}
public void OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
{
switch(scrollState)
{
case ScrollState.Idle:
if (!touching)
{
scrolling = false;
GetSelection();
}
break;
default:
scrolling = true;
break;
}
}
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Up:
touching = false;
if (!scrolling)
GetSelection();
break;
default:
touching = true;
break;
}
return true;
}
void GetSelection()
{
// touch and srolling is done, do something
}
}
Usage:
var scrollListener = new MyScrollListener();
listView.SetOnTouchListener(scrollListener);
listView.SetOnScrollListener(scrollListener);
listView.SetOnScrollChangeListener(scrollListener); // API23

How to get the text position from the pdf page in iText 7

I am trying to find the text position in PDF page?
What I have tried is to get the text in the PDF page by PDF Text Extractor using simple text extraction strategy. I am looping each word to check if my word exists. split the words using:
var Words = pdftextextractor.Split(new char[] { ' ', '\n' });
What I wasn't able to do is to find the text position. The problem is I wasn't able to find the location of the text. All I need to find is the y co-ordinates of the word in the PDF file.
I was able to manipulate it with my previous version for Itext5. I don't know if you are looking for C# but that is what the below code is written in.
using iText.Kernel.Geom;
using iText.Kernel.Pdf.Canvas.Parser;
using iText.Kernel.Pdf.Canvas.Parser.Data;
using iText.Kernel.Pdf.Canvas.Parser.Listener;
using iTextSharp.text.pdf.parser;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class TextLocationStrategy : LocationTextExtractionStrategy
{
private List<textChunk> objectResult = new List<textChunk>();
public override void EventOccurred(IEventData data, EventType type)
{
if (!type.Equals(EventType.RENDER_TEXT))
return;
TextRenderInfo renderInfo = (TextRenderInfo)data;
string curFont = renderInfo.GetFont().GetFontProgram().ToString();
float curFontSize = renderInfo.GetFontSize();
IList<TextRenderInfo> text = renderInfo.GetCharacterRenderInfos();
foreach (TextRenderInfo t in text)
{
string letter = t.GetText();
Vector letterStart = t.GetBaseline().GetStartPoint();
Vector letterEnd = t.GetAscentLine().GetEndPoint();
Rectangle letterRect = new Rectangle(letterStart.Get(0), letterStart.Get(1), letterEnd.Get(0) - letterStart.Get(0), letterEnd.Get(1) - letterStart.Get(1));
if (letter != " " && !letter.Contains(' '))
{
textChunk chunk = new textChunk();
chunk.text = letter;
chunk.rect = letterRect;
chunk.fontFamily = curFont;
chunk.fontSize = curFontSize;
chunk.spaceWidth = t.GetSingleSpaceWidth() / 2f;
objectResult.Add(chunk);
}
}
}
}
public class textChunk
{
public string text { get; set; }
public Rectangle rect { get; set; }
public string fontFamily { get; set; }
public int fontSize { get; set; }
public float spaceWidth { get; set; }
}
I also get down to each individual character because it works better for my process. You can manipulate the names, and of course the objects, but I created the textchunk to hold what I wanted, rather than have a bunch of renderInfo objects.
You can implement this by adding a few lines to grab the data from your pdf.
PdfDocument reader = new PdfDocument(new PdfReader(filepath));
FilteredEventListener listener = new FilteredEventListener();
var strat = listener.AttachEventListener(new TextExtractionStrat());
PdfCanvasProcessor processor = new PdfCanvasProcessor(listener);
processor.ProcessPageContent(reader.GetPage(1));
Once you are this far, you can pull the objectResult from the strat by making it public or creating a method within your class to grab the objectResult and do something with it.
#Joris' answer explains how to implement a completely new extraction strategy / event listener for the task. Alternatively one can try and tweak an existing text extraction strategy to do what you required.
This answer demonstrates how to tweak the existing LocationTextExtractionStrategy to return both the text and its characters' respective y coordinates.
Beware, this is but a proof-of-concept which in particular assumes text to be written horizontally, i.e. using an effective transformation matrix (ctm and text matrix combined) with b and c equal to 0.
Furthermore the character and coordinate retrieval methods of TextPlusY are not at all optimized and might take long to execute.
As the OP did not express a language preference, here a solution for iText7 for Java:
TextPlusY
For the task at hand one needs to be able to retrieve character and y coordinates side by side. To make this easier I use a class representing both text its characters' respective y coordinates. It is derived from CharSequence, a generalization of String, which allows it to be used in many String related functions:
public class TextPlusY implements CharSequence
{
final List<String> texts = new ArrayList<>();
final List<Float> yCoords = new ArrayList<>();
//
// CharSequence implementation
//
#Override
public int length()
{
int length = 0;
for (String text : texts)
{
length += text.length();
}
return length;
}
#Override
public char charAt(int index)
{
for (String text : texts)
{
if (index < text.length())
{
return text.charAt(index);
}
index -= text.length();
}
throw new IndexOutOfBoundsException();
}
#Override
public CharSequence subSequence(int start, int end)
{
TextPlusY result = new TextPlusY();
int length = end - start;
for (int i = 0; i < yCoords.size(); i++)
{
String text = texts.get(i);
if (start < text.length())
{
float yCoord = yCoords.get(i);
if (start > 0)
{
text = text.substring(start);
start = 0;
}
if (length > text.length())
{
result.add(text, yCoord);
}
else
{
result.add(text.substring(0, length), yCoord);
break;
}
}
else
{
start -= text.length();
}
}
return result;
}
//
// Object overrides
//
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
for (String text : texts)
{
builder.append(text);
}
return builder.toString();
}
//
// y coordinate support
//
public TextPlusY add(String text, float y)
{
if (text != null)
{
texts.add(text);
yCoords.add(y);
}
return this;
}
public float yCoordAt(int index)
{
for (int i = 0; i < yCoords.size(); i++)
{
String text = texts.get(i);
if (index < text.length())
{
return yCoords.get(i);
}
index -= text.length();
}
throw new IndexOutOfBoundsException();
}
}
(TextPlusY.java)
TextPlusYExtractionStrategy
Now we extend the LocationTextExtractionStrategy to extract a TextPlusY instead of a String. All we need for that is to generalize the method getResultantText.
Unfortunately the LocationTextExtractionStrategy has hidden some methods and members (private or package protected) which need to be accessed here; thus, some reflection magic is required. If your framework does not allow this, you'll have to copy the whole strategy and manipulate it accordingly.
public class TextPlusYExtractionStrategy extends LocationTextExtractionStrategy
{
static Field locationalResultField;
static Method sortWithMarksMethod;
static Method startsWithSpaceMethod;
static Method endsWithSpaceMethod;
static Method textChunkSameLineMethod;
static
{
try
{
locationalResultField = LocationTextExtractionStrategy.class.getDeclaredField("locationalResult");
locationalResultField.setAccessible(true);
sortWithMarksMethod = LocationTextExtractionStrategy.class.getDeclaredMethod("sortWithMarks", List.class);
sortWithMarksMethod.setAccessible(true);
startsWithSpaceMethod = LocationTextExtractionStrategy.class.getDeclaredMethod("startsWithSpace", String.class);
startsWithSpaceMethod.setAccessible(true);
endsWithSpaceMethod = LocationTextExtractionStrategy.class.getDeclaredMethod("endsWithSpace", String.class);
endsWithSpaceMethod.setAccessible(true);
textChunkSameLineMethod = TextChunk.class.getDeclaredMethod("sameLine", TextChunk.class);
textChunkSameLineMethod.setAccessible(true);
}
catch(NoSuchFieldException | NoSuchMethodException | SecurityException e)
{
// Reflection failed
}
}
//
// constructors
//
public TextPlusYExtractionStrategy()
{
super();
}
public TextPlusYExtractionStrategy(ITextChunkLocationStrategy strat)
{
super(strat);
}
#Override
public String getResultantText()
{
return getResultantTextPlusY().toString();
}
public TextPlusY getResultantTextPlusY()
{
try
{
List<TextChunk> textChunks = new ArrayList<>((List<TextChunk>)locationalResultField.get(this));
sortWithMarksMethod.invoke(this, textChunks);
TextPlusY textPlusY = new TextPlusY();
TextChunk lastChunk = null;
for (TextChunk chunk : textChunks)
{
float chunkY = chunk.getLocation().getStartLocation().get(Vector.I2);
if (lastChunk == null)
{
textPlusY.add(chunk.getText(), chunkY);
}
else if ((Boolean)textChunkSameLineMethod.invoke(chunk, lastChunk))
{
// we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
if (isChunkAtWordBoundary(chunk, lastChunk) &&
!(Boolean)startsWithSpaceMethod.invoke(this, chunk.getText()) &&
!(Boolean)endsWithSpaceMethod.invoke(this, lastChunk.getText()))
{
textPlusY.add(" ", chunkY);
}
textPlusY.add(chunk.getText(), chunkY);
}
else
{
textPlusY.add("\n", lastChunk.getLocation().getStartLocation().get(Vector.I2));
textPlusY.add(chunk.getText(), chunkY);
}
lastChunk = chunk;
}
return textPlusY;
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new RuntimeException("Reflection failed", e);
}
}
}
(TextPlusYExtractionStrategy.java)
Usage
Using these two classes you can extract text with coordinates and search therein like this:
try ( PdfReader reader = new PdfReader(YOUR_PDF);
PdfDocument document = new PdfDocument(reader) )
{
TextPlusYExtractionStrategy extractionStrategy = new TextPlusYExtractionStrategy();
PdfPage page = document.getFirstPage();
PdfCanvasProcessor parser = new PdfCanvasProcessor(extractionStrategy);
parser.processPageContent(page);
TextPlusY textPlusY = extractionStrategy.getResultantTextPlusY();
System.out.printf("\nText from test.pdf\n=====\n%s\n=====\n", textPlusY);
System.out.print("\nText with y from test.pdf\n=====\n");
int length = textPlusY.length();
float lastY = Float.MIN_NORMAL;
for (int i = 0; i < length; i++)
{
float y = textPlusY.yCoordAt(i);
if (y != lastY)
{
System.out.printf("\n(%4.1f) ", y);
lastY = y;
}
System.out.print(textPlusY.charAt(i));
}
System.out.print("\n=====\n");
System.out.print("\nMatches of 'est' with y from test.pdf\n=====\n");
Matcher matcher = Pattern.compile("est").matcher(textPlusY);
while (matcher.find())
{
System.out.printf("from character %s to %s at y position (%4.1f)\n", matcher.start(), matcher.end(), textPlusY.yCoordAt(matcher.start()));
}
System.out.print("\n=====\n");
}
(ExtractTextPlusY test method testExtractTextPlusYFromTest)
For my test document
the output of the test code above is
Text from test.pdf
=====
Ein Dokumen t mit einigen
T estdaten
T esttest T est test test
=====
Text with y from test.pdf
=====
(691,8) Ein Dokumen t mit einigen
(666,9) T estdaten
(642,0) T esttest T est test test
=====
Matches of 'est' with y from test.pdf
=====
from character 28 to 31 at y position (666,9)
from character 39 to 42 at y position (642,0)
from character 43 to 46 at y position (642,0)
from character 49 to 52 at y position (642,0)
from character 54 to 57 at y position (642,0)
from character 59 to 62 at y position (642,0)
=====
My locale uses the comma as decimal separator, you might see 666.9 instead of 666,9.
The extra spaces you see can be removed by fine-tuning the base LocationTextExtractionStrategy functionality further. But that is the focus of other questions...
First, SimpleTextExtractionStrategy is not exactly the 'smartest' strategy (as the name would suggest.
Second, if you want the position you're going to have to do a lot more work. TextExtractionStrategy assumes you are only interested in the text.
Possible implementation:
implement IEventListener
get notified for all events that render text, and store the corresponding TextRenderInfo object
once you're finished with the document, sort these objects based on their position in the page
loop over this list of TextRenderInfo objects, they offer both the text being rendered and the coordinates
how to:
implement ITextExtractionStrategy (or extend an existing
implementation)
use PdfTextExtractor.getTextFromPage(doc.getPage(pageNr), strategy), where strategy denotes the strategy you created in step 1
your strategy should be set up to keep track of locations for the text it processed
ITextExtractionStrategy has the following method in its interface:
#Override
public void eventOccurred(IEventData data, EventType type) {
// you can first check the type of the event
if (!type.equals(EventType.RENDER_TEXT))
return;
// now it is safe to cast
TextRenderInfo renderInfo = (TextRenderInfo) data;
}
Important to keep in mind is that rendering instructions in a pdf do not need to appear in order.
The text "Lorem Ipsum Dolor Sit Amet" could be rendered with instructions similar to:
render "Ipsum Do"
render "Lorem "
render "lor Sit Amet"
You will have to do some clever merging (depending on how far apart two TextRenderInfo objects are), and sorting (to get all the TextRenderInfo objects in the proper reading order.
Once that's done, it should be easy.
For anyone looking for a simple Rectangle object this worked for me. I made these two classes, and call the static method "GetTextCoordinates" with your page and desired text.
public class PdfTextLocator : LocationTextExtractionStrategy
{
public string TextToSearchFor { get; set; }
public List<TextChunk> ResultCoordinates { get; set; }
/// <summary>
/// Returns a rectangle with a given location of text on a page. Returns null if not found.
/// </summary>
/// <param name="page">Page to Search</param>
/// <param name="s">String to be found</param>
/// <returns></returns>
public static Rectangle GetTextCoordinates(PdfPage page, string s)
{
PdfTextLocator strat = new PdfTextLocator(s);
PdfTextExtractor.GetTextFromPage(page, strat);
foreach (TextChunk c in strat.ResultCoordinates)
{
if (c.Text == s)
return c.ResultCoordinates;
}
return null;
}
public PdfTextLocator(string textToSearchFor)
{
this.TextToSearchFor = textToSearchFor;
ResultCoordinates = new List<TextChunk>();
}
public override void EventOccurred(IEventData data, EventType type)
{
if (!type.Equals(EventType.RENDER_TEXT))
return;
TextRenderInfo renderInfo = (TextRenderInfo)data;
IList<TextRenderInfo> text = renderInfo.GetCharacterRenderInfos();
for (int i = 0; i < text.Count; i++)
{
if (text[i].GetText() == TextToSearchFor[0].ToString())
{
string word = "";
for (int j = i; j < i + TextToSearchFor.Length && j < text.Count; j++)
{
word = word + text[j].GetText();
}
float startX = text[i].GetBaseline().GetStartPoint().Get(0);
float startY = text[i].GetBaseline().GetStartPoint().Get(1);
ResultCoordinates.Add(new TextChunk(word, new Rectangle(startX, startY, text[i].GetAscentLine().GetEndPoint().Get(0) - startX, text[i].GetAscentLine().GetEndPoint().Get(0) - startY)));
}
}
}
}
public class TextChunk
{
public string Text { get; set; }
public Rectangle ResultCoordinates { get; set; }
public TextChunk(string s, Rectangle r)
{
Text = s;
ResultCoordinates = r;
}
}

Keyword Search for ListField in Blackberry

I am creating a ListField. in each row of I am adding a image and 3 labelfield.
Can any one tell me how to create a keywordfilterField for this...
Thanks in advance
I am new to blackberry.
Little code will help me alot
This is my code for creating a custom list
class CustomListField extends ListField implements ListFieldCallback
{
String type;
int DISPLAY_WIDTH = Display.getWidth();
int DISPLAY_HEIGHT = Display.getHeight();
Vector mItems = new Vector();
Vector mine = new Vector();
Vector three= new Vector();
// SizedVFM mListManager = new SizedVFM(DISPLAY_WIDTH, DISPLAY_HEIGHT - 40);
Bitmap searchresult = Bitmap.getBitmapResource("res/searchresult.png");
HorizontalFieldManager hfManager;
Bitmap image ,image1;
int z = this.getRowHeight();
CustomListField(String text1,String text2,String type)
{
for (int i = 1; i < 31; i++)
{
mItems.addElement(text1 +String.valueOf(i));
mine.addElement(" "+text2);
three.addElement("31");
}
this.type=type;
this.setRowHeight((2*z));
this.setCallback(this);
this.setSize(20);
//mListManager.add(mListField);
//add(mListManager);
}
public void drawListRow(ListField field, Graphics g, int i, int y, int w)
{
// Draw the text.
image = Bitmap.getBitmapResource("res/searchresult.png");
String text = (String) get(field, i);
String mytext = (String)mine.elementAt(i);
String urtext=(String)three.elementAt(i);
g.drawBitmap(0, y, image.getWidth(),image.getHeight(), image, 0, 0);
g.drawText(text, image.getWidth(), y, 0, w);
g.setColor(Color.GRAY);
g.drawText(mytext, image.getWidth(), y+getFont().getHeight(), 0, w);
g.drawText(urtext,Graphics.getScreenWidth()*7/8,y,0,w);
if (i != 0)
{
g.drawLine(0, y, w, y);
}
}
public Object get(ListField listField, int index)
{
return mItems.elementAt(index);
}
public int getPreferredWidth(ListField listField)
{
return DISPLAY_WIDTH;
}
public int indexOfList(ListField listField, String prefix, int start)
{
return 0;
}
protected boolean touchEvent(TouchEvent message)
{
// If click, process Field changed
if ( message.getEvent() == TouchEvent.CLICK )
{
if(type.equals("Stops"))
UiApplication.getUiApplication().pushScreen(new SearchScreen("Services"));
else if(type.equals("Services"))
UiApplication.getUiApplication().pushScreen(new SearchScreen("Stops"));
return true;
}
return super.touchEvent(message);
}
}
The problem with KeywordFilterField is that it uses internally its own ListField, so I think it is going to be difficult to customize. If you wanted to use it as it is provided, you'll have to use it as follows:
//KeywordFilterField contains a ListField to display and a search edit field to type in the words
KeywordFilterField keywordFilterField = new KeywordFilterField();
//Instantiate the sorted collection:
CustomList cl = new CustomList(mItems);
//Pass the custom collection
keywordFilterField.setSourceList(cl, cl);
//Now you have to add two fields: first the list itself
myManager.add(keywordFilterField);
//And the search field, probably you'd want it at top:
myScreen.setTitle(keywordFilterField.getKeywordField());
You'll have to implement a custom sortable collection to hold the items you wan't to display:
class CustomList extends SortedReadableList implements KeywordProvider {
//In constructor, call super constructor with a comparator of <yourClass>
public CustomList(Vector elements)
{
super(new <yourClass>Comparator()); //pass comparator to sort
loadFrom(elements.elements());
}
//Interface implementation
public String[] getKeywords( Object element )
{
if(element instanceof <yourClass> )
{
return StringUtilities.stringToWords(element.toString());
}
return null;
}
void addElement(Object element)
{
doAdd(element);
}
//...
}
You have a full demo available inside the JDE samples folder. It is called keywordfilterdemo.
To use a custom list like the one you posted, you'll probably have to code a lot of stuff, like a custom EditField to type in the keywords receiving events on every typed character, linked to a search on a sortered collection (maybe you could use a SortedReadableList for this) which will select in your ListField the first search result returned by this collection.

Add buttons to a ListField in BlackBerry

I am using a ListField in BlackBerry and want to include a button with two text fields in the row like:
Button
Text1
Text2
But I am not able to add the buttons. All the help I've found is about adding images.
Take a look at How to customize list field in blackberry and Blackberry - how to add fields to listfield
by default ... list field provides the focus on a single row as a whole....and not to the single field on a row(as u told that u want to add three fields....buttons, textfield, textfield).
so i want to know why do u want to add buttons and two separate text-fields in a single row... I think its not easy if u want to get focus only on button OR only on a text-field....in a single row of a list field.
by the way... here is the sample code........ how u create three fields in a single row of list field...
just call the constructor of this list-field class in ur main screen's class and add it like.....
DetailListField _listField = new DetailListField();
add(_listField);
DetailListField class -
class DetailListField extends ListField implements ListFieldCallback
{
private Vector rows;
private Font font;
public DetailListField()
{
this(0, ListField.USE_ALL_WIDTH | DrawStyle.LEFT);
}
public DetailListField(int numRows, long style)
{
super(0, style);
try
{
rows = new Vector();
font = Font.getDefault().derive(Font.PLAIN, 7, Ui.UNITS_pt);
setRowHeight(-2);
setCallback(this);
for (int x = 0 ; x < 5 ; x++)
{
TableRowManager row = new TableRowManager();
// button, textfield, textfield
ButtonField _btn = new ButtonField("Button", ButtonField.CONSUME_CLICK);
_btn.setBorder(VISUAL_STATE_NORMAL, BorderFactory.createSimpleBorder(new XYEdges(1,1,1,1),
new XYEdges(0x557788, 0xAA22BB, 0x557788, 0xAA22BB),
Border.STYLE_SOLID));
row.add(_btn);
BasicEditField _basicEdit1 = new BasicEditField(BasicEditField.EDITABLE | BasicEditField.FILTER_DEFAULT);
_basicEdit1.setBorder(VISUAL_STATE_NORMAL, BorderFactory.createSimpleBorder(new XYEdges(2,2,2,2),
new XYEdges(0x557788, 0xAA22BB, 0x557788, 0xAA22BB),
Border.STYLE_SOLID));
row.add(_basicEdit1);
BasicEditField _basicEdit2 = new BasicEditField(BasicEditField.EDITABLE | BasicEditField.FILTER_DEFAULT);
_basicEdit2.setBorder(VISUAL_STATE_NORMAL, BorderFactory.createSimpleBorder(new XYEdges(2,2,2,2),
new XYEdges(0x994422, 0xAA22BB, 0x994422, 0xAA22BB),
Border.STYLE_SOLID));
row.add(_basicEdit2);
// add id to the vector.
rows.addElement(row); // returnData[x][0]);
// call draw list row
// then call constructor of manager class
}
setSize(rows.size());
invalidate();
} catch(Exception e) {
}
}
public void drawListRow(ListField list, Graphics g, int index, int y, int width)
{
try
{
DetailListField dl = (DetailListField)list;
TableRowManager rowManager = (TableRowManager)dl.rows.elementAt(index);
rowManager.drawRow(g, 0, y, width, list.getRowHeight());
} catch(Exception e) {
}
}
protected boolean keyChar(char key, int status, int time)
{
if (key == Characters.ENTER)
{
return true;
// We've consumed the event.
}
else if(key == Characters.ESCAPE)
{
return true;
}
return super.keyChar(key, status, time);
}
protected boolean navigationClick(int status, int time)
{
try
{
// use below method if want to get label value from manager.
final int index = this.getSelectedIndex();
if(index >= 0) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("Selected index number : " + (index + 1));
}
});
}
} catch (final Exception e) {
}
return true;
}
public Object get(ListField listField, int index)
{
// TODO Auto-generated method stub
return rows.elementAt(index);
}
public int getPreferredWidth(ListField listField)
{
// TODO Auto-generated method stub
return 0;
}
public int indexOfList(ListField listField, String prefix, int start)
{
// TODO Auto-generated method stub
return rows.indexOf(prefix, start);
}
/**
* MANAGER CLASS
*/
private class TableRowManager extends Manager
{
int _height = 0, _width = 0;
int yPos = 0;
public TableRowManager()
{
super(0);
}
// Causes the fields within this row manager to be layed out then
// painted.
public void drawRow(Graphics g, int x, int y, int width, int height)
{
try
{
_height = height;
_width = getPreferredWidth();
yPos = y;
// Arrange the cell fields within this row manager.
// set the size and position of each field.
layout(_width, _height);
// Place this row manager within its enclosing list.
setPosition(x, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
} catch(Exception e) {
System.out.println("Exeception : (DetailListField) 4 : " + e.toString());
}
}
// Arranges this manager's controlled fields from left to right within
// the enclosing table's columns.
protected void sublayout(int width, int height)
{
try
{
// set the bitmap field
Field _field0 = getField(0);
layoutChild(_field0, (_width/3) - 30 , _height - 20);
setPositionChild(_field0, 2, 5);
// set the name field
Field _field1 = getField(1);
_field1.setFont(font);
layoutChild(_field1, (_width/3) - 30, _field1.getPreferredHeight());
setPositionChild(_field1, (_width/3) - 30 + 10, 5);
Field _field2 = getField(2);
_field2.setFont(font);
layoutChild(_field2, (_width/3) - 30, _field2.getPreferredHeight());
setPositionChild(_field2, ((_width/3) - 30)*2 + 20, 5);
setExtent(_width, _height);
} catch(Exception e) {
System.out.println("Exeception : (DetailListField) 5 : " + e.toString());
}
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth()
{
return (Display.getWidth());
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight()
{
return _height;
}
}
}
bt still i dont know how to get focus on single field of a single row...
usage:
ListCallBack _callBack = new ListCallBack();
_countries.setCallback(_callBack);
code:
private class ListCallBack implements ListFieldCallback{
public void drawListRow(ListField listField, Graphics graphics,
int index, int y, int width) {
for(int i = 0; i <= 23; i++) {
graphics.drawBitmap(0, y, 48, 48, (Bitmap) MyApp._flagVector.elementAt(index), 0, 0);
}
String text = (String)MyApp._countryVector.elementAt(index);
graphics.drawText(text, 65, y, 0, width);
}
public Object get(ListField listField, int index) {
return MyApp._countryVector.elementAt(index);
}
public int getPreferredWidth(ListField listField) {
return Display.getWidth();
}
public int indexOfList(ListField listField, String prefix, int start) {
return MyApp._countryVector.indexOf(prefix, start);
}
}

Blackberry - get checked items from list with checkboxes

How can all checked items from a list can be fetched?
I need to get all selected (checked) items from the list and populate a vector.
I am not getting all selected items, I am getting only the item on which current focus is.
I am implementing listfield with checkboxes as per the knowledgebase article.
If I use getSelection(), it is returning me the currently highlighted list row index, and not all that have been checked.
As I undestood, sample is How To - Create a ListField with check boxes
Then you can add Vector to the class where ListFieldCallback is implemented:
private Vector _checkedData = new Vector();
public Vector getCheckedItems() {
return _checkedData;
}
and update drawListRow this way:
if (currentRow.isChecked())
{
if( -1 ==_checkedData.indexOf(currentRow))
_checkedData.addElement(currentRow);
rowString.append(Characters.BALLOT_BOX_WITH_CHECK);
}
else
{
if( -1 !=_checkedData.indexOf(currentRow))
_checkedData.removeElement(currentRow);
rowString.append(Characters.BALLOT_BOX);
}
If you would use VerticalFieldManager with custom CheckBoxField, you could iterate over all fields on screen (or any manager) and check if its' checkbox field, then take a value:
class List extends VerticalFieldManager {
...
public Vector getCheckedItems() {
Vector result = new Vector();
for (int i = 0, cnt = getFieldCount(); i < cnt; i++) {
Field field = getField(i);
if (field instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) field;
if (checkboxField.isChecked())
result.addElement(checkboxField);
}
}
return result;
}
}
#sandhya-m
class List extends VerticalFieldManager {
...
public void selectAll() {
for (int i = 0, cnt = getFieldCount(); i < cnt; i++) {
Field field = getField(i);
if (field instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) field;
checkboxField.setChecked(true);
}
}
}
}

Resources