I've an ArrayList containing Cards. I'm trying to edit a Cards tag in the ArrayList and after editingit I want the ListView to refresh, so the user can see the updated Card, with the new tag.
I'm using cardslib for my Cards. And I'm using Android TagView Lib to tag my cards.
Here's the XML for the Card
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/colorBorder"
android:layout_width="10dp"
android:layout_height="#dimen/card_base_empty_height"
android:layout_marginTop="2dp"
android:background="#drawable/rectangle" />
<TextView
(...) />
<TextView
(...) />
<TextView
(...) />
<TextView
(...) />
<pl.charmas.android.tagview.TagView
android:id="#+id/tags_view"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="#id/card_main_inner_simple_total_contacts"
android:layout_marginLeft="10dp"
android:layout_alignParentRight="true"
android:textSize="12sp"/>
</RelativeLayout>
And here's when I try to edit and update the list view:
private final OnClickCardHeaderPopupMenuListener popupMenuListener = new OnClickCardHeaderPopupMenuListener() {
#Override
public void onMenuItemClick(BaseCard baseCard, MenuItem menuItem) {
final String backupId = baseCard.getId();
switch (menuItem.getItemId()) {
case R.id.action_restore:
BackupsIntentService.restoreCloudBackup(getActivity(), backupId);
Log.d(TAG, "Going to update the card");
setCurrentTask(backupId, "Restoring...", "");
break;
case R.id.action_download:
BackupsIntentService.downloadCloudBackup(getActivity(), backupId);
break;
case R.id.action_delete:
BackupsIntentService.removeCloudBackup(getActivity(), backupId);
break;
}
}
};
And here's the setCurrentTask method, where I update and refresh the list:
private void setCurrentTask(final String backupId, final String currentTaskDescription, final String separator)
{
int pos = -1;
for(int i = 0; i<cloudBackupCardList.size(); i++)
{
BackupCard backupCard = (BackupCard) cloudBackupCardList.get(i);
if(backupCard.getId().equals(backupId))
{
pos = i;
Log.d(TAG, "Found the card at position: " + i + " updating it now");
TagView.Tag[] tags = {new TagView.Tag(currentTaskDescription, Color.BLUE)};
backupCard.setCurrentTaskDescription(tags, separator);
}
}
if(pos == -1)
return;
BackupCard backupCard = (BackupCard) cloudBackupCardList.get(pos);
Log.d(TAG, "There should be: " + currentTaskDescription + " but found: " + backupCard.getCurrentTaskDescription() + " Thread: " + Thread.currentThread()
.getName());
cardListView.setAdapter(new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
// remoteCardArrayMultiChoiceAdapter.remove(remoteCardArrayMultiChoiceAdapter.getItem(pos));
// remoteCardArrayMultiChoiceAdapter.insert(backupCard, pos);
//
//// remoteCardArrayMultiChoiceAdapter.clear();
//// remoteCardArrayMultiChoiceAdapter.addAll(cloudBackupCardList);
// remoteCardArrayMultiChoiceAdapter.notifyDataSetChanged();
// cardListView.refreshDrawableState();
}
I've tried all those (the commented ones) different methods and the list is still not updated.
Here's my logcat output:
07-07 15:12:59.644: D/CardCloudBackupsFragment(24311): Going to update the card
07-07 15:12:59.644: D/CardCloudBackupsFragment(24311): Found the card at position: 8 updating it now
07-07 15:12:59.656: D/CardCloudBackupsFragment(24311): There should be: Restoring... but found: RESTORING... ThreaD: main
As you can see from the logcat, the object is updated but in the listview, on my terminal, it is not. Which leads me to conclude that the listview is not updated/refreshed. (Dont mind the all upper case letters in Restoring, it's expected.)
////////////////////// EDIT ////////////////////////////////
Here is my setupInnerViewElements method as requested in the comments box.
#Override
public void setupInnerViewElements(ViewGroup parent, View view) {
//Retrieve elements
titleTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_title);
subTitleTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_sub_title);
TextView descriptionTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_description);
TextView totalContactsTextView = (TextView) parent.findViewById(R.id.card_main_inner_simple_total_contacts);
tagView = (TagView) parent.findViewById(R.id.tags_view);
if(isLocal)
{
if (titleTextView != null)
titleTextView.setText(TIMESTAMP_TXT + titleCard); // 1st
if (subTitleTextView != null)
subTitleTextView.setText(CONTACTS_COUNT_TXT + subTitleCard); // 2nd
if(descriptionTextView != null)
descriptionTextView.setText(RESTORE_COUNT_TXT + description); // 3rd
if(tagView != null)
{
TagView.Tag[] tags = {new TagView.Tag("Wow", Color.TRANSPARENT)};
tagView.setTags( tags, "" );
}
return;
}
if (titleTextView != null)
titleTextView.setText(TIMESTAMP_TXT + titleCard); // 1st
if (subTitleTextView != null)
subTitleTextView.setText(PHONE_BRAND_TXT + subTitleCard); // 2nd
if(descriptionTextView != null)
descriptionTextView.setText(PHONE_MODEL_TXT + description); // 3rd
if(totalContactsTextView != null)
totalContactsTextView.setText(CONTACTS_COUNT_TXT + contactsNumber); // 4th
if(tagView != null)
{
TagView.Tag[] tags = {new TagView.Tag("Wow", Color.TRANSPARENT)};
tagView.setTags( tags, "" );
}
}
Replace below Line:
cardListView.setAdapter(new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
with
RemoteCardArrayMultiChoiceAdapter adapter=new RemoteCardArrayMultiChoiceAdapter(getActivity(), cloudBackupCardList));
cardListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
Thats it...
The problem was a no problem at all, it was as simply as setting the tag and the TagsLibrary would take care of updating the CardView. I just didn't know this so I was trying to refresh the listview.
So I simply have this method on my card class:
public void setCurrentTaskDescription(TagView.Tag[] tags, String separator)
{
tagView.setTags(tags, separator);
}
and then on my listener I just do this:
switch ( menuItem.getItemId()) {
case R.id.action_restore:
BackupsIntentService.restoreCloudBackup(getActivity(), backupId);
EventBus.getDefault().post(new
setCurrentTask(backupCard, "Restoring...", "");
break;
}
private void setCurrentTask(final BackupCard backupCard, final String currentTaskDescription, final String separator)
{
TagView.Tag[] tags = {new TagView.Tag(currentTaskDescription, Color.GREEN)};
backupCard.setCurrentTaskDescription(tags, separator);
}
No need to refresh the list!
I was trying to make a thunderstorm inside a glass of water. Lesson learned.
Related
This type of formatting i need i don't want to use \n or br because my string is dynamic and i want to fix any text in this this format
This is my first textview
This is my second
textview this
is my third
textview
You can do it programmatically using this function
val text = "This is my first text view this is my second textview this is my third textview"
textView.text = proxyWifi.textFormation(text)
copy/paste this code do your project :)
public String textFormation(String text){
String result = "";
String[] sentenceWords = text.split(" ");
List<String> newSentenceWords = new ArrayList<>();
textRec(sentenceWords, newSentenceWords, sentenceWords.length -1, 0, "");
int spacing = 0;
for(int i = newSentenceWords.size() -1 ; i >= 0 ; i--){
if(i == newSentenceWords.size() -1)
result = newSentenceWords.get(i);
else{
result += "\n";
spacing += (newSentenceWords.get(i + 1).length() - newSentenceWords.get(i).length())/2;
for(int j = 0 ; j < spacing ; j++){
result += " ";
}
result += newSentenceWords.get(i);
}
}
return result;
}
public void textRec(String[] words, List<String> newWords, int indexWords, int indexNewWords, String sentence){
Log.e("sentence", sentence);
if(indexWords >= 0){
if(indexNewWords == 0) {
newWords.add(words[indexWords]);
textRec(words, newWords, indexWords - 1, ++indexNewWords, "");
}else{
if(newWords.get(indexNewWords - 1).length() >= sentence.length())
if(sentence.isEmpty())
textRec(words, newWords, indexWords - 1, indexNewWords, words[indexWords]);
else
textRec(words, newWords, indexWords - 1, indexNewWords, words[indexWords] + " " + sentence);
else {
newWords.add(sentence);
textRec(words, newWords, indexWords , ++indexNewWords, "");
}
}
}else{
if(sentence.isEmpty()){
return;
}else{
newWords.set(indexNewWords - 1 ,sentence + " " + newWords.get(indexNewWords - 1)) ;
}
}
}
OUTPUT
There is no default implementation for this. Also, you can't find the line number to do this.
So you have to split the sentence into multi lines.Use \n for next line. Set gravity center to your textView.
if you use \n then your next line will be start from
This is my first textview
<here>
<not here>
So, basically you need multiple TextViews.
First devide your text String to multiple parts(Note:- (n+1)th part should be less than nth part and deff. should be both end space).
Second Create a LinearLayout with vertical orientation and center gravity.
Third loop on that array.
and in loop create a new textview with gravity center, and set the text to it.
and add this TV to linearLayout.
thats it.
I tried to give you result as you want
This may work
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:gravity="center"
tools:context="com.ap.mytestingapp.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/strTV"
android:text="hello world!"
android:gravity="center" />
</RelativeLayout>
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.strTV);
//pass string whatever you want to show
String apStr = printString("This is my first textview This is my second textview this is my third textview");
//you need to define text size according to your requirement
// I took here 25
tv.setTextSize(25);
tv.setText(apStr);
}
private String printString(String responseString) {
String str = responseString;
String resultStr = "";
//you need to define cutLength Value according to your textView's textSize
// I took it 35 when textView's textSize is 25
int cutLength = 35;
int count = 0;
int from = 0;
for(int i = 0 ; i < str.length(); i++){
//increment of count
count++;
//check count value with cutLength so that we can add \n to string
if(count == cutLength){
// adding \n to substring
resultStr = resultStr + str.substring(from, i) + "\n";
// assigning from = i
from = i;
// reduce cutLength value
cutLength = cutLength-10;
// assigning count = 0
count = 0;
} else if(i == str.length()-1){
// adding \n to substring
resultStr = resultStr + str.substring(from) + "\n";
}
}
//return resulting string
return resultStr;
}
}
I am working on app where i use Urdu Custom Keyboard its work fine but the problem is that when i type any-word e.g. (سلام), cursor become not works at mid character for example cut/copy/paste or deleting (ا) character from the mid from word are not work.
i uses rough technique just appending characters but is also work fine.
For taping any alphabetic
private void addText(View v) {
// String b = "";
// b = (String) v.getTag();
// urdu_word.setText(b);
if (isEdit == true) {
String b = "";
b = (String) v.getTag();
if (b != null) {
Log.i("buttonsOnclick", b);
// adding text in Edittext
mEt.append(b);
}
}
}
For back button tapping
private void isBack(View v) {
if (isEdit == true) {
CharSequence cc = mEt.getText();
if (cc != null && cc.length() > 0) {
{
mEt.setText("");
mEt.append(cc.subSequence(0, cc.length() - 1));
}
}
}
}
Here the screenshot clear my problem to you people
I used a lot of library and code from github but don't catch good idea
1) Keyboard-1
2) Keyboard-2
3) Keyboard-3
4) Keyboard-4
i checked all these keyboard and more from libs, have same cursor issue, how to manage fully my custom keyboard by deleting character from mid and copy my written text copy paste like normal keyboard with EditText, thanks in advance all of you :)
Thanks God i solved my issue using simple logic.
For back button
private void isBack(View v) {
// char[] tempChar = null;
if ((mEt.getText().toString().length() > 0)) {
int temp = mEt.getSelectionEnd() - 1;
if (temp >= 0) {
mEt.setText((mEt.getText().toString()
.substring(0, mEt.getSelectionEnd() - 1).concat(mEt
.getText()
.toString()
.substring(mEt.getSelectionEnd(),
mEt.getText().length()))));
mEt.setSelection(temp);
}
}
}
For adding any character
private void addText(View v) {
int temp = mEt.getSelectionEnd();
if (temp >= 0) {
String b = "";
b = (String) v.getTag();
mEt.setText((mEt.getText().toString()
.substring(0, mEt.getSelectionEnd()) + b.concat(mEt
.getText().toString()
.substring(mEt.getSelectionEnd(), mEt.getText().length()))));
mEt.setSelection(temp + 1);
}
}
for copy paste i added few lines code to EditText
<EditText
android:id="#+id/xEt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#drawable/edittextshape"
android:ems="10"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="top"
android:imeOptions="actionDone"
android:padding="15dp"
android:singleLine="false"
android:visibility="visible" />
I am developing a android App where i have to show my data on customize alert dialog from data base. This is my database
I am trying to show all these data on alert-dialog a by follwing code
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "Position " + position);
int _id = 0;
int type = getItemViewType(position);
OrderViewHolder orderViewHolder = null;
if (convertView == null) {
orderViewHolder = new OrderViewHolder();
switch (type) {
case TYPE_STATUS:
convertView = inflater.inflate(R.layout.category_header, null);
orderViewHolder.setTvTitle((TextView) convertView
.findViewById(R.id.category));
break;
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.order_list_row, null);
orderViewHolder.setTvTitle((TextView) convertView
.findViewById(R.id.orderTitle));
orderViewHolder.setTvPrice((TextView) convertView
.findViewById(R.id.orderPrice));
orderViewHolder.setIvDelete((ImageButton) convertView
.findViewById(R.id.deleteOrder));
// orderViewHolder.setIvDelete((ImageButton)convertView.findViewById(R.id.deleteOrder).setLayoutParams(params))
break;
}
convertView.setTag(orderViewHolder);
} else {
orderViewHolder = (OrderViewHolder) convertView.getTag();
}
if (position == 0) {
if (starterCount != 0) {
orderViewHolder.getTvTitle().setText("");
// orderViewHolder.getTvTitle().setBackgroundDrawable(R.drawable.tab_starters_menu_on);
orderViewHolder.getTvTitle().setTextColor(R.color.Black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT_BOLD);
orderViewHolder.getTvTitle().setBackgroundResource(R.drawable.tt111);
orderViewHolder.getTvTitle().setHeight(20);
orderViewHolder.getTvTitle().setWidth(100);
/*
* RestaurantHome.setFontTextViewTahoma(OrderListAdapter,
* orderViewHolder.getTvTitle());
*/
}
else {
orderViewHolder.getTvTitle().setText(" ");
orderViewHolder.getTvTitle().setBackgroundColor(Color.WHITE);
}
}
if ((position !=0))
{
System.out.println(" position vlue : "+position);
if (oStarterCursor.moveToPosition(position-1)) {
String title = oStarterCursor.getString(oStarterCursor.getColumnIndex("item_name"));
System.out.println( " value of title "+title);
String price = oStarterCursor.getString(oStarterCursor.getColumnIndex("Item_cost"));
System.out.println( " value of price "+price);
_id = oStarterCursor.getInt(oStarterCursor
.getColumnIndex("_id"));
if (title != null) {
title = title.trim();
orderViewHolder.getTvTitle().setText(title);
orderViewHolder.getTvTitle().setTextColor(R.color.black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT);
orderViewHolder.getTvTitle().setGravity(Gravity.CENTER_VERTICAL);
}
if (price != null) {
price = price.trim();
orderViewHolder.getTvPrice().setText(price + ".00");
orderViewHolder.getTvTitle().setTextColor(R.color.black);
orderViewHolder.getTvTitle().setTextSize(12);
orderViewHolder.getTvTitle().setTypeface(Typeface.DEFAULT);
orderViewHolder.getTvTitle().setGravity(Gravity.CENTER_VERTICAL);
}
_id = oStarterCursor.getInt(oStarterCursor.getColumnIndex("_id"));
}
convertView.setTag(R.id.orderTitle, _id);
if (orderViewHolder.getIvDelete() != null) {
orderViewHolder.getIvDelete().setTag(R.id.orderTitle, _id);
}
// _id =
// oStarterCursor.getInt(oStarterCursor.getColumnIndex("_id"));
}
//}
return convertView;}
I am going to post my order_list_row.xml file.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100sp"
android:layout_height="fill_parent"
android:background="#fff" >
<ImageButton
android:id="#+id/deleteOrder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp"
android:background="#fff"
android:onClick="clickHandler"
android:src="#drawable/icon_close" >
</ImageButton>
<TextView
android:id="#+id/orderTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_margin="4sp"
android:background="#fff"
android:textColor="#000"
android:textSize="16dp" >
</TextView>
<TextView
android:id="#+id/orderPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4sp"
android:layout_toLeftOf="#id/deleteOrder"
android:layout_toRightOf="#id/orderTitle"
android:background="#fff"
android:textColor="#000"
android:textSize="16dp" >
</TextView>
</RelativeLayout>
But it is not showing my last data in my database.
As you can see by my screen shot last data is not showing form database. Why fanta is not showing ? Always last row is showing in alertdialog from database.What is logical issue in my code i can't understand ? Most probably it is mistake of my logic but where it is i can't find . I hope i am able to explain my problem to all my well-wisher . Please help me . Thanks in advance to all
i would like to know why are u passing position -1 as param to movetoPosition method
just pass position ..
i think according to your approach last element is never being read !!
Finally i solve my issue. Thanks to all who suggest me to solve this issue.
public int getCount() {
// TODO Auto-generated method stub
Log.d(TAG, "GetCount "+starterCount);
return starterCount +1 ;
}
And
if ((position !=0)&& (position != starterCount + 1))
{
// TODO Auto-generated method stub
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
http://www.itechcode.com/2012/03/18/create-calculator-in-android-programming/
Im using his source code but it seems very different than the "Beginner Level" Programming I have been use to i.e. creating new project, modifying layout, referencing in main.java, etc.
I'm trying to use his source code and modify/create new operations and maybe add a activity. I would usually know how to do most of that stuff if it wasn't laid out differently. Thank You!
package com.pragmatouch.calculator;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.Stack;
import android.app.Activity;
import android.os.Bundle;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.view.View;
import android.view.View.OnClickListener;
public class main extends Activity {
GridView mKeypadGrid;
TextView userInputText;
TextView memoryStatText;
Stack<String> mInputStack;
Stack<String> mOperationStack;
KeypadAdapter mKeypadAdapter;
TextView mStackText;
boolean resetInput = false;
boolean hasFinalResult = false;
String mDecimalSeperator;
double memoryValue = Double.NaN;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DecimalFormat currencyFormatter = (DecimalFormat) NumberFormat
.getInstance();
char decimalSeperator = currencyFormatter.getDecimalFormatSymbols()
.getDecimalSeparator();
mDecimalSeperator = Character.toString(decimalSeperator);
setContentView(R.layout.main);
// Create the stack
mInputStack = new Stack<String>();
mOperationStack = new Stack<String>();
// Get reference to the keypad button GridView
mKeypadGrid = (GridView) findViewById(R.id.grdButtons);
// Get reference to the user input TextView
userInputText = (TextView) findViewById(R.id.txtInput);
userInputText.setText("0");
memoryStatText = (TextView) findViewById(R.id.txtMemory);
memoryStatText.setText("");
mStackText = (TextView) findViewById(R.id.txtStack);
// Create Keypad Adapter
mKeypadAdapter = new KeypadAdapter(this);
// Set adapter of the keypad grid
mKeypadGrid.setAdapter(mKeypadAdapter);
// Set button click listener of the keypad adapter
mKeypadAdapter.setOnButtonClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Button btn = (Button) v;
// Get the KeypadButton value which is used to identify the
// keypad button from the Button's tag
KeypadButton keypadButton = (KeypadButton) btn.getTag();
// Process keypad button
ProcessKeypadInput(keypadButton);
}
});
mKeypadGrid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
}
});
}
private void ProcessKeypadInput(KeypadButton keypadButton) {
//Toast.makeText(this, keypadButton.getText(), Toast.LENGTH_SHORT).show();
String text = keypadButton.getText().toString();
String currentInput = userInputText.getText().toString();
int currentInputLen = currentInput.length();
String evalResult = null;
double userInputValue = Double.NaN;
switch (keypadButton) {
case BACKSPACE: // Handle backspace
// If has operand skip backspace
if (resetInput)
return;
int endIndex = currentInputLen - 1;
// There is one character at input so reset input to 0
if (endIndex < 1) {
userInputText.setText("0");
}
// Trim last character of the input text
else {
userInputText.setText(currentInput.subSequence(0, endIndex));
}
break;
case SIGN: // Handle -/+ sign
// input has text and is different than initial value 0
if (currentInputLen > 0 && currentInput != "0") {
// Already has (-) sign. Remove that sign
if (currentInput.charAt(0) == '-') {
userInputText.setText(currentInput.subSequence(1,
currentInputLen));
}
// Prepend (-) sign
else {
userInputText.setText("-" + currentInput.toString());
}
}
break;
case CE: // Handle clear input
userInputText.setText("0");
break;
case C: // Handle clear input and stack
userInputText.setText("0");
clearStacks();
break;
case DECIMAL_SEP: // Handle decimal seperator
if (hasFinalResult || resetInput) {
userInputText.setText("0" + mDecimalSeperator);
hasFinalResult = false;
resetInput = false;
} else if (currentInput.contains("."))
return;
else
userInputText.append(mDecimalSeperator);
break;
case DIV:
case PLUS:
case MINUS:
case MULTIPLY:
if (resetInput) {
mInputStack.pop();
mOperationStack.pop();
} else {
if (currentInput.charAt(0) == '-') {
mInputStack.add("(" + currentInput + ")");
} else {
mInputStack.add(currentInput);
}
mOperationStack.add(currentInput);
}
mInputStack.add(text);
mOperationStack.add(text);
dumpInputStack();
evalResult = evaluateResult(false);
if (evalResult != null)
userInputText.setText(evalResult);
resetInput = true;
break;
case CALCULATE:
if (mOperationStack.size() == 0)
break;
mOperationStack.add(currentInput);
evalResult = evaluateResult(true);
if (evalResult != null) {
clearStacks();
userInputText.setText(evalResult);
resetInput = false;
hasFinalResult = true;
}
break;
case M_ADD: // Add user input value to memory buffer
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
if (Double.isNaN(memoryValue))
memoryValue = 0;
memoryValue += userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
case M_REMOVE: // Subtract user input value to memory buffer
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
if (Double.isNaN(memoryValue))
memoryValue = 0;
memoryValue -= userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
case MC: // Reset memory buffer to 0
memoryValue = Double.NaN;
displayMemoryStat();
break;
case MR: // Read memoryBuffer value
if (Double.isNaN(memoryValue))
return;
userInputText.setText(doubleToString(memoryValue));
displayMemoryStat();
break;
case MS: // Set memoryBuffer value to user input
userInputValue = tryParseUserInput();
if (Double.isNaN(userInputValue))
return;
memoryValue = userInputValue;
displayMemoryStat();
hasFinalResult = true;
break;
case PRGM:
break;
default:
if (Character.isDigit(text.charAt(0))) {
if (currentInput.equals("0") || resetInput || hasFinalResult) {
userInputText.setText(text);
resetInput = false;
hasFinalResult = false;
} else {
userInputText.append(text);
resetInput = false;
}
}
break;
}
}
private void clearStacks() {
mInputStack.clear();
mOperationStack.clear();
mStackText.setText("");
}
private void dumpInputStack() {
Iterator<String> it = mInputStack.iterator();
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
CharSequence iValue = it.next();
sb.append(iValue);
}
mStackText.setText(sb.toString());
}
private String evaluateResult(boolean requestedByUser) {
if ((!requestedByUser && mOperationStack.size() != 4)
|| (requestedByUser && mOperationStack.size() != 3))
return null;
String left = mOperationStack.get(0);
String operator = mOperationStack.get(1);
String right = mOperationStack.get(2);
String tmp = null;
if (!requestedByUser)
tmp = mOperationStack.get(3);
double leftVal = Double.parseDouble(left.toString());
double rightVal = Double.parseDouble(right.toString());
double result = Double.NaN;
if (operator.equals(KeypadButton.DIV.getText())) {
result = leftVal / rightVal;
} else if (operator.equals(KeypadButton.MULTIPLY.getText())) {
result = leftVal * rightVal;
} else if (operator.equals(KeypadButton.PLUS.getText())) {
result = leftVal + rightVal;
} else if (operator.equals(KeypadButton.MINUS.getText())) {
result = leftVal - rightVal;
}
String resultStr = doubleToString(result);
if (resultStr == null)
return null;
mOperationStack.clear();
if (!requestedByUser) {
mOperationStack.add(resultStr);
mOperationStack.add(tmp);
}
return resultStr;
}
private String doubleToString(double value) {
if (Double.isNaN(value))
return null;
long longVal = (long) value;
if (longVal == value)
return Long.toString(longVal);
else
return Double.toString(value);
}
private double tryParseUserInput() {
String inputStr = userInputText.getText().toString();
double result = Double.NaN;
try {
result = Double.parseDouble(inputStr);
} catch (NumberFormatException nfe) {
}
return result;
}
private void displayMemoryStat() {
if (Double.isNaN(memoryValue)) {
memoryStatText.setText("");
} else {
memoryStatText.setText("M = " + doubleToString(memoryValue));
}
}
}
ENUM:
package com.pragmatouch.calculator;
public enum KeypadButton {
MC("MC",KeypadButtonCategory.MEMORYBUFFER)
, MR("MR",KeypadButtonCategory.MEMORYBUFFER)
, MS("MS",KeypadButtonCategory.MEMORYBUFFER)
, M_ADD("M+",KeypadButtonCategory.MEMORYBUFFER)
, M_REMOVE("M-",KeypadButtonCategory.MEMORYBUFFER)
, BACKSPACE("<-",KeypadButtonCategory.CLEAR)
, CE("CE",KeypadButtonCategory.CLEAR)
, C("C",KeypadButtonCategory.CLEAR)
, ZERO("0",KeypadButtonCategory.NUMBER)
, ONE("1",KeypadButtonCategory.NUMBER)
, TWO("2",KeypadButtonCategory.NUMBER)
, THREE("3",KeypadButtonCategory.NUMBER)
, FOUR("4",KeypadButtonCategory.NUMBER)
, FIVE("5",KeypadButtonCategory.NUMBER)
, SIX("6",KeypadButtonCategory.NUMBER)
, SEVEN("7",KeypadButtonCategory.NUMBER)
, EIGHT("8",KeypadButtonCategory.NUMBER)
, NINE("9",KeypadButtonCategory.NUMBER)
, PLUS(" + ",KeypadButtonCategory.OPERATOR)
, MINUS(" - ",KeypadButtonCategory.OPERATOR)
, MULTIPLY(" * ",KeypadButtonCategory.OPERATOR)
, DIV(" / ",KeypadButtonCategory.OPERATOR)
, RECIPROC("1/x",KeypadButtonCategory.OTHER)
, DECIMAL_SEP(",",KeypadButtonCategory.OTHER)
, SIGN("±",KeypadButtonCategory.OTHER)
, SQRT("SQRT",KeypadButtonCategory.OTHER)
, PERCENT("%",KeypadButtonCategory.OTHER)
, CALCULATE("=",KeypadButtonCategory.RESULT)
, PRGM("PRGM",KeypadButtonCategory.PRGM)
, DUMMY("",KeypadButtonCategory.DUMMY);
CharSequence mText; // Display Text
KeypadButtonCategory mCategory;
KeypadButton(CharSequence text,KeypadButtonCategory category) {
mText = text;
mCategory = category;
}
public CharSequence getText() {
return mText;
}
}
package com.pragmatouch.calculator;
public enum KeypadButtonCategory {
MEMORYBUFFER
, NUMBER
, OPERATOR
, DUMMY
, CLEAR
, RESULT
, OTHER
, PRGM
}
I have a great answer for you. I recently wanted to create my own button in android but I wanted to do it in a simple way. Follow these steps and in a few minutes I will post pictures.
1) create a new layout. start with a LinearLayout. Nest a FramedLayout and another LinearLayout inside of it.
2) then add a TextView to it. This is where practice makes perfect. Play around with the attributes. Learn what they do. when you have the general information of how you want your button to be display go to the next step.
3) what your are going to do is include this in another view as a button. You can use a specific attribute to make it look like a button as well.
Give me a few minutes and I will post some code and a picture.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/CBN_LinearLayout"
style="#android:style/Widget.Button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/CBV_texview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:gravity="right"
android:text="#string/checkorder"
android:textColor="#color/Black" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1" >
<ImageView
android:id="#+id/CBV_imageView1"
android:layout_width="23dp"
android:layout_height="15dp"
android:layout_gravity="center_vertical"
android:contentDescription="#string/redcirclenotify"
android:src="#drawable/rednotify"
android:visibility="visible" />
<TextView
android:id="#+id/CBV_textview2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:gravity="left"
android:text="#string/zero"
android:visibility="visible" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/CBV_textview3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:fadingEdge="horizontal"
android:gravity="center_horizontal"
android:text="#string/blankstring" />
<TextView
android:id="#+id/CBV_textview4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:text="#string/blankstring" />
</LinearLayout>
when you add it to another view as a button you use:
<include
android:id="#+id/MI_checkorder"
style="android:buttonStyle"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:layout_marginTop="5dp"
android:layout_weight="1"
layout="#layout/custombtnview"
android:background="#style/AppTheme"
android:clickable="true"
android:focusable="true" />
The important part of this is setting the Style for the root LinearLayout to #android:style/Widget.Button
Once this is done it will look like a button and work like a button.
Below is an image of the final product:
another part of your question. Adjust sizes of standard buttons in android:
1) almost everything can be controled with how you use the XML. This can all be controled in the area to right, in the ADK. These attributes help you to control almost every aspect.
for example as in the calculator...
you have 4 buttons in a row so you want to add 4 buttons inside of a horizontal LinearLayout. Then you can give the a weight of 1 for each button then set their Width to FillParent. This will auto size the buttons to be displayed in the width of the screen equally.
Am I better off making my own calc or modify the existing code?
I would never tell someone to recreate the wheel, however, if you do not understand the code well enough to pickup where they left off then this can be an uphill struggle for you. Your best bet if you are having trouble understanding the code given to you or how to modify it, would be to actually post the code in another question and be very specific and ask for example how can I change what this particular button displays and what the result of clicking it would be. This forum depends on the people asking the questions to be clear and concise. If not then questions will closed as fast as they are opened. Generalizations are severely frowned upon on the site.
In the end, what I am trying to do is make my own scientific calculator but I don't want to spend extra time doing the simple operations.
The best way to answer this is to take a look at how the calculator is assembled in the GUI or Graphical Layout. Try changing a button and what it does. for example make the plus a minus just for the learning curve.
1) look for , PLUS(" + ",KeypadButtonCategory.OPERATOR) and notice that is a string for plus. change it to " T " see if it changes in the app. If it does then go into the code. In the code you will find case CALCULATE: for for the = sign in the ENUM and then inside that you find evalResult = evaluateResult(true);. If you follow this you reach:
if (operator.equals(KeypadButton.DIV.getText())) {
result = leftVal / rightVal;
} else if (operator.equals(KeypadButton.MULTIPLY.getText())) {
result = leftVal * rightVal;
} else if (operator.equals(KeypadButton.PLUS.getText())) {
result = leftVal + rightVal;
} else if (operator.equals(KeypadButton.MINUS.getText())) {
result = leftVal - rightVal;
}
so now you can change result = leftVal + rightVal; to result = leftVal - rightVal; and you have just changed it. so it will take some time to understand the code but you have to do some trial and error to understand it. I hope this helps answer your question.
There is any way to define into XML layout longKeyLongPress definition like onClick does ?.
i.e this is my view
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:text="Line 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/message"
android:textSize="15dip"
android:textStyle="bold"
android:textColor="#color/colorblue"
android:shadowDy="1.0"
android:shadowDx="1.0"
android:shadowRadius="1.0"
android:shadowColor="#ffffffff"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="5dip"
android:lineSpacingExtra="3dip"
android:lineSpacingMultiplier="1.1"
android:singleLine="false"
android:autoLink="web|email|phone|map|all"
android:onClick="clickHandler"
android:clickable="true"
/>
I want something like before but reacting to longpress event.
Note:
I don't want to add listener from my code.
I tried with android:longClickable.
The attribute is not defined, however you can implement it.
Extend TextView and let's call it MyTextView.
Then add file attrs.xml in res/values/ with following content:
<xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<attr name="onKeyLongPress" format="string"/>
</declare-styleable>
</resources>
In MyTextView constructor add logic to read data from xml:
public MyTextView(final Context context, final AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
for (int i = 0; i < a.getIndexCount(); ++i)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.MyTextView_onKeyLongPress: {
if (context.isRestricted()) {
throw new IllegalStateException("The "+getClass().getCanonicalName()+":onKeyLongPress attribute cannot "
+ "be used within a restricted context");
}
final String handlerName = a.getString(attr);
if (handlerName != null) {
setOnLongClickListener(new OnLongClickListener() {
private Method mHandler;
#Override
public boolean onLongClick(final View p_v) {
boolean result = false;
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName, View.class);
} catch (NoSuchMethodException e) {
int id = getId();
String idText = id == NO_ID ? "" : " with id '"
+ getContext().getResources().getResourceEntryName(
id) + "'";
throw new IllegalStateException("Could not find a method " +
handlerName + "(View) in the activity "
+ getContext().getClass() + " for onKeyLongPress handler"
+ " on view " + MyTextView.this.getClass() + idText, e);
}
}
try {
mHandler.invoke(getContext(), MyTextView.this);
result = true;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not execute non "
+ "public method of the activity", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Could not execute "
+ "method of the activity", e);
}
return result;
}
});
}
break;
}
default:
break;
}
}
a.recycle();
}
Use new attribute in your layout xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<your.package.MyTextView
android:id="#+id/theId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:onKeyLongPress="myDoSomething"
/>
<!-- Other stuff -->
</LinearLayout>
Credits:
I have learned how to do this from this post: http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
Snippet for constructor with slight modifications was taken from original android View class.
Looking at the current documentation, such an XML parameter does not currently exist. The longClickable is a boolean parameter to define simply whether a View is responds to long clicks or not.
(10 years later, might be useful to others)
When using Databinding and MVVM you can write a Bindingadapter that works as intended:
#BindingAdapter("android:onLongClick")
fun setOnLongClickListener(view: View,block : () -> Unit) {
view.setOnLongClickListener {
block()
return#setOnLongClickListener true
}
}
You can then use it like: android:onLongClick="#{() -> vm.yourFunction()}"
You can also return the function and change Unit to boolean if you indend to return false in some cases