I am using latest release of mpandroidchart library. I have 2 bar charts on single activity. chart1 & chart2 are the id's in XML (I don't want to use barchart list view). chart1 cosnist Counts value & chart2 consist dollars value. I am getting the values already. But I want to know that is it a dollar value or counts value. so I can display the toast according to chart selected.
This is my Sample code.
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
View view;
TextView text;
switch (e.getXIndex()) {
case 0:
if (toast != null)
toast.cancel();
toast = Toast.makeText(getActivity(), "All Other Year Defectors: " +e.getVal(), Toast.LENGTH_SHORT);
view = toast.getView();
view.setBackgroundResource(R.color.all_odr_yr);
toast.setGravity(Gravity.TOP, 0, 950);
toast.show();
break;
case 1:
if (toast != null)
toast.cancel();
toast = Toast.makeText(getActivity(), "Last Year Defectors: " + e.getVal(), Toast.LENGTH_SHORT);
view = toast.getView();
view.setBackgroundResource(R.color.lst_yr_df);
toast.setGravity(Gravity.TOP, 0, 950);
toast.show();
break;
That seems to be quite difficult and hard to acheive with the library alone.
But what you could do is inline the listeners and use a separate listener for each chart, like this:
countChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
#Override
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
// COUNT CHART VALUE SELECTED
}
#Override
public void onNothingSelected() { }
});
dollarChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
#Override
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
// DOLLAR CHART VALUE SELECTED
}
#Override
public void onNothingSelected() { }
});
In that way you can differentiate between the different charts.
If you do not want to use inline listeners as Philip mentioned in his answer you can create a class implementing onChartValueSelectedListener and identify each chart with an ID.
private class CustomOnValueSelectedListener implements OnChartValueSelectedListener {
private int CHART_ID;
public CustomOnValueSelectedListener() {}
public CustomOnValueSelectedListener(int chart_id) {
CHART_ID = chart_id;
}
#Override
public void onValueSelected(Entry e, Highlight h) {
switch (CHART_ID) {
case PIE_CHART_ID:
break;
case BAR_CHART_ID:
break;
case LINE_CHART_ID:
break;
default:
//common code
break;
}
}
#Override
public void onNothingSelected() {
}
}
You can now do this -
pieChart.setOnChartValueSelectedListener(new CustomOnValueSelectedListener(PIE_ID));
barChart.setOnChartValueSelectedListener(new CustomOnValueSelectedListener(BAR_ID));
lineChart.setOnChartValueSelectedListener(new CustomOnValueSelectedListener(LINE_ID));
someOtherChart.setOnChartValueSelectedListener(new CustomValueSelectedListener());
where PIE_ID, LINE_ID and BAR_ID are some unique integers.
This way your code is concise in case you have more than 3-4 charts to deal with else inline listeners are better.
Related
friends.
I have an app module that implements State pattern. Idea is:
1. User enter the Date -->
2. Screen changes to a ne state: dynamically inflates ListView and asks user to fill the list with some data
Problem is that when I call notifyDataSetChange() from update method 2nd time, EditText view doens't want to do its functions anymore.
This is a string from a logcat, that I think contains key of my problem.
09-10 10:33:38.937 26954-26954/com.example.android.turtleinfo D/ListView: change accessibility focus position = 0
Here are codes for everything.
1. My State Pattern Super Class
public abstract class ScreenState
{
public BuilderActivity activity;
public ScreenState(BuilderActivity activity) {
this.activity = activity;
//initializeScreen(activity);
}
public abstract void initializeScreen(Activity activity);
public abstract void switchState();
public abstract void updateText(View view);
public void addTextWatcher(EditText text) {
text.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
activity.state.updateText(v);
return true;
}
return false;
}
});
}
}
2. Implementation of initialize screen and updateData methods
#Override
public void initializeScreen(Activity activity) {
((BuilderActivity) activity).editText.setHint("Name");
addTextWatcher(((BuilderActivity) activity).editText);
textView = (TextView)activity.getLayoutInflater().inflate(R.layout.schedule_text_style, null);
textView.setHeight(100);
screenText = "End Date: " + new SimpleDateFormat("MMMM dd, yyyy", Locale.ENGLISH).format(((BuilderActivity) activity).data.getEndDate())+"\n\n";
textView.setText(screenText+"\n");
((BuilderActivity) activity).scheduleLayout.addView(textView);
((BuilderActivity) activity).data.setNames(new ArrayList<String>());
lv = (ListView)activity.getLayoutInflater().inflate(R.layout.listview_text_style, null);
listItems = new ArrayList<>();
adapt = new ArrayAdapter<>(super.activity, R.layout.schedule_text_style, listItems);
lv.setAdapter(adapt);
((BuilderActivity) activity).scheduleLayout.addView(lv);
}
#Override
public void updateText(View view) {
String text = activity.editText.getText().toString();
if (text.length() >= 2) {
if (!activity.data.names.contains(text)) {
activity.data.addToList(text);
listItems.add(text);
adapt.notifyDataSetChanged();
activity.editText.setText("");
counter++;
activity.editText.setText("");
} else {
Toast.makeText(activity, "same names are not allowed",
Toast.LENGTH_LONG).show();
((BuilderActivity) activity).editText.setText("");
}
}
else
{
Toast.makeText(activity, "name should contain 2 or more symbols",
Toast.LENGTH_LONG).show();
((BuilderActivity) activity).editText.setText("");
}
}
This is how it looks on device.
1. First insertion is ok
2. And second and further insertionas are impossible. OK softkeyboard button switches first to NEXT button
3. If I click next, EditText looses focus, nothing happens, but NEXT button Switches to '/n' button.
So, please, if anyone know, what am I doing worng, help!
Thanks in advance!
Your problem is in
public void addTextWatcher(EditText text)
function.
Look at the android:imeActionId and android:imeOptions attributes, plus the setOnEditorActionListener() method, all on TextView/Edittext.
You can also change the text of the keyboard button by using this.
mEditText.setImeActionLabel("Your text", KeyEvent.KEYCODE_ENTER);
I have the following code:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getItemAtPosition(position);
Toast.makeText(this, "You selected " +item.toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(this, "You didn't select any preset", Toast.LENGTH_SHORT).show();
}
And the following array:
<string-array name="presets_array">
<item>Light Car</item>
<item>Medium Car</item>
<item>Heavy Car</item>
<item>Van</item>
</string-array>
It's working fine, when I select Light car it displays the correct text and so on with the others.
But I want to do more things, if selected thing is Van, change weight value, if medium car, other cost, etc.
I think I have to use a switch but I'm not sure how it works.
There are some options. You should choose the best which fits to you...
Just checking position
Good performance but if you change array order, you must re-order the switch statement
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getItemAtPosition(position);
Toast.makeText(this, "You selected " + item.toString(), Toast.LENGTH_SHORT).show();
swith(position) {
case 0:
// CODE for Light Car
break;
case 1:
// CODE for Medium Car
break;
case 2:
// CODE for Heavy Car
break;
case 3:
// CODE for Van
break;
}
}
String Checking
Low performance since you have to compare Strings several times in the worst case.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Object item = parent.getItemAtPosition(position);
Toast.makeText(this, "You selected " + item.toString(), Toast.LENGTH_SHORT).show();
if(item.toString().equals("Light Car")) {
// CODE
} else if(item.toString().equals("Medium Car")) {
// CODE
} else if(item.toString().equals("Heavy Car")) {
// CODE
} else if(item.toString().equals("Van")) {
// CODE
}
}
you can write code similar to this code inside onItemSelected method:
switch (item)
{
case Light Car:
// TODD
break;
case Van:
// TODO
break;
.......
}
i have created a custom listview with an ImageView, two TextViews and a Button
now i am facing issue when i try to set onClicklistner to that button
i want different method to be done for every button
here is my code for customlistview class
i have used temporary onclicklistner for that button which shows the toast "Bought"
what i want to do is that after clicking the button i have to return the price of the food.
class CustomListView extends ArrayAdapter {
public CustomListView(Context context, String[] resource) {
super(context,R.layout.custom_view , resource);
}
Toast toast= null;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater MyInflater = LayoutInflater.from(getContext());
View CustomView = MyInflater.inflate(R.layout.custom_view, parent, false);
String SingleItem= (String) getItem(position);
final TextView text =(TextView)CustomView.findViewById(R.id.Itemname);
final ImageView Image= (ImageView)CustomView.findViewById(R.id.icon);
final TextView Pricetag= (TextView)CustomView.findViewById(R.id.PriceTextView);
text.setText(SingleItem);
switch (SingleItem)
{
case "Chicken":
Image.setImageResource(R.drawable.desert1);
Pricetag.setText("Rs 300");
break;
case "soap":
Image.setImageResource(R.drawable.desert2);
Pricetag.setText("Rs 300");
break;
case "Fish":
Image.setImageResource(R.drawable.fish);
Pricetag.setText("Rs 100");
break;
default:
Image.setImageResource(R.drawable.myimage);
Pricetag.setText("Rs 0.00");
break;
}
final Button Buybutton= (Button)CustomView.findViewById(R.id.BuyButton);
toast = Toast.makeText(getContext(), "", Toast.LENGTH_LONG);
Buybutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toast.setText("Bought");
toast.show();
}
});
text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toast.setText(text.getText().toString());
toast.show();
}
});
return CustomView;
}
}
For the record, there should be a better way to do this, using food-id or other approach to prevent this, but based on your request, here we go:
1- in getView() when you get a reference on the button i.e:
final Button Buybutton= (Button)CustomView.findViewById(R.id.BuyButton);
do a one more step:
Buybutton.setTag(10);
10 here could be any other number, and you need to find a way to determine which number to use for each button, also it could be a string , ex value of SingleItem
Buybutton.setTag(SingleItem);
2- at onClick() you need to find out what the value assign to the view (button) and based on this value call the proper method:
#Override
public void onClick(View v) {
if (v.getTag().toString().equals("xxxxx")){
doSomething();
}else if (v.getTag().toString().equals("yyyy")){
doAnotherThing();
}else if (v.getTag().toString().equals("zzzzz")){
doSomething12();
}
//and so on...
}
this approach used String as value in setTag() and getTag()
if you use integers, just replace the condition as belwo:
if (Integer.parseInt(v.getTag().toString()) == 10)
EDIT:
If i understand well, then you need to:
Buybutton.setTag(SingleItem);
and onClick():
#Override
public void onClick(View v) {
showPriceTag(v.getTag().toString());
}
add method showPriceTag():
public void showPriceTag(String type){
switch (type)
{
case "Chicken":
//set the price tag data ...
break;
case "soap":
//set the price tag data ...
break;
case "Fish":
//set the price tag data ...
break;
default:
//set the default price tag data ...
break;
}
}
If i call the snackbar multiple times in a row, only the last snackbar item is displayed.
e.g. with the codes below, only Item 3 would be shown. it seems that Snackbar.LENGTH_LONG is ignored (and set to zero?) for item 1 and 2.
Snackbar.make(view, "Item 1", Snackbar.LENGTH_LONG).show();
Snackbar.make(view, "Item 2", Snackbar.LENGTH_LONG).show();
Snackbar.make(view, "Item 3", Snackbar.LENGTH_LONG).show();
yet in the google documents, I see that it is possible to queue the messages.
public boolean isShownOrQueued ()
Returns whether this Snackbar is currently being shown,
or is queued to be shown next.
so how do we actually queue the snackbar?
Here is a partial snippet that solves your problem, although it might not
be the correct way to go about things:
//using a queue to pass string to the snackbar
Queue<String> myQueue = new LinkedList<String>();
myQueue.offer("item 1");
myQueue.offer("item 2");
myQueue.offer("item 3");
displaysnack(myQueue, view);
public void displaysnack(final Queue dQueue, final View view){
Snackbar.make(view, (String)dQueue.poll(), Snackbar.LENGTH_LONG).setCallback(new Snackbar.Callback() {
#Override
public void onDismissed(Snackbar snackbar, int event) {
switch (event) {
case Snackbar.Callback.DISMISS_EVENT_ACTION:
Toast.makeText(getApplicationContext(), "Clicked the action", Toast.LENGTH_LONG).show();
break;
//once the timeout expires, display the next one in the queue.
case Snackbar.Callback.DISMISS_EVENT_TIMEOUT:
Toast.makeText(getApplicationContext(), "Showing: "+ (dQueue.size()), Toast.LENGTH_SHORT).show();
if (dQueue.size()>0){displaysnack(dQueue, view);}
break;
case Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE:
//Toast.makeText(getApplicationContext(), "Multiple Shown", Toast.LENGTH_SHORT).show();
break;
}
}
I also needed to implement a queue of snackbars but did not find ready solution. So I decided to implement it on my own. You can try it https://github.com/AntonyGolovin/FluentSnackbar.
Just call important() on Builder and it will be added to the queue.
I also implemented my own, probably not the slickest but suited my needs. Its in C# for Xamarin though.
public class SnackbarManager : Snackbar.Callback
{
List<Snackbar> snackbarsWaiting;
List<Snackbar> snackbarsHolding;
public SnackbarManager()
{
snackbarsWaiting = new List<Snackbar>();
snackbarsHolding = new List<Snackbar>();
}
public void AddToQueue(Snackbar snackbar)
{
if (snackbar.Duration == Snackbar.LengthIndefinite) snackbar.SetDuration(Snackbar.LengthLong);
snackbar.SetCallback(this);
if (snackbarsWaiting.Count > 0 && snackbarsWaiting[0].IsShown) snackbarsHolding.Add(snackbar);
else snackbarsWaiting.Add(snackbar);
}
public void Show()
{
if (snackbarsWaiting.Count > 0 && !snackbarsWaiting[0].IsShown)
snackbarsWaiting[0].Show();
}
public override void OnDismissed(Snackbar snackbar, int evt)
{
base.OnDismissed(snackbar, evt);
snackbarsWaiting.Remove(snackbar);
if (snackbarsHolding.Count > 0)
{
snackbarsWaiting.AddRange(snackbarsHolding);
snackbarsHolding.Clear();
}
if (snackbarsWaiting.Count > 0) snackbarsWaiting[0].Show();
}
}
I met this problem too, this is my solution.
static List<Snackbar> snackBarList = new ArrayList<>();
public static void mySnackBar(CoordinatorLayout coordinatorLayout, String s,boolean queued) {
Snackbar snackbar = Snackbar.make(coordinatorLayout, s, Snackbar.LENGTH_SHORT);
if (queued) {
//if true set onDismiss CallBack
snackbar.setCallback(new Snackbar.Callback()
{
#Override
public void onDismissed(Snackbar currentSnackbar, int event) {
super.onDismissed(currentSnackbar, event);
//first remove current snackBar in List, then if List not empty show the first one
snackBarList.remove(currentSnackbar);
if (snackBarList.size() > 0)
snackBarList.get(0).show();
}
});
//add (set callback) snackBar to List
snackBarList.add(snackbar);
//the beginning
if (snackBarList.size() == 1)
snackBarList.get(0).show();
} else snackbar.show();
}
I've written a library that do just that. It also includes progressBar. Try it out https://github.com/tingyik90/snackprogressbar
I have a TextView. I have added custom links like "#abc", "#android" by matching some regex pattern. The links are displaying properly. However I am not getting a way to extract the text of the link which is clicked. I am using SpannableString to setText to the textview. I then set spans using my custom ClickableSpan. It works fine. Plus I can also catch the onclick event. But the onClick() method has a View paramter. If I call getText() on the View (ofcourse after typecasting it to TextView), it returns the entire text.
I searched a lot but always found ways to add links and catch the event, but none told about getting the text of the link.
This is the code I am using to add links and recieve onclick. I got the code from one of the SO threads..
Pattern pattern = Pattern.compile("#[\\w]+");
Matcher matcher = pattern.matcher(tv.getText());//tv is my TextView
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
f.setSpan(new InternalURLSpan(new View.OnClickListener() {
public void onClick(View v) {
showDialog(1);
}
}), x, y, android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
tv.setLinkTextColor(Color.rgb(19, 111, 154));
tv.setLinksClickable(true);
Here is the InternalURLSpan:
class InternalURLSpan extends android.text.style.ClickableSpan {
View.OnClickListener mListener;
public InternalURLSpan(View.OnClickListener listener) {
mListener = listener;
}
#Override
public void onClick(View widget) {
mListener.onClick(widget);
TextView tv = (TextView) widget;
System.out.println("tv.gettext() :: " + tv.getText());
Toast.makeText(MyActivity.this,tv.getText(),
Toast.LENGTH_SHORT).show();
}
}
Is it possible to get the text of the link clicked?
If not, is there a way of associating some data to a particular link and knowing which link gets clicked?
Any pointers.
Thanks
The solution goes like this -
Call setLinks() with you textview and the text to be added.
setLinks(textView, text);
setLinks() function is as -
void setLinks(TextView tv, String text) {
String[] linkPatterns = {
"([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])",
"#[\\w]+", "#[\\w]+" };
for (String str : linkPatterns) {
Pattern pattern = Pattern.compile(str);
Matcher matcher = pattern.matcher(tv.getText());
while (matcher.find()) {
int x = matcher.start();
int y = matcher.end();
final android.text.SpannableString f = new android.text.SpannableString(
tv.getText());
InternalURLSpan span = new InternalURLSpan();
span.text = text.substring(x, y);
f.setSpan(span, x, y,
android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(f);
// tv.setOnLongClickListener(span.l);
}
}
tv.setLinkTextColor(Color.BLUE);
tv.setLinksClickable(true);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setFocusable(false);
}
and the InternalURLSpan class goes like this -
class InternalURLSpan extends android.text.style.ClickableSpan {
public String text;
#Override
public void onClick(View widget) {
handleLinkClicked(text);
}
}
handleLinkClicked() is as -
public void handleLinkClicked(String value) {
if (value.startsWith("http")) { // handle http links
} else if (value.startsWith("#")) { // handle #links
} else if (value.startsWith("#")) { // handle #links
}
}
Here is a pretty simple solution I found to get the value of the link inside the TextView when the user clicks on it. In this case I'm using phone numbers and it works like a charm.
myTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(myTextView.getSelectionStart()== -1 &&
myTextView.getSelectionEnd() == -1){
Toast.makeText(getApplicationContext(), "You clicked outside the link",
Toast.LENGTH_SHORT).show();
}
else {
int start = myTextView.getSelectionStart();
int end = myTextView.getSelectionEnd();
String selected = myTextView.getText().toString().substring(start, end);
Toast.makeText(getApplicationContext(),
"Clicked: " + selected,
Toast.LENGTH_SHORT).show();
}
}
});
Hope it helps.
Use
android:linksClickable="true"
android:autoLink="web"
textView.setMovementMethod(LinkMovementMethod.getInstance())