How to make phone calls programmatically in Android? - java

I have the following layout defined in useful_numbers_item_fragment.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/call_linear_layout">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/useful_nums_item_name"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/useful_nums_item_value"/>
</LinearLayout>
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="#drawable/call"
android:id="#+id/call_btn"
android:onClick="callNumber"/>
</LinearLayout>
I dynamically populate the two text views in a class called UNItemListFragment.java
in the onCreate method:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
if (getArguments().containsKey(Constants.UNItem.GROUP_ID)) {
simpleCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.useful_numbers_item_fragment, null,
new String[]{Constants.UNItem.NAME, Constants.UNItem.VALUE},
new int[]{R.id.useful_nums_item_name, R.id.useful_nums_item_value}, 0);
setListAdapter(simpleCursorAdapter);
getLoaderManager().initLoader(0, getArguments(), this);
}
}
For each number if i click on the button i want to make a phone call by
calling the callNumber method when the user clicks the button:
public void callNumber(View view) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
TextView unItemVal = (TextView) findViewById(R.id.useful_nums_item_value);
String phoneNumber = unItemVal.getText().toString();
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
}
It is ok when I click the first button in the list, but when I click on the other buttons
it continues calling the number defined in the first row...
Any idea how to resolve this?

The problem is that this line:
TextView unItemVal = (TextView) findViewById(R.id.useful_nums_item_value);
is executed on the activity, so the findViewById will always return the first item with that id, which is likely the first item in the list.
The best way to fix this would be to override the adapter and add a tag containing the phone number to the view. A quick way to fix this would be to tag along in the view hierarchy, like so:
public void callNumber(View view) {
if( view != null ) { // view is the button tapped
View parent = view.getParent(); // this should be the LinearLayout
if( parent instanceof LinearLayout ) {
TextView unItemVal = (TextView) ((LinearLayout)parent).findViewById(R.id.useful_nums_item_value);
if( unItemVal != null ) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
String phoneNumber = unItemVal.getText().toString();
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
}
}
}
}
This would find the parent for the button that was clicked, and then find the text-view containing the number within that ViewGroup.

Using findViewById() will return the first view in the activity or fragment with the specified id. If this is a ListView, it will correspond to the first row.
There are many ways to work around this problem. The quickest one (but certainly not the prettiest one, since it depends on the layout) would be to use findViewById() relative to the LinearLayout that contains the list item. Assuming that view is the ImageButton, it would be somthing like:
((View)view.getParent()).findViewById(R.id.useful_nums_item_value)
A more elegant solution would be to set a tag in the adapter's getView(), containing the data you need (in this case, the phone number to call).

Related

TextView doesn't change visually, but the date it keeps is correct

After login, I want to change text in TextView near profile on name_user.
But it doesn't change textView visually.
It is worth to mention, that when outputting (Toast), it gives out the data that is needed, but does not visually display it. Everything is fine with the TextView parameters (I think), because if you set the finished text in the parameters( i mean android:text="smth"), it visually displays it.
Java code:
`protected void onCreate(Bundle savedInstanceState) {
yourLayout = getLayoutInflater().inflate(R.layout.layout_navigation_header, null);
profileName = yourLayout.findViewById(R.id.profName); //
Intent intent = getIntent(); // Get data from previous activity.
String name_user = intent.getStringExtra("name");
String email_user = intent.getStringExtra("email");
String password_user = intent.getStringExtra("password");
profileName.setText(name_user); //0 changes, textView still don't change.
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu2);
DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
Toast toast = Toast.makeText(getApplicationContext(), profileName.getText().toString(),
Toast.LENGTH_SHORT); // for debug, it works and show profileName that contains name_user, but.
toast.show();
findViewById(R.id.imageMenu).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
drawerLayout.openDrawer(GravityCompat.START);
}
});
}`
Part of main XML
`<com.google.android.material.navigation.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:headerLayout="#layout/layout_navigation_header"// layour_navigation_header -here is TextView
app:menu='#menu/navigation_menu'
android:layout_gravity="start"/>`
Part of layour_navigation_header with TextView that I need to change.
`<TextView
android:id="#+id/profName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textColor="#color/black"
android:textSize="18sp"
android:text="Temporary"
app:layout_constraintBottom_toTopOf="#id/viewSupporter"
app:layout_constraintStart_toEndOf="#id/imageProfile"/>`
Hope you could help me
I tried to move
`yourLayout = getLayoutInflater().inflate(R.layout.layout_navigation_header, null);
profileName = yourLayout.findViewById(R.id.profName); //
Intent intent = getIntent(); // Get data from previous activity.
String name_user = intent.getStringExtra("name");
String email_user = intent.getStringExtra("email");
String password_user = intent.getStringExtra("password");
profileName.setText(name_user); //0 changes, textView still don't change`
before
`super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu2);`
but final result remains the same. It contains data, but not visually displays it.
You're inflating layout_navigation_header layout and setting a value in one of its textviews. But you never seem to place the layout on screen, the layout instance simply gets discarded.
What gets displayed is the activity_menu2 layout you inflate and set as content view with setContentView(). If that layout includes layout_navigation_header or its look-a-like with some mechanism, it's not the same instance you inflated earlier.
To solve the issue, just call setContentView() to set your desired layout, call findViewById() to find the textview and set a text to it.

Get LinearLayout reference at custom view

My question is about Android/Java.
I wanna access to other views from my custom view.
My main.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainLinearLayout1">
<org.javaforum.input
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
required=""
android:hint="Enter your E-Mail"
oninvalid="this.setCustomValidity('SO - Please enter a correct E-Mail!!!')"/>
<org.javaforum.input
android:layout_width="wrap_content"
android:layout_height="wrap_content"
inputType="submit"/>
</LinearLayout>
So when the second "input" view is clicked, I wanna check if there exists an attribute named "required" at the first "input" view.
I tried this in my input.java:
public class input extends TextView{
public input(Context context, AttributeSet attr) {
super(context, attr, getIdentifier(context,attr));
}
#Override
public void onFinishInflate() {
setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout layout = (LinearLayout)findViewById(R.id.mainLinearLayout1);
View v = null;
for(int i=0; i<layout.getChildCount(); i++) {//Error
//Code
}
}
});
}
}
But I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.widget.LinearLayout.getChildCount()' on a null object reference
I don't understand why it's null. It should be already created, right?
So how can I get an LinearLayout reference of my main.xml at my custom view correctly?
To solve the null pointer exception, you will need to search for the other widget in the parent LinearLayout. You can use View.getParent() to identify the parent. Since the view you are looking for is a sibling of the current view, you will find it in the parent.
As for determining if a certain attribute is set, I recommend that the value be captured by its view and a method provided to present that value upon request. Say the value is your "required" value then capture that value locally and provide a method, getRequiredValue(), for instance, to expose it.
You can use
LinearLayout layout = (LinearLayout) getRootView().findViewById(R.id.mainLinearLayout1);
if you only call findViewById inside custom view it only lookup the child view.
This should be called in the Activity's onCreate instead of TextView's onFinishInflate.
First give the submit button an id eg btn_submit, then in onCreate
Button btn_submit = (Button)findViewById(R.id.btn_submit);
btn_submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout layout = (LinearLayout)findViewById(R.id.mainLinearLayout1);
View v = null;
for(int i=0; i<layout.getChildCount(); i++) {
//Code
}
}
});

addView adds the view but it's not showing it

I know this has already been asked, but I tried everything and I couldn't solve my problem.
When I create the views programmatically, they are definitely added. I checked in the debugger and everything is in it's place, even the parent view gets bigger in height because they are using space. But I can't see them. It's like they are below other views or invisible (but they are not. I checked many times...).
This is the xml code where I'm trying to insert the views. I want to insert them where the cursor is (where it's tagged information). I only have it there to show you how it will look like in the end, but this part will be added programmatically.
<LinearLayout
android:id="#+id/llhTestItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:orientation="horizontal">
<TextView
android:id="#+id/tvInformationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="17sp"
fontPath="fonts/OpenSans-Regular.ttf"
android:text="Sub title: "/> <!-- tvInformationTitle -->
<TextView
android:id="#+id/tvInformation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
fontPath="fonts/OpenSans-Light.ttf"
android:text="information"/> <!-- tvInformation -->
</LinearLayout> <!-- information -->
Below you can see the code that I'm using to add the views just like in the xml above.
#Override
public void onBindViewHolder(SetupViewerHolder holder, int position) {
CardViewItem cardViewItem = cardViewItemList.get(position);
holder.tvTitle.setText(cardViewItem.getCardTitle());
for (int i = 0; i < cardViewItem.getInformationList().size(); i++){
//region Create llhItem
LinearLayout.LayoutParams llhItemParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
llhItemParams.topMargin = dipToPixels(6);
LinearLayout llhItem = new LinearLayout(context);
llhItem.setLayoutParams(llhItemParams);
llhItem.setOrientation(LinearLayout.HORIZONTAL);
//endregion
LinearLayout.LayoutParams tvInformationsParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//region Create tvInformationTitle
TextView tvInformationTitle = new TextView(context);
tvInformationTitle.setLayoutParams(tvInformationsParams);
tvInformationTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
if (Build.VERSION.SDK_INT < 23){
tvInformationTitle.setTextAppearance(context, R.style.OpenSansRegular);
} else {
tvInformationTitle.setTextAppearance(R.style.OpenSansRegular);
}
tvInformationTitle.setText(cardViewItem.getInformationList().get(i)[0]);
//endregion
//region Create tvInformation
TextView tvInformation = new TextView(context);
tvInformation.setLayoutParams(tvInformationsParams);
tvInformation.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
if (Build.VERSION.SDK_INT < 23){
tvInformation.setTextAppearance(context, R.style.OpenSansLight);
} else {
tvInformation.setTextAppearance(R.style.OpenSansLight);
}
tvInformation.setText(cardViewItem.getInformationList().get(i)[1]);
//endregion
llhItem.addView(tvInformationTitle);
llhItem.addView(tvInformation);
holder.llvInformation.addView(llhItem);
}
Basically what I'm trying to achieve is to have a recycler view, and each item has only one title, one overflow button, but can have multiple information rows.
Here is a print of this, which I had hard coded in xml previously as a prototype.
I know of some alternative ways of doing this that might work, but for now I would like to have it like this, since everything is working like it should, the views are just "not visible".
Had to use layout.post
holder.llvInformation.post( new Runnable() {
#Override
public void run() {
holder.llvInformation.addView(llhItem);
}
});
Have you tried calling invalidate() after adding the view? Like this:
holder.llvInformation.addView(llhItem);
holder.llvInformation.invalidate();

Android: Linking Edit Text field to button

I am creating a times tables app, in which one of the activities allows the user to enter which times tables they would like to view, then the app will bring up that times tables.(e.g. 6x5=30) etc.
Below is the xml layout I have created for the activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp">
<TextView
android:id="#+id/tvTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I want to see the: "
android:textSize="25dp" />
<EditText
android:id="#+id/etEnterNumber"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Number..."
>
</EditText>
<TextView
android:id="#+id/tvBottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Times tables!"
android:textSize="25dp" />
<Button
android:id="#+id/btnGo"
android:layout_width="50dp"
android:layout_height="50dp"
android:text="Go"
android:layout_gravity="center"/>r
</LinearLayout>
And this it the java class I have created thus far for the classes functionalitiy:
public class ViewTimesTables extends Activity implements View.OnClickListener {
// Declaring Vars
Button go;
EditText enterNumber;
TextView top;
TextView bottom;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setting equal to text layout View
setContentView(R.layout.view);
// calling method to intialise vars
initialiseVars();
}// on create end
/**
* method to initialise all of the buttons, textviews etc used to clean up
* the onCreate.
*/
private void initialiseVars() {
// Setting up (initialising) all the buttons text views etc from the xml
// (vid 25)
go = (Button) findViewById(R.id.btnGo);
enterNumber = (EditText) findViewById(R.id.etEnterNumber);
top = (TextView) findViewById(R.id.tvTop);
bottom = (TextView) findViewById(R.id.tvBottom);
}
/**
* Method with on click listener that adds functionality for all of the
* buttons, text views etc
*
* #param v
*/
public void onClick(View view) {
// switch statement which determines what is clicked
switch ((view).getId()) {
case R.id.etEnterNumber:
// code to read user number (i.e. between 1 and 12)
//And possibly link to go button
break;
case R.id.btnGo:
// code to bring up new activity/screen with times table
// of the number that was entered in edit text
break;
}
}
}
I am unsure how to add the correct functionality (probably within switch statement) so that when e.g. "6" is entered in the edit text box and the "go" button is pressed then the 6 times tables will be brought up in a new activity?
I would begin by looking at Intents to start a new activity and pass data to it.
A relevant tutorial is this Android Intents Tutorial
Getting the text from a edit text is a simple as enterNumber.getText().getString()
You could then use a conditional statement to call the designated class.
Something like this would allow you to pass two values to the SixTimesTables class with the values 5 and 6 passed in.
if(enterNumber.getText().getString().equals("6")){
Intent i = new Intent(this, SixTimesTables.class);
i.putExtra("Value1", 5);
i.putExtra("Value2", 6);
// set the request code to any code you like,
// you can identify the callback via this code
startActivityForResult(i, REQUEST_CODE);
}
You probably want a dynamic layout for next activity.
It may help you.
http://www.dreamincode.net/forums/topic/130521-android-part-iii-dynamic-layouts/
Then you can switch between activities as AndyGable mentioned.
Hopefully it'll help you.
You really dont need the onClick for the editText you can handle if data is entered in the editText or not from the button click only like this:
public void onClick(View view) {
// switch statement which determines what is clicked
switch ((view).getId()) {
case R.id.btnGo:
// code to bring up new activity/screen with times table
// of the number that was entered in edit text
// check if editText has values or not
if(TextUtils.isEmpty(mEditText.getText().toString())) {
mEditText.setError("Please enter a number");
}else {
int number = Integer.parseInt(mEditText.getText().toString());
Intent intent = new Intent(YourCurrentActivity.this, NextActivity.class);
intent.putExtra("value", number);
startActivity(intent);
// it is always good to check if the value entered is a number only or not
// add inputType tag in the xml
// android:inputType="number" for the editText.
}
break;
}
}
Now, in order to get value in the next activity do this:
// write this inside the onCreate of the Activity.
int number;
if(getIntent().getExtras() != null) {
number = getIntent().getIntExtra("value");
}
// use the number then to display the tables

Display Text Being Typed

I am trying to develop a chat room for an Android App. I have a created some area for EditText and a corresponding button to Enter the text that is typed by a user.
On clicking on Enter I want to display the typed text on the same screen i.e. whatever text is being typed, it is subsequently being displayed on the same screen. I am using Linear Layout(Horizontal) for my app.
How can I implement this ?? Can someone help me with the code. I am totally new to Android Development Framework. Thanks and Regards.
Its very simple. You create the xml file with one textView and one edittext and one button. Then you handle the event of button click in mainActivity and call onResume from it. Override the onResume so that you can update the textview.
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
TextView text = (TextView) findViewById(R.id.txtView1);
EditText editBox = (EditText)findViewById(R.id.txtBox1);
String str = text.getText().toString();
text.setText(str+" "+editBox.getText().toString());
editBox.setText("");
editBox.setHint("Type in here");
}
You can use 'Toast' to display the msg or use another 'TextView' which is set using 'setText()'
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout android:id="#+id/linearLayout1" android:layout_width="match_parent"android:orientation="vertical" android:layout_height="match_parent">
</LinearLayout>
<LinearLayout android:id="#+id/linearLayout2"android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent">
<EditText...
<Button...
</LinearLayout>
</LinearLayout>
setContentView(R.Layout.main);
LinearLayout ll = (LinearLayout)findViewById(R.id.linearLayout1); //Layout where you want to put your new dynamic TextView.
String s=editText.getText().toString(); //Fetching String from your EditText
TextView tv = new TextView(this);
tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
tv.setText(s);
ll.addView(tv); //Add TextView inside the Layout.
You can use an one editText for input and one TextView for displaying the typed message:
tvChatWindow = (TextView) findViewById(R.id.tvChatWindow);
etInputWindow = (EditText) findViewById(R.id.etInputWindow);
btnEnter = (Button) findViewById(R.id.btnEnter);
btnEnter.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// send message to other chat clients here
//add a new line break character and the typed string to Chat Window
tvChatWindow.append("\n" + etInputWindow.getText().toString());
//clear the text you have typed on the edittext
etInputWindow.setText("");
}
});

Categories

Resources