How do I represent an Object Array in XML with data binding? - android-databinding

With data binding, I am trying to connect my member variable Tile[] tiles which resides in Model model to the TextViews in my XML file. However, I am getting the following gradle error:
Error:(106, 33) Identifiers must have user defined types from the XML file. tiles is missing it
This is (part of) my XML:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="(Tile[]) tiles"
type="com.myapp.Model" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv0"
android:layout_width="100dp"
android:layout_height="100dp"
android:text='#{tiles[0].getValue == 0 ? "" : tiles[0].getValue}'
android:textSize='#{tiles[0].getValue < 100 ? "48sp" : tiles[0].getValue < 1000 ? "36sp" : "24sp"}'/>
<TextView
android:id="#+id/tv1"
android:layout_width="100dp"
android:layout_height="100dp"
android:text='#{tiles[1].getValue == 0 ? "" : tiles[1].getValue}'
android:textSize='#{tiles[1].getValue < 100 ? "48sp" : tiles[1].getValue < 1000 ? "36sp" : "24sp"}'/>
...
</RelativeLayout>
</layout>
This is (part of) my Model class:
class Model {
private Tile[] tiles = new Tile[16];
Model(Tile[] tiles) {
setTiles(tiles);
}
Tile[] getTiles(){ return tiles;}
void setTiles(Tile[] tiles) { System.arraycopy(tiles, 0, this.tiles, 0, tiles.length); }
int getValue(int index) { return tiles[index].getValue(); }
void setValue(int index, int value) { tiles[index].setValue(value); }
int getId(int index) { return tiles[index].getId(); }
void setId(int index, int id) { tiles[index].setId(id);}
}
And this is (part of) my Tile class:
class Tile {
private int value;
private int id;
Tile(int id, int value) {
this.id = id;
this.value = value;
}
int getValue() {
return value;
}
void setValue(int value) {
this.value = value;
}
int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
}
Most likely, this line is wrong: type="com.myapp.Model", since the type of my tiles variable is not Model, but the compiler/gradle does not let me put com.myapp.Tile nor com.myapp.Tile[] nor com.myapp.Model.Tile[]. How do I correctly declare my Tile[] variable?

Try with this in your xml :
<variable
name="tiles"
type="com.<your package>.Tile[]"/> //it might show you an error in xml but you can ignore it.
and set its value from activity/fragment/viewmodel
binding.setTiles(<your array>);
Make sure your Tile class and its variable are public.
public class Tile {
public int value;
public int id;
.
.
.
}

Related

if statement doesn't check the values of the edittexts reached by scrolling the recyclerview

i have a recyclerview the has an edittext in each row. the user can change the value of the edittext as he wishes but it should not be left empty for the values will be saved in a database. for this i'm trying to check if the edittext is empty. if any row has an empty edittext, the user is given a message when he wants to save that there is an empty value. this is the code that i wrote:
public class recyclerview_viewholder : RecyclerView.ViewHolder
{
public TextView rownbr, itemname;
public EditText qty;
public TextView unit;
public LinearLayout linearLayout;
public recyclerview_viewholder(View itemView, Action<int> listener)
: base(itemView)
{
rownbr = itemView.FindViewById<TextView>(Resource.Id.rownbr);
itemname = itemView.FindViewById<TextView>(Resource.Id.laborname);
unit = itemView.FindViewById<TextView>(Resource.Id.days);
qty = itemView.FindViewById<EditText>(Resource.Id.overtime);
linearLayout = itemView.FindViewById<LinearLayout>(Resource.Id.linearLayout);
itemView.Click += (sender, e) => listener(base.LayoutPosition);
}
}
public class recyclerviewAdapter : RecyclerView.Adapter
{
// Event handler for item clicks:
public event EventHandler<int> ItemClick;
DataTable summary_Requests = new DataTable();
//Context context;
public readonly new_request_items context;
int selected_pos = -1;
private SwipeToDeleteCallback swipeToDeleteCallback;
List<list_item> item_details = new List<list_item>();
public recyclerviewAdapter(new_request_items context, DataTable sum_req, List<list_item> item_details)
{
this.context = context;
summary_Requests = sum_req;
this.item_details = item_details;
}
public recyclerviewAdapter(DataTable sum_req, SwipeToDeleteCallback swipeToDeleteCallback)
{
this.swipeToDeleteCallback = swipeToDeleteCallback;
summary_Requests = sum_req;
}
public override RecyclerView.ViewHolder
OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.recycler_view_request_new_data, parent, false);
recyclerview_viewholder vh = new recyclerview_viewholder(itemView, OnClick);
vh.qty.TextChanged += (sender, e) =>
{
if (vh.qty.Text != "")
try
{
int position = vh.LayoutPosition;
summary_Requests.Rows[position]["itemQty"] = Convert.ToDecimal(vh.qty.Text);
user.zero_val = "Not_exist";
}
catch (System.FormatException exp)
{
var icon = AppCompatResources.GetDrawable(context.Context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("qty can be decimal", icon);
user.zero_val = "exits";
}
else if (vh.qty.Text == "")
{
var icon = AppCompatResources.GetDrawable(context.Context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("value can not be empty", icon);
user.zero_val = "exits";
}
};
vh.ItemView.LongClick += (sender, e) =>
{
int position = vh.AdapterPosition;
string itemcode = summary_Requests.Rows[position]["itemcode"].ToString();
list_item result = item_details.Find(list_item => list_item.item_code == itemcode);
Bundle bundle = new Bundle();
bundle.PutString("result", JsonConvert.SerializeObject(result));
items_info iteminf = new items_info();
iteminf.Arguments = bundle;
iteminf.Cancelable = true;
var SupportFragmentManager = this.context.FragmentManager;
iteminf.Show(SupportFragmentManager, "dialog");
selected_pos = position;
NotifyDataSetChanged();
//fill global variables that need to be passed to detail fragment
};
return vh;
}
public override void
OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
recyclerview_viewholder vh = holder as recyclerview_viewholder;
vh.rownbr.Text = summary_Requests.Rows[position]["rowNumber"].ToString();
vh.itemname.Text = summary_Requests.Rows[position]["name"].ToString();
vh.unit.Text = summary_Requests.Rows[position]["itemsunitcode"].ToString();
vh.qty.Text= summary_Requests.Rows[position]["itemQty"].ToString();
if (selected_pos == position)
vh.ItemView.SetBackgroundColor(Color.ParseColor("#4fa5d5"));
else
vh.ItemView.SetBackgroundColor(Color.LightGray);
}
public void RemoveItem(int position)
{
if (laborers_dt_total.Rows.Count != 0)
{
if (position < laborers_dt_total.Rows.Count && position > -1)
{
laborers_dt_total.Rows.RemoveAt(position);
}
else
{
Toast.MakeText(context.Context, "select an item to delete", ToastLength.Long).Show();
}
}
else if (laborers_dt_total.Rows.Count == 0)
{
Toast.MakeText(context.Context, "no items to delete", ToastLength.Long).Show();
}
for (int i = 0; i < laborers_dt_total.Rows.Count; i++)
{
laborers_dt_total.Rows[i]["rowNumber"] = (i + 1).ToString();
NotifyDataSetChanged();
}
}
public DataTable get_dt_final()
{
DataTable final_dt = summary_Requests.Copy();
return final_dt;
}
public override int ItemCount
{
get { return summary_Requests.Rows.Count; }
}
// Raise an event when the item-click takes place:
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
// user.req_pos = position;
}
}
now it works well when there are only few rows in the recyclerview, but when there are many in which i have to scroll through it, if i keep an edittext empty in a row reached by scrolling, the user.zero_val doesn't take the value of exits to tell me that an edittext is empty. what should i do in this case? where do i check for empty edittext? thanks in advance.
this is a simple code i wrote with hopes it would illustrate my problem:
this is the axml of the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="255sp"
android:id="#+id/recyclerView1" />
<Button
android:text="Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/button1" />
</LinearLayout>
this is the layout of each row of the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/light_grey"
android:padding="1dp"
android:layout_marginTop="0.5dp"
android:weightSum="8"
android:gravity="center"
android:id="#+id/linearLayout"
>
<TextView
android:text=""
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="2"
android:id="#+id/rownbr"
android:background="#drawable/back"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:textSize="12dp"
android:gravity="center"
android:textColor="#000000"
/>
<TextView
android:text=""
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="4"
android:id="#+id/laborname"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:textSize="12dp"
android:gravity="center"
android:textColor="#000000"
android:background="#drawable/back"
android:layout_marginLeft="2dp"/>
<TextView
android:text=""
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:id="#+id/days"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:textSize="12dp"
android:textColor="#000000"
android:layout_marginLeft="2dp"
android:gravity="center"
android:background="#drawable/back"/>
<EditText
android:text=""
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:id="#+id/overtime"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:textSize="12dp"
android:textColor="#000000"
android:layout_marginLeft="2dp"
android:gravity="center"
android:background="#drawable/back"/>
</LinearLayout>
this is the back.xml drawable:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#android:color/white" />
<stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
this is the activity where the recyclerview is populated and managed:
public class MainActivity : AppCompatActivity
{
RecyclerView mRecyclerView;
DataTable dt = new DataTable();
RecyclerView.LayoutManager mLayoutManager;
recyclerviewAdapter RecyclerviewAdapter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
dt.Columns.Add("rowNumber");
dt.Columns.Add("name");
dt.Columns.Add("itemsunitcode");
dt.Columns.Add("itemQty");
dt.Rows.Add("1", "rana hd", "pcs", "1");
dt.Rows.Add("2", "rana hd1", "pcs", "1");
dt.Rows.Add("3", "rana hd2", "pcs", "1");
dt.Rows.Add("4", "rana hd3", "pcs", "1");
dt.Rows.Add("5", "rana hd4", "pcs", "1");
dt.Rows.Add("6", "rana hd5", "pcs", "1");
dt.Rows.Add("7", "rana hd6", "pcs", "1");
dt.Rows.Add("8", "rana hd7", "pcs", "1");
dt.Rows.Add("9", "rana hd8", "pcs", "1");
dt.Rows.Add("10", "rana hd9", "pcs", "1");
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView1);
Button btn= FindViewById<Button>(Resource.Id.button1);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.HasFixedSize = true;
mRecyclerView.SetLayoutManager(mLayoutManager);
RecyclerviewAdapter = new recyclerviewAdapter(this, dt);
mRecyclerView.SetAdapter(RecyclerviewAdapter);
btn.Click += delegate
{
if (user.zero_val == "exits")
Toast.MakeText(this, "exists", ToastLength.Long).Show();
if (user.zero_val == "Not_exist")
Toast.MakeText(this, "Not_exist", ToastLength.Long).Show();
};
}
public class recyclerview_viewholder : RecyclerView.ViewHolder
{
public TextView rownbr, itemname;
public EditText qty;
public TextView unit;
public LinearLayout linearLayout;
public recyclerview_viewholder(View itemView, Action<int> listener)
: base(itemView)
{
rownbr = itemView.FindViewById<TextView>(Resource.Id.rownbr);
itemname = itemView.FindViewById<TextView>(Resource.Id.laborname);
unit = itemView.FindViewById<TextView>(Resource.Id.days);
qty = itemView.FindViewById<EditText>(Resource.Id.overtime);
linearLayout = itemView.FindViewById<LinearLayout>(Resource.Id.linearLayout);
itemView.Click += (sender, e) => listener(base.LayoutPosition);
}
}
public class recyclerviewAdapter : RecyclerView.Adapter
{
// Event handler for item clicks:
public event EventHandler<int> ItemClick;
DataTable summary_Requests = new DataTable();
//Context context;
public readonly MainActivity context;
int selected_pos = -1;
public recyclerviewAdapter(MainActivity context, DataTable sum_req)
{
this.context = context;
summary_Requests = sum_req;
}
public override RecyclerView.ViewHolder
OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.recyclerview_data, parent, false);
recyclerview_viewholder vh = new recyclerview_viewholder(itemView, OnClick);
vh.qty.TextChanged += (sender, e) =>
{
if (vh.qty.Text != "")
try
{
int position = vh.LayoutPosition;
summary_Requests.Rows[position]["itemQty"] = Convert.ToDecimal(vh.qty.Text);
user.zero_val = "Not_exist";
}
catch (System.FormatException exp)
{
var icon = AppCompatResources.GetDrawable(context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("qty can be decimal", icon);
user.zero_val = "exits";
}
else if (vh.qty.Text == "")
{
var icon = AppCompatResources.GetDrawable(context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("value can not be empty", icon);
user.zero_val = "exits";
}
};
vh.ItemView.LongClick += (sender, e) =>
{
int position = vh.AdapterPosition;
selected_pos = position;
NotifyDataSetChanged();
};
return vh;
}
public override void
OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
recyclerview_viewholder vh = holder as recyclerview_viewholder;
vh.rownbr.Text = summary_Requests.Rows[position]["rowNumber"].ToString();
vh.itemname.Text = summary_Requests.Rows[position]["name"].ToString();
vh.unit.Text = summary_Requests.Rows[position]["itemsunitcode"].ToString();
vh.qty.Text = summary_Requests.Rows[position]["itemQty"].ToString();
if (selected_pos == position)
vh.ItemView.SetBackgroundColor(Color.ParseColor("#4fa5d5"));
else
vh.ItemView.SetBackgroundColor(Color.LightGray);
}
public DataTable get_dt_final()
{
DataTable final_dt = summary_Requests.Copy();
return final_dt;
}
public override int ItemCount
{
get { return summary_Requests.Rows.Count; }
}
// Raise an event when the item-click takes place:
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
// user.req_pos = position;
}
}
}
}
this is the user class:
public static class user
{
public static string zero_val = "";
}
If I undstand your meanings correctly, I don't think it's correct to use variable zero_val in class user to indicate whether or not null values exist.For example ,if you have enter a empty value for the first EditText, then the value of zero_val will been changed to Not_exist, then if we enter another empty value for the second EditText, then the value of zero_val will also been changed to Not_exist,after that, if we change the second EditText to a correct value, then the value of zero_val will been changed to exits.But now, actually the first EditText still be empty.
I think you can verify the values the table DataTable when clicking button.
You can refer to the following code:
btn.Click += delegate
{
bool hasEmpty = false ;
foreach (DataRow row in dt.Rows)
{
string itemQty = row["itemQty"].ToString();
string rowNumber = row["rowNumber"].ToString();
System.Diagnostics.Debug.WriteLine("rowNumber =" + rowNumber + "< --- > itemQty = " + itemQty);
if (string.IsNullOrEmpty(itemQty)) {
hasEmpty = true;
}
}
//if (user.zero_val.Equals("exits"))
// Toast.MakeText(this, "exists", ToastLength.Long).Show();
//if (user.zero_val.Equals("Not_exist"))
// Toast.MakeText(this, "Not_exist", ToastLength.Long).Show();
if (!hasEmpty)
Toast.MakeText(this, "exists", ToastLength.Long).Show();
else
Toast.MakeText(this, "Not_exist", ToastLength.Long).Show();
};
In addition, modify the TextChanged function in RecyclerviewAdapter:
vh.qty.TextChanged += (sender, e) =>
{
if (!vh.qty.Text.Equals(""))
try
{
int position = vh.LayoutPosition;
summary_Requests.Rows[position]["itemQty"] = Convert.ToDecimal(vh.qty.Text);
}
catch (System.FormatException exp)
{
var icon = AppCompatResources.GetDrawable(context, Resource.Drawable.error);
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("qty can be decimal", icon);
//store a empty value for this textview
int position = vh.LayoutPosition;
summary_Requests.Rows[position]["itemQty"] = "";
}
else if (vh.qty.Text.Equals(""))
{
var icon = AppCompatResources.GetDrawable(context, Resource.Drawable.error);
int position = vh.LayoutPosition;
//store a empty value for this textview
summary_Requests.Rows[position]["itemQty"] = "";
icon.SetBounds(0, 0, 50, 50);
vh.qty.SetError("value can not be empty", icon);
}
};

OptaPlaner simple example cant find feasible solution

to get familiar with optaplanner i created a simple test project. I only have one Solution and one Entity class. The Entity has only one value between 0 and 9. There should only be odd numbers and the sum of all should be less then 10 (this are just some random constraints i came up with).
As Score i use a simple HardSoftScore. Here is the code:
public class TestScoreCalculator implements EasyScoreCalculator<TestSolution>{
#Override
public HardSoftScore calculateScore(TestSolution sol) {
int hardScore = 0;
int softScore = 0;
int valueSum = 0;
for (TestEntity entity : sol.getTestEntities()) {
valueSum += entity.getValue() == null? 0 : entity.getValue();
}
// hard Score
for (TestEntity entity : sol.getTestEntities()) {
if(entity.getValue() == null || entity.getValue() % 2 == 0)
hardScore -= 1; // constraint: only odd numbers
}
if(valueSum > 10)
hardScore -= 2; // constraint: sum should be less than 11
// soft Score
softScore = valueSum; // maximize
return HardSoftScore.valueOf(hardScore, softScore);
}
}
and this is my config file:
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!-- Domain model configuration -->
<scanAnnotatedClasses/>
<!-- Score configuration -->
<scoreDirectorFactory>
<easyScoreCalculatorClass>score.TestScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<secondsSpentLimit>30</secondsSpentLimit>
</termination>
</solver>
for some reason OptaPlanner cant find a feasible solution. It terminates with LS step (161217), time spent (29910), score (-2hard/10soft), best score (-2hard/10soft)... and the solution 9 1 0 0.
So the hardScore is -2 because the two 0 are not odd. A possible solution would be 7 1 1 1 for example. Why is this ? This should be a really easy example ...
(when i set the Start values to 7 1 1 1 it terminates with this solution and a score of (0hard/10soft) how it should be)
Edit:
The Entity class
#PlanningEntity
public class TestEntity {
private Integer value;
#PlanningVariable(valueRangeProviderRefs = {"TestEntityValueRange"})
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
#ValueRangeProvider(id = "TestEntityValueRange")
public CountableValueRange<Integer> getStartPeriodRange() {
return ValueRangeFactory.createIntValueRange(0, 10);
}
}
The Solution class
#PlanningSolution
public class TestSolution {
private List<TestEntity> TestEntities;
private HardSoftScore score;
#PlanningEntityCollectionProperty
public List<TestEntity> getTestEntities() {
return TestEntities;
}
public void setTestEntities(List<TestEntity> testEntities) {
TestEntities = testEntities;
}
#PlanningScore
public HardSoftScore getScore() {
return score;
}
public void setScore(HardSoftScore score) {
this.score = score;
}
#Override
public String toString() {
String str = "";
for (TestEntity testEntity : TestEntities)
str += testEntity.getValue()+" ";
return str;
}
}
The Main Program class
public class Main {
public static final String SOLVER_CONFIG = "score/TestConfig.xml";
public static int printCount = 0;
public static void main(String[] args) {
init();
}
private static void init() {
SolverFactory<TestSolution> solverFactory = SolverFactory.createFromXmlResource(SOLVER_CONFIG);
Solver<TestSolution> solver = solverFactory.buildSolver();
TestSolution model = new TestSolution();
List<TestEntity> list = new ArrayList<TestEntity>();
// list.add(new TestEntity(){{setValue(7);}});
// list.add(new TestEntity(){{setValue(1);}});
// list.add(new TestEntity(){{setValue(1);}});
// list.add(new TestEntity(){{setValue(1);}});
for (int i = 0; i < 4; i++) {
list.add(new TestEntity());
}
model.setTestEntities(list);
// Solve the problem
TestSolution solution = solver.solve(model);
// Display the result
System.out.println(solution);
}
}
It gets stuck in a local optima because there is no move that takes 1 from entity and gives it to another entity. With a custom move you can add that.
These kind of moves only apply to numeric value ranges (which are rare, usually value ranges are a list of employees etc), but they should probably exist out of the box (feel free to create a jira for them).
Anyway, another way to get the good solution is to add <exhaustiveSearch/>, that bypassing local search and therefore the local optima. But that doesn't scale well.

Drag a Textfield to a new position

Im trying to get my TextField to move on the screen. I want to be able to drag it to a new position on the screen. I´ve been struggling with this for days now and I really cant figure this one out...
This is what I´ve done so far:
InputProcessor drag = new InputAdapter() {
#Override
public boolean touchDown(int screenX, int screenY, int pointer,
int button) {
// TODO Auto-generated method stub
return super.touchDown(screenX, screenY, pointer, button);
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer,
int button) {
int x = Gdx.input.getX();
int y = Gdx.input.getY();
textField.setPosition(x, y);
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
// TODO Auto-generated method stub
return super.touchDragged(screenX, screenY, pointer);
}
};
game.inputMultiplexer = new InputMultiplexer();
game.inputMultiplexer.addProcessor(stage);
game.inputMultiplexer.addProcessor(stagePurc);
game.inputMultiplexer.addProcessor(stageText);
game.inputMultiplexer.addProcessor(drag);
Gdx.input.setInputProcessor(game.inputMultiplexer);
Here´s the textfield:
final TextField textField = new TextField(prefs.getString("textField", "Enter name:"), textstyle);
textField.setX(textX);
textField.setY(textY);
textField.setMaxLength(20);
textField.setWidth(textWidth);
textField.setHeight(textHeight);
Put the TextView in a LinearLayout:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:clipChildren="false"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#color/text_color"
android:textSize="16sp" />
</LinearLayout>
Then set a touch listener:
txt.setOnTouchListener(new View.OnTouchListener() {
int initialX = 0;
int initialY = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
initialX = (int) event.getX();
initialY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) txt.getLayoutParams();
int left = lp.leftMargin + (currentX - initialX);
int top = lp.topMargin + (currentY - initialY);
int right = lp.rightMargin - (currentX - initialX);
int bottom = lp.bottomMargin - (currentY - initialY);
lp.rightMargin = right;
lp.leftMargin = left;
lp.bottomMargin = bottom;
lp.topMargin = top;
txt.setLayoutParams(lp);
break;
default:
break;
}
return true;
}
});
Works pretty well. I got this code from here: How to make the TextView drag in LinearLayout smooth, in android?

C++/CLI IEnumerable and IEnumerator implementation

Does anyone have a working, step-by-step example of how to implement IEnumerable and IEnumerator in C++/CLI? Alternatively, does someone know how to fix the following code from MS Connect which does not compile in Visual Studio 2005?
http://connect.microsoft.com/VisualStudio/feedback/details/101089/how-to-implement-ienumerable-t-and-ienumerable-c-cli
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
bool MoveNext()
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
T get()
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() new sealed = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
void Reset() {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() new sealed = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}
The compiler is unable to find the enumerator method implementations:
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'bool System::Collections::IEnumerator::MoveNext(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'void System::Collections::IEnumerator::Reset(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'T System::Collections::Generic::IEnumerator<T>::Current::get(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>' must provide an implementation for the interface method 'System::Collections::Generic::IEnumerator<T> ^System::Collections::Generic::IEnumerable<T>::GetEnumerator(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 68
This compiles for me without a single warning (on VS2010):
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
virtual bool MoveNext() = IEnumerator<T>::MoveNext
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
virtual T get() = IEnumerator<T>::Current::get
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
virtual void Reset() = IEnumerator<T>::Reset {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
virtual IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}

Receiving Index Out of Range with NHibernate

I'm hoping that someone can help me with this issue. I've been racking
my brain and my project is due very soon. Thank You in advance.
I'm receiving an index out of range exception when inserting a new
record. After searching endlessly for information, it was suggested
that the number of column values in my mapping do not match that in my
persistent class. However, I counted and re-counted, and they seem to
match. As you can see by my code below, I'm using
NHibernate.Mapping.Attributes to do my mapping. Maybe I'm doing
something wrong there.
I finally downloaded the NHibernate source and debugged through my
problem. Below is the insert statement that NHibernate is attempting
to build:
{INSERT INTO WTSLIB33T.PRODDATA (PSTAT, PCONO, PDVNO, PWKTY, PCRTY,
PTSID, PCNNO, PDTTK, PJBNO, PSJNO, PTKNO, PCWNO, PWKAR, PWKDC, PWKCD,
PCNWO, PWDNO, PDESC, PDCCD, PHRS, PUNIT, PSEQ, PCUST) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}
As you can see, the number of parameters matches the number of fields
in the list. I've also matched up this generated insert with my class
and what I found is that the PSEQ and PCUST columns are out of order
with my persistent class. Then, while debugging through the Dehydrate
function I found two possible issues. The first is that I noticed that
the call to the NullSafeSet function sets parameter 0 to what my PSEQ
field should be set to but parameter 0 in the insert statement is
PSTAT.
The second issue I noticed is that the very last call "index +=
ArrayHelper.CountTrue(includeColumns[i]);" in the Dehydrate function
leaves the index variable at 23 which is correct; however, the next
call "IdentifierType.NullSafeSet(statement, id, index,
session);" ,where it checks for a row id, passes in index 23 which
would be out of range. This value should be 22 for the zero based
array.
protected int Dehydrate(object id, object[] fields, object rowId, bool[] includeProperty, bool[][] includeColumns, int table, IDbCommand statement, ISessionImplementor session, int index)
{
if (log.IsDebugEnabled)
{
log.Debug("Dehydrating entity: " + MessageHelper.InfoString(this, id, Factory));
}
// there's a pretty strong coupling between the order of the SQL parameter
// construction and the actual order of the parameter collection.
for (int i = 0; i < entityMetamodel.PropertySpan; i++)
{
if (includeProperty[i] && IsPropertyOfTable(i, table))
{
PropertyTypes[i].NullSafeSet(statement, fields[i], index, includeColumns[i], session);
index += ArrayHelper.CountTrue(includeColumns[i]);
}
if (rowId != null)
{
// TODO H3.2 : support to set the rowId
// TransactionManager.manager.SetObject(ps, index, rowId);
// index += 1;
throw new NotImplementedException("support to set the rowId");
}
else if (id != null)
{
IdentifierType.NullSafeSet(statement, id, index, session);
index += IdentifierColumnSpan;
}
return index;
}
MY PERSISTENT CLASS:
[NHibernate.Mapping.Attributes.Class(0, Schema = WTSLIB33T, Table =
"PRODDATA", NameType = typeof(ProddataDAO),
Lazy = true)]
public class ProddataDAO : Object // : INotifyPropertyChanged
{
public ProddataDAO()
{
}
public ProddataDAO(string PSTAT, decimal PCONO, decimal PDVNO, decimal PSEQ, string PWKTY, string PCRTY,
decimal PTSID, decimal PCUST, decimal PCNNO, decimal PDTTK, string PJBNO, string PSJNO, decimal PTKNO,
string PCWNO, string PWKAR, string PWKDC, string PWKCD, string PCNWO, decimal PWDNO, string PDESC,
decimal PDCCD, decimal PHRS, decimal PUNIT)
{
_PSTAT = PSTAT;
_PCONO = PCONO;
_PDVNO = PDVNO;
_PSEQ = PSEQ;
_PWKTY = PWKTY;
_PCRTY = PCRTY;
_PTSID = PTSID;
_PCUST = PCUST;
_PCNNO = PCNNO;
_PDTTK = PDTTK;
_PJBNO = PJBNO;
_PSJNO = PSJNO;
_PTKNO = PTKNO;
_PCWNO = PCWNO;
_PWKAR = PWKAR;
_PWKDC = PWKDC;
_PWKCD = PWKCD;
_PCNWO = PCNWO;
_PWDNO = PWDNO;
_PDESC = PDESC;
_PDCCD = PDCCD;
_PHRS = PHRS;
_PUNIT = PUNIT;
}
//public event PropertyChangedEventHandler PropertyChanged;
private decimal _PSEQ;
//[NHibernate.Mapping.Attributes.Id(0, Name="PSEQ", Column="PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.CompositeId(1, UnsavedValue=NHibernate.Mapping.Attributes.UnsavedValueType.Undefined)]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PSEQ", Column = "PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PCUST", Column = "PCUST")]
//[NHibernate.Mapping.Attributes.Generator(3, Class="none")]
[NHibernate.Mapping.Attributes.Property(4, Name="PSEQ", Column="PSEQ")]
public virtual decimal PSEQ
{
get
{
return _PSEQ;
}
set
{
if (value != this._PSEQ)
{
_PSEQ = value;
//OnPropertyChanged("PSEQ");
}
}
}
private decimal _PCUST;
//[NHibernate.Mapping.Attributes.Id(0, Column = "PCUST", Type = "Decimal")]
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCUST
{
get
{
return _PCUST;
}
set
{
if (value != this._PCUST)
{
_PCUST = value;
//OnPropertyChanged("PCUST");
}
}
}
private string _PSTAT;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PSTAT
{
get
{
return _PSTAT;
}
set
{
if (value != this._PSTAT)
{
this._PSTAT = value;
//OnPropertyChanged("PSTAT");
}
}
}
private decimal _PCONO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCONO
{
get
{
return _PCONO;
}
set
{
if (value != this._PCONO)
{
_PCONO = value;
//OnPropertyChanged("PCONO");
}
}
}
private decimal _PDVNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDVNO
{
get
{
return _PDVNO;
}
set
{
if (value != this._PDVNO)
{
_PDVNO = value;
//OnPropertyChanged("PDVNO");
}
}
}
private string _PWKTY;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKTY
{
get
{
return _PWKTY;
}
set
{
if (value != this._PWKTY)
{
_PWKTY = value;
//OnPropertyChanged("PWKTY");
}
}
}
private string _PCRTY;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCRTY
{
get
{
return _PCRTY;
}
set
{
if (value != this._PCRTY)
{
_PCRTY = value;
//OnPropertyChanged("PCRTY");
}
}
}
private decimal _PTSID;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PTSID
{
get
{
return _PTSID;
}
set
{
if (value != this._PTSID)
{
_PTSID = value;
//OnPropertyChanged("PTSID");
}
}
}
private decimal _PCNNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PCNNO
{
get
{
return _PCNNO;
}
set
{
if (value != this._PCNNO)
{
_PCNNO = value;
//OnPropertyChanged("PCNNO");
}
}
}
private decimal _PDTTK;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDTTK
{
get
{
return _PDTTK;
}
set
{
if (value != this._PDTTK)
{
_PDTTK = value;
//OnPropertyChanged("PDTTK");
}
}
}
private string _PJBNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PJBNO
{
get
{
return _PJBNO;
}
set
{
if (value != this._PJBNO)
{
_PJBNO = value;
//OnPropertyChanged("PJBNO");
}
}
}
private string _PSJNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PSJNO
{
get
{
return _PSJNO;
}
set
{
if (value != this._PSJNO)
{
_PSJNO = value;
//OnPropertyChanged("PSJNO");
}
}
}
private decimal _PTKNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PTKNO
{
get
{
return _PTKNO;
}
set
{
if (value != this._PTKNO)
{
_PTKNO = value;
//OnPropertyChanged("PTKNO");
}
}
}
private string _PCWNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCWNO
{
get
{
return _PCWNO;
}
set
{
if (value != this._PCWNO)
{
_PCWNO = value;
//OnPropertyChanged("PCWNO");
}
}
}
private string _PWKAR;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKAR
{
get
{
return _PWKAR;
}
set
{
if (value != this._PWKAR)
{
_PWKAR = value;
//OnPropertyChanged("PWKAR");
}
}
}
private string _PWKDC;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKDC
{
get
{
return _PWKDC;
}
set
{
if (value != this._PWKDC)
{
_PWKDC = value;
//OnPropertyChanged("PWKDC");
}
}
}
private string _PWKCD;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PWKCD
{
get
{
return _PWKCD;
}
set
{
if (value != this._PWKCD)
{
_PWKCD = value;
//OnPropertyChanged("PWKCD");
}
}
}
private string _PCNWO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PCNWO
{
get
{
return _PCNWO;
}
set
{
if (value != this._PCNWO)
{
_PCNWO = value;
//OnPropertyChanged("PCNWO");
}
}
}
private decimal _PWDNO;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PWDNO
{
get
{
return _PWDNO;
}
set
{
if (value != this._PWDNO)
{
_PWDNO = value;
//OnPropertyChanged("PWDNO");
}
}
}
private string _PDESC;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual string PDESC
{
get
{
return _PDESC;
}
set
{
if (value != this._PDESC)
{
_PDESC = value;
//OnPropertyChanged("PDESC");
}
}
}
private decimal _PDCCD;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PDCCD
{
get
{
return _PDCCD;
}
set
{
if (value != this._PDCCD)
{
_PDCCD = value;
//OnPropertyChanged("PDCCD");
}
}
}
private decimal _PHRS;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PHRS
{
get
{
return _PHRS;
}
set
{
if (value != this._PHRS)
{
_PHRS = value;
//OnPropertyChanged("PHRS");
}
}
}
private decimal _PUNIT;
[NHibernate.Mapping.Attributes.Property(4)]
public virtual decimal PUNIT
{
get
{
return _PUNIT;
}
set
{
if (value != this._PUNIT)
{
_PUNIT = value;
//OnPropertyChanged("PUNIT");
}
}
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
ProddataDAO p = obj as ProddataDAO;
if (this.PCONO == p.PCONO && this.PDVNO == p.PDVNO && this.PCUST == p.PCUST && this.PSEQ == p.PSEQ)
return true;
else
return false;
}
public override int GetHashCode()
{
int hash = 1122;
hash += (null == this.PCONO ? 0 : this.PCONO.GetHashCode());
hash += (null == this.PDVNO ? 0 : this.PDVNO.GetHashCode());
hash += (null == this.PCUST ? 0 : this.PCUST.GetHashCode());
hash += (null == this.PSEQ ? 0 : this.PSEQ.GetHashCode());
return hash;
}
One possible cause for this problem is that you have mapped two properties to the same column. For example you have mapped a foreign key relation as a relation and as a property field, or you have a descriminator that you also have mapped as a field.
Looking at the primary key mapping I see that it is mapped twice:
[NHibernate.Mapping.Attributes.CompositeId(1, UnsavedValue=NHibernate.Mapping.Attributes.UnsavedValueType.Undefined)]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PSEQ", Column = "PSEQ", Type="Decimal")]
[NHibernate.Mapping.Attributes.KeyProperty(2, Name = "PCUST", Column = "PCUST")]
//[NHibernate.Mapping.Attributes.Generator(3, Class="none")]
[NHibernate.Mapping.Attributes.Property(4, Name="PSEQ", Column="PSEQ")]
Are you sure this is the way to map a composite key with NHiberante attributes? I haven't used it myself. But my guess is that it is this that is causing NHibernate to think that you have mapped the column PSEQ twice.
I think you should only use the KeyProperty and skip the Property attribute for the properties that belong to the primary key.
Try adding this in the top section of the class (do not adorn the property declarations)
[CompositeId(1,UnsavedValue=UnsavedValueType.Undefined)]
[KeyProperty(2, Name="PSEQ", Column="PSEQ")]
[KeyProperty(4, Name="PCUST", Column="PCUST")]
Found this leated forum thread: https://forum.hibernate.org/viewtopic.php?f=25&t=964631&start=0
i had a similar situation when using XML mapping, we had originally included the "parent id" column in the .hbm.xml, then when we went to add the back-reference via a many-to-one tag i received the index out of range exception. removing the original declaration was the key.
<class name="IncomeDetail" table="INCOMEDETAILS" mutable="true" lazy="false">
<id name="IncomeDetailID" column="INCOME_DETAIL_ID">
<generator class="native" />
</id>
<property name='ParticipantID' column='PARTICIPANT_ID' type='Int32'/>
<property name='IncomeGroupCD' column='INCOME_GROUP_CD' type='String'/>
<property name='IncomeTypeID' column='INCOME_TYPE_ID' type='Int32'/>
<!--<property name='EmploymentID' column='EMPLOYMENT_ID' type='Int32'/>-->
<property name='IncomeFrequencyCD' column='INCOME_FREQUENCY_CD' type='String'/>
<property name='CapturedDetGrossIncomeAmt' column='CAPTURED_DET_GROSS_INCOME_AMT' type='Decimal'/>
<property name='CapturedDetNetIncomeAmt' column='CAPTURED_DET_NET_INCOME_AMT' type='Decimal'/>
<property name='VerifiedDetGrossIncomeAmt' column='VERIFIED_DET_GROSS_INCOME_AMT' type='Decimal'/>
<property name='VerifiedDetNetIncomeAmt' column='VERIFIED_DET_NET_INCOME_AMT' type='Decimal'/>
<property name='IncomeDesc' column='INCOME_DESC' type='String'/>
<property name='CapturedDT' column='CAPTURED_DT' type='DateTime' not-null='true'/>
<property name='CapturedBy' column='CAPTURED_BY' type='String' not-null='true'/>
<property name='VerificationDT' column='VERIFICATION_DT' type='DateTime' />
<property name='VerifiedBy' column='VERIFIED_BY' type='String' />
<property name='VefificationSourceCD' column='VEFIFICATION_SOURCE_CD' type='String'/>
<many-to-one name="EmploymentIncome" column="EMPLOYMENT_ID" />
</class>