How to make a clickable link in TextView.seterror() - android

Hi everyone.
I'd like to add a clickable url in the errormsg shown by using TextView.setError(msg) method.
please take a look on my code.
final EditText testview = findViewById(R.id.testview);
final TextView textView = findViewById(R.id.testtextview);
Button btntest = findViewById(R.id.testbutton);
btntest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
testview.setMovementMethod(new LinkMovementMethod());
testview.setError(Html.fromHtml("testurl click me "));
LayoutInflater inflater = LayoutInflater.from(testview.getContext());
TextView err = (TextView) inflater.inflate(
Resources.getSystem().getIdentifier("textview_hint","layout", "android"), null);
err.setMovementMethod(LinkMovementMethod.getInstance());
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(Html.fromHtml("testurl click me "));
textView.setError(Html.fromHtml("testurl click me "));
inflater = LayoutInflater.from(textView.getContext());
err = (TextView) inflater.inflate(
Resources.getSystem().getIdentifier("textview_hint","layout", "android"), null);
err.setMovementMethod(LinkMovementMethod.getInstance());
}
});
I have tried to setMovementMethod() on the specific TextView, which shows the errormsg, but the "click me" seems remain unclickable.
Thanks again.

If you can call setMovementMethod on error textview then this solution is perfect
final EditText testview = findViewById(R.id.editText);
final TextView textView = findViewById(R.id.testtextview);
Button btntest = findViewById(R.id.testbutton);
SpannableStringBuilder ssb = new SpannableStringBuilder(Html.fromHtml("testurl click me "));
URLSpan[] urlSpans = ssb.getSpans(0,ssb.length(),URLSpan.class);
int start = ssb.getSpanStart(urlSpans[0]);
int end = ssb.getSpanEnd(urlSpans[0]);
testview.setMovementMethod(LinkMovementMethod.getInstance());
ClickableSpan span = new ClickableSpan() {
#Override
public void onClick(#NonNull View view) {
Log.d("Cust","C");
}
};
ssb.setSpan(span,start,end,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
//testview.setError(span.toString());
testview.setError(ssb);

Related

Text out of text view

I am currently having a problem with Android application. I am using a table layout with some views in it. The problem is that it seems like the TextView does not wraps the text correctly. However, when I change swipe between fragments it just resizes and it fits as how its supposed to.
This is what is looks like in the first place when the onCreate function is called.
And this is how it looks when I swipe between fragments.
This is the method I used to set up the views inside the table.
private void initializeBookTable(final List<Book> bookList, View view, final Button modifyBtn, final Button deleteBtn)
{
//Get screen width
DisplayMetrics displaymetrics = new DisplayMetrics();
((Activity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
TableLayout table = view.findViewById(R.id.book_tableLayout);
//Border for the text views
final GradientDrawable gd = new GradientDrawable();
gd.setColor(getResources().getColor(R.color.colorTeal));
gd.setCornerRadius(2);
gd.setStroke(2, 0xFF000000);
//Font for the text views
Typeface font = Typeface.create("casual",Typeface.BOLD);
//Header row
TableRow headerRow = new TableRow(this.getContext());
TableLayout.LayoutParams headerRowParams = new TableLayout.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT);
headerRowParams.setMargins(0,1,0,0);
headerRow.setLayoutParams(headerRowParams);
//Header name text view
TextView headerName = new TextView(this.getContext());
headerName.setText(getResources().getString(R.string.book_NAME));
headerName.setBackground(gd);
headerName.setPadding(20,0,20,0);
headerName.setTypeface(font);
headerName.setTextColor(Color.BLACK);
headerName.setMinWidth(screenWidth/4);
headerRow.addView(headerName);
//Header chapter text view
TextView headerChapter = new TextView(this.getContext());
headerChapter.setText(getResources().getString(R.string.book_CHAPTER));
headerChapter.setBackground(gd);
headerChapter.setPadding(20,0,20,0);
headerChapter.setTypeface(font);
headerChapter.setTextColor(Color.BLACK);
headerChapter.setMinWidth(screenWidth/4);
headerRow.addView(headerChapter);
//Header page text view
TextView headerPage = new TextView(this.getContext());
headerPage.setText(getResources().getString(R.string.book_PAGE));
headerPage.setBackground(gd);
headerPage.setPadding(20,0,20,0);
headerPage.setTypeface(font);
headerPage.setTextColor(Color.BLACK);
headerPage.setMinWidth(screenWidth/4);
headerRow.addView(headerPage);
//Header name text view
TextView headerStatus = new TextView(this.getContext());
headerStatus.setText(getResources().getString(R.string.book_STATUS));
headerStatus.setBackground(gd);
headerStatus.setPadding(20,0,20,0);
headerStatus.setTypeface(font);
headerStatus.setTextColor(Color.BLACK);
headerStatus.setMinWidth(screenWidth/4);
headerRow.addView(headerStatus);
//Add row to table
table.addView(headerRow);
for(int i = 0; i < bookList.size(); i++)
{
TableRow row = new TableRow(this.getContext());
//Set text views parameters
TableRow.LayoutParams textViewParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
textViewParams.setMargins(0,1,0,1);
row.setLayoutParams(textViewParams);
//Set text views parameters
TextView name = new TextView(this.getContext());
name.setText(bookList.get(i).getName());
name.setBackground(gd);
name.setPadding(20,0,20,0);
name.setLayoutParams(textViewParams);
TextView chapter = new TextView(this.getContext());
chapter.setText(bookList.get(i).getChapter());
chapter.setBackground(gd);
chapter.setPadding(20,0,20,0);
chapter.setLayoutParams(textViewParams);
TextView page = new TextView(this.getContext());
page.setText(bookList.get(i).getPage());
page.setBackground(gd);
page.setPadding(20,0,20,0);
page.setLayoutParams(textViewParams);
TextView status = new TextView(this.getContext());
status.setText(bookList.get(i).getStatus());
status.setBackground(gd);
status.setPadding(20,0,20,0);
status.setLayoutParams(textViewParams);
//Add text views to the row
row.addView(name);
row.addView(chapter);
row.addView(page);
row.addView(status);
row.setClickable(true);
//Click listener for each row
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TableRow tableRow = (TableRow) view;
selectedRow = tableRow;
//If the row is already selected (in red) deselect it
TextView textViewCheck = (TextView) tableRow.getChildAt(0);
if(selection && textViewCheck.getText().toString().equals(selectedBook.getName()))
{
for(int i = 0; i < 4; i++)
{
TextView textView = (TextView) tableRow.getChildAt(i);
textView.setBackground(gd);
}
//Disable add and modify buttons when row is deselected
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
selection = false;
selectedBook = null;
}
//If the row is not in red check if there is already a selected row
else
{
if(selection)
{
String message = "Please select only one";
Toast.makeText(getContext(), message, LENGTH_SHORT).show();
}
else
{
for(int i = 0; i < 4; i++)
{
TextView textView = (TextView) tableRow.getChildAt(i);
textView.setBackgroundColor(Color.RED);
}
//Enable add and modify buttons when row is selected
modifyBtn.setEnabled(true);
deleteBtn.setEnabled(true);
TextView nameView = (TextView) tableRow.getChildAt(0);
selectedBook = storage.findBook(nameView.getText().toString());
selection = true;
}
}
}
});
//Set row parameters
TableRow.LayoutParams tableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT);
tableRowParams.setMargins(0,1,0,1);
row.setLayoutParams(tableRowParams);
table.addView(row);
}
}
This is my onCreate
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.books_fragment,container,false);
storage = InternalStorage.getInstance(this.getContext());
final Button modifyBtn = view.findViewById(R.id.modifyBtn);
final Button deleteBtn = view.findViewById(R.id.deleteBtn);
//Disable modify and delete buttons
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
this.initializeBookTable(storage.getBookList(),view, modifyBtn, deleteBtn);
Button addBtn = view.findViewById(R.id.addBtn);
addBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivity(), AddModifyBook.class);
startActivity(intent);
}
});
modifyBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
Intent intent = new Intent(getActivity(), AddModifyBook.class);
//Passing the selected book to the AddModifyBook activity
intent.putExtra("selectedBook",selectedBook);
startActivity(intent);
selectedBook = null;
selection = false;
}
});
final TableLayout table = view.findViewById(R.id.book_tableLayout);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
storage.removeBook(selectedBook);
selectedBook = null;
selection = false;
modifyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
table.removeView(selectedRow);
}
});
return view;
}
And for onResume I have the default.
Another thing that is happening is that if I just set the background of the name (the first column) with the gradient drawable gd then it works but If I set the rest background of the rest of the columns then I have the problem that I have already explained.
So apparently I have managed to solve the issue by using a gradient drawable for the name and a different gradient drawable for the other properties.

How to save user input from Alert Dialog?

I'm building an app that is supposed to take text entered from the user and place them into the textviews in a custom list item. The user enters the text into an AlertDialog but once the AlertDialog closes (hence destroyed), all the text entered is destroyed alongside with it and gives me a NullPointerException error.
This is code that handles the Dialog creation and data retrieving:
public class AssignmentActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_assignment);
...
FloatingActionButton assignmentAddButton = (FloatingActionButton) findViewById(R.id.assignment_add_button);
assignmentAddButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editCourseInfoDialog();
}
});
}
private void editCourseInfoDialog() {
LayoutInflater inflater = LayoutInflater.from(AssignmentActivity.this);
View dialogLayout = inflater.inflate(R.layout.assignment_edit_dialog, null);
AlertDialog.Builder dialog = new AlertDialog.Builder(AssignmentActivity.this);
dialog.setView(dialogLayout);
final TextView name = (TextView) dialogLayout.findViewById(R.id.assignmentNameView);
final TextView mark = (TextView) dialogLayout.findViewById(R.id.assignmentMarkView);
final TextView overallMark = (TextView) dialogLayout.findViewById(R.id.assignmentOverallMarkView);
final TextView weight = (TextView) dialogLayout.findViewById(R.id.assignmentWeightView);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
assignment.setName(String.valueOf(name.getText()));
assignment.setMark(Double.valueOf(mark.getText() + ""));
assignment.setMarkOutOf(Double.valueOf(overallMark.getText() + ""));
assignment.setPercentage(Double.valueOf(weight.getText() + ""));
assignmentAdapter.notifyDataSetChanged();
dialog.dismiss();
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
}
The issue with your initialization.
LayoutInflater inflater = LayoutInflater.from(AssignmentActivity.this);
View dialogLayout = inflater.inflate(R.layout.assignment_edit_dialog, null);
AlertDialog.Builder dialog = new AlertDialog.Builder(AssignmentActivity.this);
dialog.setView(dialogLayout);
final TextView name = (TextView) dialogLayout .findViewById(R.id.assignmentNameView);
final TextView mark = (TextView) dialogLayout .findViewById(R.id.assignmentMarkView);
final TextView overallMark = (TextView) dialogLayout .findViewById(R.id.assignmentOverallMarkView);
final TextView weight = (TextView) dialogLayout .findViewById(R.id.assignmentWeightView);
As you said TextViews are hooked up with AlertDialog custom view then they view context should be of Dialog view.
You have a lot to learn in terms of concept. You are setting adapter before initializing your list.
assignmentAdapter = new AssignmentListAdapter(assignmentList, this); // at this line **assignmentList** is null as you initiliaze after this line
assignment = new Assignment(this);
You must initialize first like this
assignment = new Assignment(this);
assignmentAdapter = new AssignmentListAdapter(assignmentList, this);

Android ArrayAdapter gives newly scrolled item

I have an ArrayAdapter which shows some posts using a fragment. In this fragment I have some buttons. So all of the posts shown have these buttons.
The problem is, when I click a button of a post to setText to a field of this post; instead of changing text of post that I clicked, it changes text of newly scrolled item.
For example if I scroll down the ListView a new item comes. Then regardless of which post I clicked it changes text of this new post.
How can I prevent this to happen? I take current post using
getItem(position)
By scroolling I mean new element of the list are loaded and shown.
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.comment_small,parent,false);
TextView tvOwner = (TextView) v.findViewById(R.id.tvCommentSmallOwner);
TextView tvCreationDate = (TextView) v.findViewById(R.id.tvCommentSmallCreationDate);
TextView tvCreationDateValue = (TextView) v.findViewById(R.id.tvCommentSmallCreationDate);
TextView tvContent = (TextView) v.findViewById(R.id.tvCommentSmallContent);
tvVoteCount = (TextView) v.findViewById(R.id.tvCommentVoteCount);
c = getItem(position);
tvOwner.setText(context.getResources().getString(R.string.generic_by) + " " + c.getOwnerId());
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String s =c.getPostDate();
System.out.println(s);
tvCreationDateValue.setText(s);
tvContent.setText(c.getContent());
btnDownVote = (ImageButton) v.findViewById(R.id.btnCommentDownVote);
btnUpVote = (ImageButton) v.findViewById(R.id.btnCommentUpVote);
tvVoteCount.setText("" + c.getNetCount());
btnUpVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
c=getItem(position);
ServerRequests sr = new ServerRequests(getContext());
MemberLocalStore memberLocalStore = new MemberLocalStore(getContext());
Member m = memberLocalStore.getLoggedInMember();
sr.voteComment(c, true, m.getId(), new Consumer<String>() {
#Override
public void accept(String vote) {
tvVoteCount.setText("" + vote);
}
});
}
});
btnDownVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
c=getItem(position);
ServerRequests sr = new ServerRequests(getContext());
MemberLocalStore memberLocalStore = new MemberLocalStore(getContext());
Member m = memberLocalStore.getLoggedInMember();
sr.voteComment(c, false, m.getId(), new Consumer<String>() {
#Override
public void accept(String vote) {
tvVoteCount.setText("" + vote);
}
});
}
});
return v;
}
I want to vote (like,dislike) some posts but when I click upvote button that marked as 1, overall vote of the post that marked as 2 changes.

Approach to get values of a dynamically generated textView

I successfully created a dynamic TextView and a Button now when ever the button was clicked the value of a TextView changes.
But the problem is I have a final "submit button" outside a loop which should get the INDIVIDUAL values of each TextView and I cant think of a way how to do it can someone pls give me an approach for this thanks!. pls be nice..
code
Cursor citem= sdb.rawQuery("SELECT * FROM ITEM INNER JOIN CATEGORY ON item.categoryid = category.id where category.categoryname='"+fcat+"'", null);
ScrollView scrollView= new ScrollView(this);
LinearLayout mainLayout= new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
Button border = new Button(this);
border.setId(Integer.parseInt(cuser.getString(cuser.getColumnIndex("id"))));;
border.setText("ORDER");
while (citem.moveToNext())
{
byte[] blob =citem.getBlob(citem.getColumnIndex("itemimage"));
int id = Integer.parseInt(citem.getString(citem.getColumnIndex("id")));
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setTag(id);
int i;
ImageView iv = new ImageView(this);
iv.setId(id);
iv.setImageBitmap(dh.getPhoto(blob));
final TextView txtquantity = new TextView(this);
txtquantity.setId(id);
txtquantity.setText("0");
txtquantity.setTextSize(20);
final TextView txtprice = new TextView(this);
txtprice.setId(id);
txtprice.setText(citem.getString(citem.getColumnIndex("itemprice")));
txtprice.setTextSize(30);
ImageButton btn1 = new ImageButton(this);
btn1.setId(id);
final int id_ = btn1.getId();
btn1.setImageResource(R.drawable.ic_launcher);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int i = 0;
i=Integer.parseInt((String) txtquantity.getText())+1;
txtquantity.setText(String.valueOf(i));
totalprice.setText(String.valueOf(Integer.parseInt(totalprice.getText().toString())+(Integer.parseInt(txtprice.getText().toString())*1)));
}
});
ImageButton btn2 = new ImageButton(this);
btn2.setId(id);
final int id2_ = btn2.getId();
btn2.setImageResource(R.drawable.ic_launcher);
btn2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(Integer.parseInt((String)txtquantity.getText())<=0)
{
}
else
{
int i=0;
i= Integer.parseInt((String) txtquantity.getText())-1;
txtquantity.setText(String.valueOf(i));
totalprice.setText(String.valueOf(Integer.parseInt(totalprice.getText().toString())-(Integer.parseInt(txtprice.getText().toString())*1)));
}
}
});
linearLayout.addView(iv);
linearLayout.addView(txtprice);
linearLayout.addView(btn1);
linearLayout.addView(txtquantity);
linearLayout.addView(btn2);
mainLayout.addView(linearLayout);
}
mainLayout.addView(totalprice);
mainLayout.addView(border);
scrollView.addView(mainLayout);
setContentView(scrollView);
Not quite sure what problem you're having? If it's just reading all the TextViews you created in the loop, then you should just keep a list, and send it off for processing when you submit...
List<TextView> tv_list = new ArrayList<TextView>();
while(...){
//In loop..add your tv's
TextView some_tv = new TextView()
tv_list.add(some_tv);
...
}
//In the submit, send them off for processing...
private void process_tvs(List<TextView> tv_list){
for(TextView tv:tv_list){
//Assuming your tv's have numbers...
int val = Integer.valueOf(tv.getText().toString());
//do something....
}
}

setOnClickListener scope on dynamic added elements

I am adding programatically and dynamically some elements (buttons and text views) with android. I also need to set the setOnClickListener event for each of these buttons and from that event execute some action on the click of button:
do
{
EditText txt1 = new EditText(this);
EditText txt2 = new EditText(this);
Button showtxt = new Button(this);
linearLayout.addView(showtxt );
linearLayout.addView(txt1);
linearLayout.addView(txt2);
showtxt.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
String aaa= txt1 .getText().toString();//HOW TO ACCESS txt1 and txt2 from here
String bbb= txt2 .getText().toString();
}
}
}
while(somecondition)
I am almost new to android. How can I access to txt1 and txt2 in the click callback function?
You need to make the define the variables where they will have class wide scope:
public class Example extends Activity {
EditText txt1;
EditText txt2;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
txt1 = new EditText(this);
txt2 = new EditText(this);
...
Now your onClick function will be able to see txt1 and txt2.
Alternatively
Since you appear to be creating a lot of txt1 and txt2 in one LinearLayout, you can pass your Button a reference to its EditTexts:
do {
...
// EditText[] array = { txt1, txt2 };
// is the short version of
EditText[] array = new EditText[2];
array[0] = txt1;
array[1] = txt2;
showtxt.setTag(array);
showtxt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EditText[] array = (EditText[]) v.getTag();
String aaa = array[0].getText().toString();
String bbb = array[1].getText().toString();
Log.v("Example", aaa + " " + bbb);
}
});
} while(some condition)
This may not be not ideal, however without any further context I cannot guess your ultimate goal. Hope that helps!
Last Suggestion
If we call the Button and two EditTexts a row, you could store each row in a ViewGroup or View of its own. Say you wanted to have background colors for each row:
View row = new View(this); // or this could be another LinearLayout
row.setBackgroundColor(0x0000ff);
// Create and add the Button and EditTexts to row, as in row.addView(showtxt), etc
...
linearLayout.addView(row);
showtxt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
View row = v.getParent()
String aaa = ((EditText) row.getChildAt(1)).getText().toString();
String bbb = ((EditText) row.getChildAt(2)).getText().toString();
Log.v("Example", aaa + " " + bbb);
}
});

Categories

Resources