Telerik RadPageview Right-to-Left Layout Arrow Keys - telerik

I have a RadPageview in Strip Mode and I want my program to had support a right-to-left language. When I changing the Right-to-Left Property to true it works fine. but when I run my program and use Arrow Keys (Left or Right) it doesn't work correctly. Left key goes to Right and Right key goes to Left. How can I fix it?

Telerik answered my question:
http://www.telerik.com/forums/right-to-left-arrow-keys-problem
the possible solution that I can suggest is to create a custom RadPageViewStripElement and override its IsNextKey and IsPreviousKey methods on a way to reverse the previous/next navigation as follows:
public class CustomPageView : RadPageView
{
public override string ThemeClassName
{
get
{
return typeof(RadPageView).FullName;
}
}
protected override RadPageViewElement CreateUI()
{
switch (this.ViewMode)
{
case PageViewMode.Strip:
return new CustomRadPageViewStripElement();
default:
return base.CreateUI();
}
}
}
public class CustomRadPageViewStripElement : RadPageViewStripElement
{
public CustomRadPageViewStripElement()
{
}
protected override Type ThemeEffectiveType
{
get
{
return typeof(RadPageViewStripElement);
}
}
protected override bool IsNextKey(Keys key)
{
if (this.RightToLeft)
{
if (key == Keys.Left)
{
return true;
}
else
{
return false;
}
}
return base.IsNextKey(key);
}
protected override bool IsPreviousKey(Keys key)
{
if (this.RightToLeft)
{
if (key == Keys.Right)
{
return true;
}
else
{
return false;
}
}
return base.IsPreviousKey(key);
}
}

I fix it programmatically by using ProcessCmdKey of form.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Right))
{
int x = radPageView1.Pages.IndexOf(this.radPageView1.SelectedPage) - 1;
if (x < 0)
x = radPageView1.Pages.Count() - 1;
else if (x >= radPageView1.Pages.Count())
x = 0;
radPageView1.SelectedPage = radPageView1.Pages[x];
return true;
}
else if(keyData == Keys.Left)
{
int x = radPageView1.Pages.IndexOf(this.radPageView1.SelectedPage) + 1;
if (x <= 0)
x = radPageView1.Pages.Count() - 1;
else if (x >= radPageView1.Pages.Count())
x = 0;
radPageView1.SelectedPage = radPageView1.Pages[x];
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}

Related

How to prevent user pressing multiple keys Javafx?

I have a player that can move when pressing the arrow keys. I would like to prevent the user to press multiple arrows at the same time.
This what I have tried:
boolean[] pressedKeys = new boolean[4];
canvas.setOnKeyPressed(event -> {
if (!Arrays.asList(pressedKeys).contains(true)){
if (event.getCode() == KeyCode.UP){
pressedKeys[0] = true;
} else if (event.getCode() == KeyCode.RIGHT){
pressedKeys[1] = true;
} else if (event.getCode() == KeyCode.DOWN){
pressedKeys[2] = true;
} else if (event.getCode() == KeyCode.LEFT){
pressedKeys[3] = true;
}
}
});
canvas.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.UP){
pressedKeys[0] = false;
} else if (event.getCode() == KeyCode.RIGHT){
pressedKeys[1] = false;
} else if (event.getCode() == KeyCode.DOWN){
pressedKeys[2] = false;
} else if (event.getCode() == KeyCode.LEFT){
pressedKeys[3] = false;
}
});
But it does not work, here I can still press the right and the up arrows for example.
Thanks for any help
I'd create an event handler implementation like this:
class InputHandler implements EventHandler<KeyEvent> {
final private Set<KeyCode> activeKeys = new HashSet<>();
#Override
public void handle(KeyEvent event) {
if (activeKeys.isEmpty() && KeyEvent.KEY_PRESSED.equals(event.getEventType())) {
activeKeys.add(event.getCode());
} else if (KeyEvent.KEY_RELEASED.equals(event.getEventType())) {
activeKeys.remove(event.getCode());
}
}
public Set<KeyCode> getActiveKeys() {
return Collections.unmodifiableSet(activeKeys);
}
}
The check activeKeys.isEmpty() ensures that we don't register a new keypress until a prior key is released.
A single value for the activeKey could be used instead of the activeKeys HashSet, I just adapted this from a prior solution which works in a more general case.
To use it:
InputHandler inputHandler = new InputHandler();
scene.setOnKeyPressed(inputHandler);
scene.setOnKeyReleased(inputHandler);
Then, if it is something like a game where the input is checked on each frame update of an AnimationTimer, in the update method you can check the current active keys for the frame and action them, like this:
private AnimationTimer createGameLoop() {
return new AnimationTimer() {
public void handle(long now) {
update(now, inputHandler.getActiveKeys());
if (isGameOver()) {
this.stop();
}
}
};
I am not sure if your chosen strategy will result in a desirable user experience, you will need to try it out and see how well it works in your application.
I found a solution, thanks to #kleopatra
This is what I made:
boolean pressedKeys = false, releasedKeys = true;
canvas.setOnKeyPressed(event -> {
if (releasedKeys){
// Code goes here
pressedKeys = true;
releasedKeys = false;
}
});
canvas.setOnKeyReleased(event -> {
if (pressedKeys){
pressedKeys = false;
releasedKeys = true;
}
});
Like this, its not possible to press multiple keys at one time

How to implement TabLayout.IOnTabSelectedListener.OnTabUnselected with TabbedPage.ToolbarPlacement="Bottom" - Xamarin Forms?

I just recently used android:TabbedPage.ToolbarPlacement="Bottom". I used to have the following code:
void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
{
var playPage = Element.CurrentPage as NavigationPage;
if (!(playPage.RootPage is PhrasesFrame))
return;
var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
var playTab = tabLayout.GetTabAt(4);
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
Anyone knows how can I implement this with ToolbarPlacement="Bottom" ? I have implemented both BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener but can't find any reference for UnselectedTab if there is any.
Edit:
Previous custom renderer using the default tab position and implementing TabLayout:
namespace Japanese.Droid
{
public class MyTabbedPageRenderer: TabbedPageRenderer, TabLayout.IOnTabSelectedListener
{
ViewPager viewPager;
TabLayout tabLayout;
bool setup;
public MyTabbedPageRenderer(Context context): base(context){ }
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// More codes here
}
void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
{
UpdateTab(tab);
}
void TabLayout.IOnTabSelectedListener.OnTabSelected(TabLayout.Tab tab)
{
UpdateTab(tab);
}
void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
{
var playPage = Element.CurrentPage as NavigationPage;
if (!(playPage.RootPage is PhrasesFrame))
return;
var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
var playTab = tabLayout.GetTabAt(4);
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
void UpdateTab(TabLayout.Tab tab)
{
// To have the logic only on he tab on position 1
if (tab == null || tab.Position != 4)
{
return;
}
if (tab.Text == "Play")
{
tab.SetText("Pause");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
}
else
{
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
}
}
}
Current custom renderer using the ToolbarPlacement="Bottom":
namespace Japanese.Droid
{
public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
{
public BottomTabPageRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
// More codes here
}
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
UpdateTab(item)
}
void BottomNavigationView.IOnNavigationItemReselectedListener.OnNavigationItemReselected(IMenuItem item)
{
UpdateTab(item);
}
void UpdateTab(IMenuItem item)
{
var playTabId = 4;
var title = item.TitleFormatted.ToString();
if (item == null || item.ItemId != playTabId)
{
return;
}
if (item.ItemId == playTabId)
{
if (title == "Play")
{
item.SetTitle("Pause");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
}
else
{
item.SetTitle("Play");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
}
}
}
}
So now my problem is I don't have any idea how will I implement the TabLayout.IOnTabSelectedListener.OnTabUnselected in the new custom renderer.
There is no official stuff for OnTabReselected event for TabbedPage's bottom navigation or
BottomNavigationView because It doesn't use TabLayout.Tab for a start. Many overridden methods of TabbedPageRenderer not being called like SetTabIcon. If you are using IOnTabSelectedListener interface(As your first part of code) you have three methods to use.
void OnTabReselected(Tab tab);
void OnTabSelected(Tab tab);
void OnTabUnselected(Tab tab);
But when it comes to BottomNavigationView interface you have only two methods
void OnNavigationItemReselected
bool OnNavigationItemSelected
So we don't have built in OnTabUnselected method. Here you need to write custom code to make unseleted event.
I have tried this code without using custom renderer using 4 tabs pages & the xaml of tabbed written in MailPage.xaml file. First declare List<string> in App.xaml.cs file to store Title of all tabs
public static List<string> Titles {get;set;}
Add tabs pages title in above list from MainPage.xaml.cs file's OnAppearing method
protected override void OnAppearing()
{
for (int i = 0; i < this.Children.Count; i++)
{
App.Titles.Add(this.Children[i].Title);
}
}
Now go to your MyTabbedPage class in which is available in shared project.
public class MyTabbedPage : Xamarin.Forms.TabbedPage
{
string selectedTab = string.Empty;
string unSelectedTab = string.Empty;
bool isValid;
public MyTabbedPage()
{
On<Xamarin.Forms.PlatformConfiguration.Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
this.CurrentPageChanged += delegate
{
unSelectedTab = selectedTab;
selectedTab = CurrentPage.Title;
if (App.Titles != null)
isValid = true;
else
App.Titles = new List<string>();
if (isValid)
{
MoveTitles(selectedTab);
//Pass 0 index for tab selected & 1 for tab unselected
var unSelecteTabTitle = App.Titles[1];
//TabEvents(1); here you know which tab unseleted call any method
}
};
}
//This method is for to moving selected title on top of App.Titles list & unseleted tab title automatic shifts at index 1
void MoveTitles(string selected)
{
var holdTitles = App.Titles;
if (holdTitles.Count > 0)
{
int indexSel = holdTitles.FindIndex(x => x.StartsWith(selected));
holdTitles.RemoveAt(indexSel);
holdTitles.Insert(0, selected);
}
App.Titles = holdTitles;
}
}
Or you can make swith case like this
void TabEvents(int index)
{
switch (index)
{
case 0:
//Tab selected
break;
case 1:
//Tab unselected
break;
}
}
Few things I should mention that MainPage.xaml.cs file inheriting MyTabbedPage
public partial class MainPage : MyTabbedPage
Structure of MainPage.xaml file
<?xml version="1.0" encoding="utf-8" ?>
<local:MyTabbedPage
<TabbedPage.Children>
<NavigationPage Title="Browse">
</NavigationPage>
</TabbedPage.Children>
</local:MyTabbedPage>
Answer seems long but hope it help you.
As per G.Hakim's suggestion, I was able to do what I wanted to do by capturing the tab item I wanted to work on and do the necessary actions in BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected.
namespace Japanese.Droid
{
public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
{
// same as above
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
if(item.ItemId == 4 && item.TitleFormatted.ToString() == "Play")
{
item.SetTitle("Pause");
item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
App.pauseCard = false;
playTab = item;
}
if(item.ItemId !=4 && playTab.TitleFormatted.ToString() == "Pause")
{
playTab.SetTitle("Play");
playTab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
App.pauseCard = true;
}
return true;
}
// same as above
}
}

Sort array of objects based on property in typescript

I'm showing an array with items of type 'request' in a table. I want to sort the columns of the table so I planned to make a click method for every column header. This methods sorts the array based on the value of the property shown in that column.
public sortProduct(): void {
this.requests.sort((a, b) => {
if (a.productName < b.productName)
return -1;
if (a.productName > b.productName)
return 1;
return 0;
});
if (!this.productSortOrder) {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
This works, but now I need to make a method for every column. I am looking for a way to call a sort method like this:
this.requests.sortMethod(property, order);
This method would then sort the requests array based on the property of the objects in the array and in the given sortorder.
How can I do that? I guess I'm looking for something like Func<> in C#.
You can us a function signature for a similar effect to Func
sortProduct<T>(prop: (c: Product) => T, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (prop(a) < prop(b))
return -1;
if (prop(a) > prop(b))
return 1;
return 0;
});
if (order === "DESC") {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
// Usage
sortProduct(p=> p.productName, "ASC");
Or you can use the property name instead (keyof Product will ensure the string must be a property of Product):
sortProduct<T>(propName: keyof Product, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (a[propName] < b[propName])
return -1;
if (a[propName] > b[propName])
return 1;
return 0;
});
...
}
// Usage
sortProduct("productName", "ASC");
sortProduct("productName_", "ASC"); // Error
You can use a SortUtil class with a static template method sortByProperty:
export class SortUtil {
static sortByProperty<T>(array: T[], propName: keyof T, order: 'ASC' | 'DESC'): void {
array.sort((a, b) => {
if (a[propName] < b[propName]) {
return -1;
}
if (a[propName] > b[propName]) {
return 1;
}
return 0;
});
if (order === 'DESC') {
array.reverse();
}
}
}

Click an Item -hold- and swipe to an other site

If an object is clicked, the next page should not be called immediately. But the click should remain on the object until you scroll through a wipe to the next page.
How can it hold the click command on an Item?
How can it swipe from the clicked Item to an other Page?
Update
Click one item > OnHold> swipe from the holded item to the left and right.
This is the actual behavior:
private int index = -1;
break;
}
return true;
}
}
To highlight the item when it is clicked, you can set background color to the item's view, to perform a swipe gesture for each item, I think you will need to implement IOnTouchListener for each item. Here I created an adapter to implement this feature:
public class LVAdapter : BaseAdapter<ListItemModel>, View.IOnTouchListener
{
private List<ListItemModel> items = new List<ListItemModel>();
private Activity context;
private int index = -1;
public enum SwipeAction
{
LR, // Left to Right
RL, // Right to Left
TB, // Top to bottom
BT, // Bottom to Top
None // when no action was detected
}
private int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
private SwipeAction maction = SwipeAction.None;
public LVAdapter(Activity context, List<ListItemModel> items) : base()
{
this.context = context;
this.items = items;
}
public override ListItemModel this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
private void SetSelectedItem(int position)
{
index = position;
NotifyDataSetChanged();
}
private class MyViewHolder : Java.Lang.Object
{
public TextView Name { get; set; }
public TextView Description { get; set; }
public int index { get; set; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
MyViewHolder holder = null;
var view = convertView;
if (view != null)
holder = view.Tag as MyViewHolder;
if (holder == null)
{
holder = new MyViewHolder();
view = context.LayoutInflater.Inflate(Resource.Layout.ItemCell, null);
holder.Name = view.FindViewById<TextView>(Resource.Id.nametxt);
holder.Description = view.FindViewById<TextView>(Resource.Id.detailtxt);
holder.index = position;
view.Tag = holder;
}
holder.Name.Text = items[position].Name;
holder.Description.Text = items[position].Description;
if (index != -1 && position == index)
{
holder.Name.SetBackgroundColor(Android.Graphics.Color.Red);
holder.Description.SetBackgroundColor(Android.Graphics.Color.Pink);
}
else
{
holder.Name.SetBackgroundColor(Android.Graphics.Color.RoyalBlue);
holder.Description.SetBackgroundColor(Android.Graphics.Color.SeaGreen);
}
view.SetOnTouchListener(this);
return view;
}
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
downX = e.GetX();
downY = e.GetY();
maction = SwipeAction.None;
break;
case MotionEventActions.Move:
upX = e.GetX();
upY = e.GetY();
var deltaX = downX - upX;
var deltaY = downY - upY;
if (Math.Abs(deltaX) > MIN_DISTANCE)
{
if (deltaX < 0)
{
maction = SwipeAction.LR;
}
else if (deltaX > 0)
{
maction = SwipeAction.RL;
}
return true;
}
else if (Math.Abs(deltaY) > MIN_DISTANCE)
{
if (deltaY < 0)
{
maction = SwipeAction.TB;
}
else if (deltaY > 0)
{
maction = SwipeAction.BT;
}
return false;
}
break;
case MotionEventActions.Up:
var holder = v.Tag as MyViewHolder;
if (maction == SwipeAction.None)
{
SetSelectedItem(holder.index);
}
else if (maction == SwipeAction.LR | maction == SwipeAction.RL)
{
if (holder.index == index)
context.StartActivity(typeof(Activity1));
}
break;
}
return true;
}
}
The ListItemModel is quite simple by my side:
public class ListItemModel
{
public string Name { get; set; }
public string Description { get; set; }
}
You can try to modify the model and holder as you need.

Gwt CellTable Sorting page by page only

GWT CellTable column sorting page by page only, for each page i have to click the column header
for sorting.
How to sort whole data on single header click.
This is my code,
dataProvider = new ListDataProvider<List<NamePair>>();
dataProvider.addDataDisplay(dgrid);
List<List<NamePair>> list = dataProvider.getList();
for (List<NamePair> contact : test) {
dataProvider.setList(test);
list.add(contact);
}
ListHandler<List<NamePair>> columnSortHandler = new ListHandler<List<NamePair>>(dataProvider.getList());
System.out.println("Column count->"+dgrid.getColumnCount());
for(int j=0 ; j<dgrid.getColumnCount();j++){
final int val = j;
columnSortHandler.setComparator(dgrid.getColumn(val), new Comparator<List<NamePair>>() {
public int compare(List<NamePair> o1, List<NamePair> o2) {
if (o1 == o2) {
return 0;
}
// Compare the column.
if (o1 != null) {
int index = val;
return (o2 != null) ? o1.get(index-2).compareTo(o2.get(index-2)) : 1;
}
return -1;
}
});
}
dgrid.addColumnSortHandler(columnSortHandler);
I suggest you override ListHandler , override and call super.onColumnSort(ColumnSortEvent) to debug the onColumnSort(ColumnSortEvent) method, you'll understand what is happening very fast.
The source code of the method is pretty direct
public void onColumnSort(ColumnSortEvent event) {
// Get the sorted column.
Column<?, ?> column = event.getColumn();
if (column == null) {
return;
}
// Get the comparator.
final Comparator<T> comparator = comparators.get(column);
if (comparator == null) {
return;
}
// Sort using the comparator.
if (event.isSortAscending()) {
Collections.sort(list, comparator);
} else {
Collections.sort(list, new Comparator<T>() {
public int compare(T o1, T o2) {
return -comparator.compare(o1, o2);
}
});
}
}

Resources