In last post I posted initial implementation for my Audiobook Reader app for Ubuntu-Touch, I was able to add some more features to it then after. I added support for Adding and removing custom bookmark and play the custom bookmark.
I also added support for searching the books by title in book list view. Similar to email application in Nokia N9. In this post I will show how similar feature can be implemented in QML application.
In my implementation if you pull down the book list, then it will show the search box. You can type in that search box and it will try to show books that matches that typed text. If you don't type for some time, search box will gets disappear.
Here is demo,
Following is my code. First I created TextField where user can type search text. If user type some text then I am applying the filter to my list's data model using typed text and also resetting the timer, which is responsible in hiding the search field.
I also added support for searching the books by title in book list view. Similar to email application in Nokia N9. In this post I will show how similar feature can be implemented in QML application.
In my implementation if you pull down the book list, then it will show the search box. You can type in that search box and it will try to show books that matches that typed text. If you don't type for some time, search box will gets disappear.
Here is demo,
Following is my code. First I created TextField where user can type search text. If user type some text then I am applying the filter to my list's data model using typed text and also resetting the timer, which is responsible in hiding the search field.
.... TextField{ id: searchField width: parent.width visible: false onTextChanged: { timer.restart(); if(text.length > 0 ) { model.applyFilter(text); } else { model.reload(); } } onVisibleChanged: { if( visible) focus = true } Behavior on visible { NumberAnimation{ duration: 200 } } }Following is my list view, Here I am setting its y property based on visibility of search field. Data model implements method for showing filtered data or all the data. Other important function is onContentYChanged, this function makes search field visible if user pull down the book list view.
ListView { id:listView clip: true width: parent.width height: parent.height y: searchField.visible ? searchField.height : 0 Behavior on y { NumberAnimation{ duration: 200 } } model: ListModel { id: model Component.onCompleted: { reload(); } function reload() { var bookList = DB.getAllBooks(); model.clear(); for( var i=0; i < bookList.length ; ++i ) { model.append(bookList[i]); } } function applyFilter(bookName) { var bookList = DB.getBooksByName(bookName); model.clear(); for( var i=0; i < bookList.length ; ++i ) { model.append(bookList[i]); } } } delegate: listDelegate onContentYChanged: { if( contentY < -100 ) { searchField.visible = true; timer.running = true; } } }Lastly the timer, which is responsible for hiding the search field if user don't type anything for certain duration.
Timer{ id: timer; running: false; interval: 7000; repeat: false onTriggered: { searchField.visible = false; } }That's all needed to add search support to QML ListView.
Hi,
ReplyDeleteNice article, and nice blog, it's helped me a lot with QML.
Just one question, do you know if this could be done with a WebView ?
Eg, to find text on a page ?
Regards.
You mean searching the text and putting search box with WebView ? I think same UI logic can be used with WebView. For searching text should also be easy once you get hold of its html content.
DeleteCool article, the getBooksByName function is looking for the passed string in every entry right ...
ReplyDeleteCould you give the implementation of getBooksByName and getAllBooks ?
DeleteCan this method use on listmodel ?.Can you please provide some example.I can't see how the code works cause your listview get data from database while my app get data from listmodel and foldermodel.
ReplyDeletehow to work on list item component
ReplyDeletecan u please tell me how to implement on json data
this is my JSON data
ReplyDelete{
"atm_locations": [
{
"id": 1234,
"name": "HDFC bank ATM",
"address": "Gachbowli, Hyderabad",
"latitude": "17.434656800000000000",
"longitude": "78.363600700000000000"
},
{
"id": 5821,
"name": "ICICI Bank ATM",
"address": "Hitech City, Hyderabad",
"latitude": "17.434656800000000000",
"longitude": "78.363600700000000000"
},
{
"id": 6325,
"name": "SBI Bank ATM",
"address": "Kondapur, Hyderabad",
"latitude": "17.434656800000000000",
"longitude": "78.363600700000000000"
},
{
"id": 2458,
"name": "HDFC bank ATM",
"address": "DLF, Gachibowli, Hyderabad",
"latitude": "17.434656800000000000",
"longitude": "78.363600700000000000"
}
]
}
my qml page
ReplyDeleteContainer {
Container {
preferredHeight: 650.0
ListView {
id: locationlistview
dataModel: locationModel
listItemComponents: [
ListItemComponent {
type: ""
Container {
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
Container {
layout: StackLayout {
}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
translationY: 20.0
Label {
text: ListItemData.name
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
textStyle.color: Color.create("#f74848")
translationX: 20.0
textStyle.fontSize: FontSize.Small
}
Label {
text: ListItemData.address
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
textStyle.color: Color.create("#727272")
textStyle.fontSize: FontSize.XXSmall
translationX: 20.0
translationY: -20.0
}
Divider {
translationY: -20.0
}
}
}
}
]
onTriggered: {
locationlistview.clearSelection();
locationlistview.toggleSelection(indexPath);
console.log("the indexpath===" + indexPath)
}
attachedObjects: [
// Definition of the second Page, used to dynamically create the Page above.
ArrayDataModel {
id: locationModel
},
DataSource {
id: dataSource
source: "asset:///model/atmLocations.json"
onDataLoaded: {
for (var i = 0; i < data.atm_locations.length; i ++) {
locationModel .append(data.atm_locations[i]);}
}
}
]
}
}
TextField {
id: search
preferredWidth: 650.0
horizontalAlignment: HorizontalAlignment.Center
hintText: "enter bank name"
onTextChanged: {
//todo search techinque
}
}
onCreationCompleted: {
dataSource.load();
}
}
now i have to search in array please give solution
same designing can u tell me in html5
ReplyDeleteam doing a audio player for ubuntu desktop and want put searchbox over playlist but am not using listmodel am using foldermodel to get list of Audio files help me implimenting it . i tried to do it but i dont know whats wrong happening with it my project is herre http://launchpad.net/kmusicplay thanks
ReplyDeleteHi, I checked your code, I did not seen code for search box or filtering. But I have following suggestion. You can use code similar to this post, in applyFilter function of Model, you will need to manipulate the filter applied to FolderListModel (nameFilters: [ "*.mp3" ]), here in case of search, you need to make filter to show file and folder names matching to searched text.
DeleteThis comment has been removed by the author.
Deletecan you implement the same search function having FolderModelList as listview model ???
ReplyDeleteimport QtQuick 2.3
ReplyDeleteimport QtQuick.Controls 1.2
import Qt.labs.folderlistmodel 2.1
Item {
width: 300
height: 300
FolderListModel
{
id: folderListModel
}
function updateFilter()
{
var text = filterField.text
var filter = "*"
for(var i = 0; i<text.length; i++)
if(!caseSensitiveCheckbox.checked)
filter+= "[%1%2]".arg(text[i].toUpperCase()).arg(text[i].toLowerCase())
else
filter+= text[i]
filter+="*"
print(filter)
folderListModel.nameFilters = [filter]
}
Row
{
spacing: 5
Text {text:"Filter"}
TextField
{
id: filterField
onTextChanged: updateFilter()
}
Text {text:"Case Sensitive"}
CheckBox
{
id: caseSensitiveCheckbox
checked: false
onCheckedChanged:updateFilter()
}
}
ListView
{
anchors.fill: parent
anchors.topMargin: 30
model:folderListModel
delegate: Text{text: model.fileName}
}
}
could you send mı full code?
ReplyDeleteme*
Delete