first of all, I'll explain the expected behavior of the App.
What does the App do?
When I run the App I see this view:
Now if you hit the "+" button you'll see this Dialog:
By clicking Add this entry will be added to a ListView. I added two items. This looks like this:
Expected Result
Now when I touch and hold the mic icon of the list items it should start recording audio through the device microphone and then save this recording with the name of the bold entry, that means e.g. the first recording will get the name A.3gp, the second one B.3gp and so on..
Actual Result (UPDATE 07.12.2017)
The current state is:
Every item in the list gets his "own" recording. That means if I touch and hold the microphone icon of the first item in the list, it is doing what it should do. The same goes for all other items on the list.
When I add the first item A, then touch its record icon, a file will be created with the name A.3gp (which is correct behavior).
When I add the second item B then do nothing and then add a third item C and touch the record icon for B, a file will be created with the name C.3gp (which is not a correct behavior, it should be B.3gp).
Now to the fun part.
Code (UPDATE 07.12.2017)
1. The Model
public class Word {
private String mForeignTranslation;
private String mDefaultTranslation;
private ImageView mRecordIconImageResourceId;
private MediaRecorder mMediaRecorder;
public Word(String foreignTranslation, String defaultTranslation, ImageView recordIconImageResourceId) {
this.mForeignTranslation = foreignTranslation;
this.mDefaultTranslation = defaultTranslation;
this.mRecordIconImageResourceId = recordIconImageResourceId;
}
public Word(String foreignTranslation, String defaultTranslation) {
this.mForeignTranslation = foreignTranslation;
this.mDefaultTranslation = defaultTranslation;
}
public String getDefaultTranslation() {
return mDefaultTranslation;
}
public String getForeignTranslation() {
return mForeignTranslation;
}
public ImageView getRecordIconImageResourceId() {
return mRecordIconImageResourceId;
}
public MediaRecorder getMediaRecorder() {
return mMediaRecorder;
}
public void setDefaultTranslation(String mDefaultTranslation) {
this.mDefaultTranslation = mDefaultTranslation;
}
public void setForeignTranslation(String mForeignTranslation) {
this.mForeignTranslation = mForeignTranslation;
}
public void setRecordIconImageResourceId(ImageView recordIconImageResourceId) {
this.mRecordIconImageResourceId = recordIconImageResourceId;
}
public void setMediaRecorder(MediaRecorder mMediaRecorder) {
this.mMediaRecorder = mMediaRecorder;
}
}
2. The Adapter
public class WordAdapter extends ArrayAdapter<Word> {
private ArrayList<Word> wordsArrayList = new ArrayList<>();
private MediaRecorder mediaRecorder = new MediaRecorder();
public WordAdapter(#NonNull Context context, ArrayList<Word> words) {
super(context, 0, words);
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.my_word_list_items,parent,false);
}
Word currentWord = getItem(position);
TextView foreignWord = listItemView.findViewById(R.id.myForeignWord);
foreignWord.setText(currentWord.getForeignTranslation());
TextView defaultWord = listItemView.findViewById(R.id.myDefaultWord);
defaultWord.setText(currentWord.getDefaultTranslation());
final ImageView recordIconImageView = listItemView.findViewById(R.id.recordIconImageView);
wordsArrayList = MyWordsActivity.getWordsArrayList();
recordIconImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: {
recordIconImageView.setImageResource(R.drawable.mic_red);
startAudioRecording();
break;
}
case MotionEvent.ACTION_UP: {
recordIconImageView.setImageResource(R.drawable.mic_black);
stopAudioRecording();
break;
}
}
return true;
}
});
return listItemView;
}
private ArrayList<Word> getWordsArrayList() {
return wordsArrayList;
}
private void startAudioRecording() {
if (wordsArrayList != null) {
Log.i("ArrayListe", wordsArrayList.toArray().toString());
getMediaRecorderReady();
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
Toast.makeText(this.getContext(), "Recording started", Toast.LENGTH_SHORT).show();
}
}
private void stopAudioRecording() {
try {
mediaRecorder.stop();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(this.getContext(), "Recording stopped", Toast.LENGTH_SHORT).show();
}
private void getMediaRecorderReady() {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+"speakmylanguage"+"/"+MyWordsActivity.getForeignWord()+".3gp");
}
}
3. The Activity
public class MyWordsActivity extends AppCompatActivity {
private static String defaultWord, foreignWord;
private static ArrayList<Word> wordsArrayList = new ArrayList<>();
WordAdapter wordAdapter;
// Main Activity Views
TextView hintTextView;
ListView myWordsListView;
FloatingActionButton floatingButtonAddNewWord;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_words);
// Init Main Activity Views
hintTextView = findViewById(R.id.hintTextView);
myWordsListView = findViewById(R.id.myWordsList);
floatingButtonAddNewWord = findViewById(R.id.fabAddNewWord);
floatingButtonAddNewWord.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Dialog addNewWordsDialog = new Dialog(MyWordsActivity.this);
addNewWordsDialog.setContentView(R.layout.activity_add_new_words);
final EditText addForeignWordEditText = addNewWordsDialog.findViewById(R.id.addForeignWordEditText);
final EditText addDefaultWordEditText = addNewWordsDialog.findViewById(R.id.addDefaultWordEditText);
final Button addNewWordButton = addNewWordsDialog.findViewById(R.id.addNewWordButton);
addNewWordsDialog.show();
addNewWordButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!addDefaultWordEditText.getText().toString().equals("") &&
!addForeignWordEditText.getText().toString().equals("")) {
foreignWord = addForeignWordEditText.getText().toString();
defaultWord = addDefaultWordEditText.getText().toString();
wordsArrayList.add(new Word(foreignWord, defaultWord));
hintTextView.setVisibility(View.GONE);
addNewWordsDialog.dismiss();
} else {
Toast.makeText(MyWordsActivity.this, "Please enter two words", Toast.LENGTH_SHORT).show();
}
}
});
wordAdapter = new WordAdapter(MyWordsActivity.this, getWordsArrayList());
myWordsListView.setAdapter(wordAdapter);
}
});
}
public static String getDefaultWord() {
return defaultWord;
}
public static void setDefaultWord(String defaultWord) {
MyWordsActivity.defaultWord = defaultWord;
}
public static String getForeignWord() {
return foreignWord;
}
public static void setForeignWord(String foreignWord) {
MyWordsActivity.foreignWord = foreignWord;
}
public static ArrayList<Word> getWordsArrayList() {
return wordsArrayList;
}
}
4. The Layouts
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/myWordsListItems"
android:layout_width="match_parent"
android:layout_height="88dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:id="#+id/myForeignWord"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="bottom"
android:textAppearance="?android:textAppearanceMedium"
android:textSize="24sp"
android:textStyle="bold"
tools:text="foreign word" />
<TextView
android:id="#+id/myDefaultWord"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
android:textAppearance="?android:textAppearanceMedium"
android:textSize="24sp"
tools:text="default word" />
</LinearLayout>
<ImageView
android:id="#+id/playIconImageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:clickable="true"
android:src="#drawable/play_icon" />
<ImageView
android:id="#+id/recordIconImageView"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="72dp"
android:clickable="true"
android:src="#drawable/mic_black" />
</RelativeLayout>
activity_my_words.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:orientation="vertical"
tools:context="com.yousef.mustafa.speakmylanguage.View.MyWordsActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:title="#string/app_name"
app:titleTextColor="#color/colorWhite" />
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myWordsList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:drawSelectorOnTop="true"
android:orientation="vertical"
tools:context=".View.MyWordsActivity" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabAddNewWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="bottom|center"
android:layout_marginBottom="32dp"
android:tint="#color/colorWhite"
app:backgroundTint="#color/colorGrey"
app:srcCompat="#drawable/icon_add" />
<TextView
android:id="#+id/hintTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="155dp"
android:gravity="center"
android:text="#string/hint"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
activity_add_new_words.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorDialogBackground">
<LinearLayout
android:id="#+id/addNewWordLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:layout_marginTop="12dp"
android:text="#string/add_word_title"
android:textColor="#color/colorBlack"
android:textSize="24sp"
android:textStyle="bold" />
<EditText
android:id="#+id/addForeignWordEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="4dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_weight="5"
android:gravity="center_horizontal"
android:hint="#string/enter_foreign_word"
android:inputType="textPersonName|textCapWords"
android:textSize="24sp" />
<EditText
android:id="#+id/addDefaultWordEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="4dp"
android:layout_weight="5"
android:gravity="center_horizontal"
android:hint="#string/enter_default_word"
android:inputType="textPersonName|textCapWords"
android:textSize="24sp" />
<Button
android:id="#+id/addNewWordButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="#string/button_add"
android:textAllCaps="false"
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
I would appreciate any help. Thanks in advance.
In the startAudioRecording() method of the Activity, you set the output filename from the foreignWord field. The problem is that the foreignWord field is set to the most recently added foreign word each time the user submits a word pair in the Add Word dialog. Thus each time the user starts a recording, the name of the output file will be set to the last foreign word added.
Instead of using fields for recordingImageView, foreignWord, defaultWord, foreignWord, audioSavePath, and mediaRecorder, you should make them local variables, and pass them as parameters to your record(), startAudioRecording(), stopAudioRecording() methods with the following steps:
Just delete those fields from the beginning of the class so that you see some compilation errors where the fields were used.
Where you see an undefined variable on the left side of an assignment, make the variable local (Ctrl+V in Android Studio).
Where you see an undefined variable elsewhere, make the variable a parameter of the method (Ctrl+P).
It should work after those changes.
`
Kindly move this snippet :
recordingImageView.setOnTouchListener(new View.OnTouchListener()
{
#Override public boolean onTouch(View view, MotionEvent motionEvent)
{
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
{ recordingImageView.setImageResource(g startAudioRecording(position);
break;
}
case MotionEvent.ACTION_UP:
{
recordingImageView.setImageResource(R.drawable.mic_black);
stopAudioRecording();
break;
}
}
return true;
}
});
In Adapter , getView(...) Below accessing recordImageView.
And put startAudioRecording() , stopAudioRecording() in same adapter or all relevant method for recording is to be in Adapter.
So by this you will get click on in each individual image view. Previously when you are fetching it will only take instance of any one image view.
Now update code on "startAudioRecording()" as:
private void startAudioRecording()
{
if (checkPermission())
{
if (wordsArrayList != null)
{
audioSavePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + wordsArrayList.get(position) + ".3gp";
getMediaRecorderReady();
}
}
}
Now your second point, saving its name by any name. Will cover by above code.
Thanks and happy coding
Related
I make a chat app using a video tutorial, but this tutorial does not show how to make messages from different people appear on different sides. The sender and receiver see all messages on the left. Could you please give some advices on this? Thanks in advance.
Now it looks like this
Main code
public class MainActivity extends AppCompatActivity {
private static int SIGN_IN_CODE=1;
private RelativeLayout activity_main;
private FirebaseListAdapter<Message> adapter;
private FloatingActionButton sendBtn;
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==SIGN_IN_CODE) {
if(requestCode == RESULT_OK) {
Snackbar.make(activity_main, "You are authorized", Snackbar.LENGTH_LONG).show();
displayAllMessages();
} else {
Snackbar.make(activity_main, "You are not authorized", Snackbar.LENGTH_LONG).show();
finish();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity_main=findViewById(R.id.activity_main);
sendBtn = findViewById(R.id.btnSend);
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText textField = findViewById(R.id.messageField);
if(textField.getText().toString().equals(""))
return;
FirebaseDatabase.getInstance().getReference().push().setValue(
new Message(
FirebaseAuth.getInstance().getCurrentUser().getEmail(),
textField.getText().toString()));
textField.setText("");
}
});
//Пользователь ещё не авторизован
if (FirebaseAuth.getInstance().getCurrentUser()==null)
startActivityForResult(AuthUI.getInstance().createSignInIntentBuilder().build(), SIGN_IN_CODE);
//Пользователь авторизован
else {
Snackbar.make(activity_main, "You are authorized", Snackbar.LENGTH_LONG).show();
displayAllMessages();
}
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
private void displayAllMessages() {
ListView listOfMessages = findViewById(R.id.list_of_messages);
FirebaseListOptions<Message> options =
new FirebaseListOptions.Builder<Message>()
.setQuery(FirebaseDatabase.getInstance().getReference(), Message.class)
.setLayout(R.layout.list_item)
.build();
adapter = new FirebaseListAdapter<Message>(options){
#Override
protected void populateView(View v, Message model, int position) {
TextView mess_user, mess_time;
BubbleTextView mess_text;
mess_user = v.findViewById(R.id.message_user);
mess_time = v.findViewById(R.id.message_time);
mess_text = v.findViewById(R.id.message_text);
mess_user.setText(model.getUserName());
mess_text.setText(model.getTextMessage());
mess_time.setText(DateFormat.format("dd-MM-yyyy HH:mm:ss", model.getMessageTime()));
}
};
listOfMessages.setAdapter(adapter);
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Message Class
public class Message {
private String UserName;
private String TextMessage;
private long MessageTime;
public Message() {}
public Message (String UserName, String TextMessage){
this.UserName = UserName;
this.TextMessage = TextMessage;
this.MessageTime = new Date().getTime();
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public String getTextMessage() {
return TextMessage;
}
public void setTextMessage(String textMessage) {
TextMessage = textMessage;
}
public long getMessageTime() {
return MessageTime;
}
public void setMessageTime(long messageTime) {
MessageTime = messageTime;
}
}
Main XML
<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"
tools:context=".MainActivity"
android:id="#+id/activity_main">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:src="#drawable/ic_send_button"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
app:fabSize="normal">
</com.google.android.material.floatingactionbutton.FloatingActionButton>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/text_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#id/btnSend"
>
<EditText
android:id="#+id/messageField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint=" Message..."
/>
</com.google.android.material.textfield.TextInputLayout>
<ListView
android:id="#+id/list_of_messages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/text_layout"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:divider="#android:color/transparent"
android:dividerHeight="12dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll">
</ListView>
</RelativeLayout>
XML for the message bubbles
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/message_user"
android:textStyle="normal|bold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:id="#+id/message_time"
/>
<com.github.library.bubbleview.BubbleTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:id="#+id/message_text"
android:layout_marginTop="9dp"
android:layout_below="#id/message_user"
android:textSize="18sp"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#fff"
android:padding="10dp"
app:angle="10dp"
app:arrowWidth="8dp"
app:arrowHeight="10dp"
app:arrowPosition="10dp"
app:bubbleColor="#03dac5"
/>
</RelativeLayout>
Try adding layout_gravity attribute in your BubbleTextView when you need this like this:
android:layout_gravity="right"
Every user will have a unique email - Let say here in the example - d#mail.ru is your email. You need to add user logic to dynamically check to decide whether you want a bubble test layout to be LEFT or RIGHT.
Update the message bubble layout.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:id="#+id/message_user"
android:textStyle="normal|bold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:id="#+id/message_time"
/>
<com.github.library.bubbleview.BubbleTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:id="#+id/message_text"
android:layout_marginTop="9dp"
android:layout_below="#id/message_user"
android:textSize="18sp"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#fff"
android:padding="10dp"
app:angle="10dp"
app:arrowWidth="8dp"
app:arrowHeight="10dp"
app:arrowPosition="10dp"
app:bubbleColor="#03dac5"
/>
</RelativeLayout>
Adapter code:- you can update as you need either LEFT or RIGHT.
adapter = new FirebaseListAdapter<Message>(options){
#Override
protected void populateView(View v, Message model, int position) {
TextView mess_user, mess_time;
BubbleTextView mess_text;
RelativeLayout Layout = v.findViewById(R.id.parentlayout);
mess_user = v.findViewById(R.id.message_user);
mess_time = v.findViewById(R.id.message_time);
mess_text = v.findViewById(R.id.message_text);
mess_user.setText(model.getUserName());
mess_text.setText(model.getTextMessage());
mess_time.setText(DateFormat.format("dd-MM-yyyy HH:mm:ss", model.getMessageTime()));
if(!model.getUserName().equals("d#mail.ru")) {
mess_text.setGravity(Gravity.LEFT)
} else {
mess_text.setGravity(Gravity.RIGHT)
}
}
};
Check this link as a reference - https://github.com/rpadma/Trip-Planner/blob/master/app/src/main/java/com/etuloser/padma/rohit/homework09a/ChatAdapter.java
Intro:
To put things into perspective, I am attempting to use fragments to create a Sudoku game.
The Sudoku board consists of 9 sub-grids, each containing 9 cells, so 9 cells in one grid, and 9 of these grids form the Sudoku board, arranged in a 3x3 fashion.
Method:
Home screen containing some information, of which a GridLayout contains 9 Framelayouts where each Sudoku Fragment will be placed into
The 9 Sudoku Fragments will make up the Sudoku board.
sudoku_cell extends a LinearLayout with an onClickListener, since extending a TextView, I was unable to inflate the sudoku_cell layout (Is it possible to do so?)
In my main activity, I have a GridLayout containing 9 FrameLayouts. These layouts have column and row locations set to form a 3x3 matrix, this is where each of the fragments will be added into.
These FrameLayouts are named on a 0-based index: frame00, frame01, frame02, frame10, etc
Documentation says:
As mentioned here on developer.android.com, I am required to have an:
Inflator method for the fragment, i.e. onCreateView() which inflates the fragment
A Layout container of sorts to root/place the fragment in, in the main activity (in my case)
A FragmentManager and FragmentTransactionManager to handle the fragments, adding and commiting them.
Problem:
TL;DR: Simply, my fragments are not showing.
After calling the commit(), I expect to see a 3x3 board of sudoku_grid fragments, each containing 9 sudoku_cells. However, this does not get shown
I have searched SO, reread the documentation, and searched more but cannot understand why it is not showing.
I have tried:
When inflating my fragment, I inflate a sudoku_cell layout instead, this does infact show a 9 cell grid.
However each cell should be a grid containing 9 cells, this leads me to believe that there may be an issue on the Sudoku_Grid - Sudoku_Cell side, possibly the sudoku_cell layout is not being inflated correctly or being rooted correctly.
Usually an LayoutInflator, and ViewGroup is passed allowing one to inflate a layout, but in the case of the sudoku_cell, I cannot find such a method to override, is this the cause?
The code:
sudoku_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/cellText"
android:layout_width="35dp"
android:layout_margin="1px"
android:textSize="18dp"
android:layout_height="35dp"
android:textAlignment="center"
android:textColor="#color/clBlack">
</TextView>
</LinearLayout>
SudokuCell.java
public class SudokuCell extends LinearLayout{
private LinearLayout layout;
private TextView textView;
private Context mContext;
private Point location;
private int index;
public SudokuCell(Context context) {
super(context);
}
public SudokuCell(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (LinearLayout) inflater.inflate(R.layout.sudoku_cell, this, true);
textView = layout.findViewById(R.id.cellText);
setText("");
}
public void setStaticText(String s){
if (textView != null) {
textView.setText(s);
textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
}
}
public void setText(String s){
if (textView != null)
textView.setText(s);
}
public Point getLocation() {
return location;
}
public void setLocation(Point location) {
this.location = location;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
9 of these sudoku_cell's get added to a sudoku_grid as shown below in the onCreateView() and populateGrid() methods:
sudoku_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2px"
android:id="#+id/grid_layout"
android:columnCount="3"
android:rowCount="3">
</GridLayout>
SudokuGrid.java
public class SudokuGrid extends Fragment{
private GridLayout gridLayout;
private List<GridFragmentListener> listeners = new ArrayList<>();
private Context mActitityContext;
private boolean FRAGMENT_LOCATION_CENTRE;
private float SCREEN_DP;
private int GRID_MARGINS_DP = 1;
private int colorOdd, colorEven;
private List<Integer> presetGrid;
private View previousView;
private Drawable previousViewDrawable;
public void addGridListener(GridFragmentListener gridFragmentListener) {
listeners.add(gridFragmentListener);
}
public void removeGridListener(GridFragmentListener gridFragmentListener) {
listeners.remove(gridFragmentListener);
}
protected void notifyValueChanged(View value) {
for (GridFragmentListener listener : listeners) listener.onValueChange(value);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mActitityContext = getActivity();
View v = inflater.inflate(R.layout.sudoku_grid, container, false);
//set grid view
gridLayout = v.findViewById(R.id.grid_layout);
populateGrid();
return v;
}
private void populateGrid() {
for (int i = 0; i < 9; i++) {
SudokuCell sudokuCell = new SudokuCell(mActitityContext);
sudokuCell.setBackgroundColor(((i % 2) == 0) ? R.color.clOdd : R.color.clEven);
System.out.printf("Sudoku Cell ID [ index = " + String.valueOf(i) + " ] - getId() = " + sudokuCell.getId());
sudokuCell.setLocation(getPoint(i));
sudokuCell.setIndex(i);
sudokuCell.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
notifyValueChanged(view);
}
});
sudokuCell.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
SudokuCell cell = (SudokuCell) view;
if (b)
view.setBackgroundColor(ContextCompat.getColor(mActitityContext, R.color.clSelected));
else
view.setBackgroundColor(ContextCompat.getColor(mActitityContext, (cell.getIndex() % 2 == 0) ? R.color.clOdd : R.color.clEven));
}
});
sudokuCell.setStaticText(String.valueOf(i));
gridLayout.addView(sudokuCell, i);
}
}
private Point getPoint(int i) {
int y = 0;
while (i > 2){
y++;
i -= 3;
}
return new Point(i, y);
}
#Override
public void onStart() {
super.onStart();
try {
addGridListener((GridFragmentListener) getActivity());
} catch (ClassCastException e) {
throw new ClassCastException(
getActivity().getClass().toString()
+ " does not implement the DetailsFragment.DetailsFragmentListener interface.");
}
}
#Override
public void onStop() {
super.onStop();
removeGridListener((GridFragmentListener) getActivity());
}
}
In my main activity, I handle the creation of 9 sudoku_grid fragments which are placed into each respective FrameLayout, to form a 3x3 matrix of Sudoku_Grids, which will form the Sudoku board
activity_main_sudoku.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="wrap302.nmu.task1.MainActivitySudoku"
android:background="#color/clDarkGrey">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/linearLayout2">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:text="#string/app_title"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textColor="#color/clWhite"
android:textAppearance="#style/TextAppearance.AppCompat.Display1"
android:textAlignment="center"
android:textStyle="bold"
android:fontFamily="sans-serif"/>
<TextView
android:text="#string/lblScore"
android:textColor="#color/clWhite"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/lblScore"
android:textAppearance="#style/TextAppearance.AppCompat.Button" android:textAlignment="center"
android:layout_marginBottom="5dp"/>
</LinearLayout>
<GridLayout
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="3"
android:rowCount="3"
android:id="#+id/main_sudokugrid_container">
<FrameLayout
android:layout_column="0"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame00"/>
<FrameLayout
android:layout_column="1"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame01"/>
<FrameLayout
android:layout_column="2"
android:layout_row="0"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame02"/>
<FrameLayout
android:layout_column="0"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame10"/>
<FrameLayout
android:layout_column="1"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame11"/>
<FrameLayout
android:layout_column="2"
android:layout_row="1"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame12"/>
<FrameLayout
android:layout_column="0"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame20"/>
<FrameLayout
android:layout_column="1"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame21"/>
<FrameLayout
android:layout_column="2"
android:layout_row="2"
android:layout_width="wrap_content"
android:background="#color/clWhite"
android:layout_height="wrap_content" android:id="#+id/frame22"/>
</GridLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center" android:id="#+id/linearLayout">
<GridLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingTop="0dp">
<Button
android:layout_row="0"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn1"
android:text="1"/>
<Button
android:layout_row="0"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn2"
android:text="2"/>
<Button
android:layout_row="0"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn3"
android:text="3"/>
<Button
android:layout_row="1"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn4"
android:text="4"/>
<Button
android:layout_row="1"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn5"
android:text="5"/>
<Button
android:layout_row="1"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn6"
android:text="6"/>
<Button
android:layout_row="2"
android:layout_column="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn7"
android:text="7"/>
<Button
android:layout_row="2"
android:layout_column="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn8"
android:text="8"/>
<Button
android:layout_row="2"
android:layout_column="2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn9"
android:text="9"/>
<Button
android:layout_row="0"
android:layout_column="3"
android:layout_rowSpan="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill_vertical"
android:id="#+id/btnClear"
android:text="Clear"/>
</GridLayout>
</LinearLayout>
</RelativeLayout>
MainActivitySudoku.java
public class MainActivitySudoku extends AppCompatActivity implements GridFragmentListener {
private FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_sudoku);
createSudokuGrid();
}
private void createSudokuGrid() {
fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransactionManager = fragmentManager.beginTransaction();
fragmentTransactionManager.add(R.id.frame00, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame01, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame02, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame10, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame11, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame12, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame20, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame21, new SudokuGrid());
fragmentTransactionManager.add(R.id.frame22, new SudokuGrid());
fragmentTransactionManager.commit();
}
#Override
protected void onStart() {
super.onStart();
Toast.makeText(this, "Activity Started & Viewable", Toast.LENGTH_SHORT).show();
}
// GridFragmentListener
#Override
public void onValueChange(View view) {
//todo something here with received view
}
}
Well, the solution proved simpler than expected.
In short, the solution was to move the SudokuCell constructor code from the
SudokuCell(Context context, AttributeSet attrs)
to the
SudokuCell(Context context)
since that was the constructor I was calling.
A few other changes can be made for improvement, this solves the fragments not being displayed.
Quite a simple error
Ok - I have given you a sample of how to add your fragments so they will display. If you go through this and emulate the process this will assist you. I've used basic examples in the layout so we can have ids to use in the classes.
You'll also need to manage the app lifecycle and the back press button on how you want to manage your stack with your fragments and maintaining any data.
Activity
public class MyActivity extends Activity {
Fragment fragment;
FrameLayout frameLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_myactivity);
View view = this.findViewById(android.R.id.content);
frameLayout = (FrameLayout) findViewById(R.id.frag);
fragment = new MyFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frag, fragment);
fragmentTransaction.commit();
}
}
Layout for Activity
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
.../...>
.../...
<FrameLayout
android:id="#+id/frag"
// sort out your layout here with the frameLayouts
android:layout_below="#+id/your_id"
/>
.../...
</RelativeLayout>
Fragment
public class MyFragmentextends Fragment {
FragmentManager fragmentManager;
Fragment fragment;
public static MyFragmentnewInstance(String item {
fragment =
new MyFragment();
// pass data from activity
Bundle args = new Bundle();
args.putString(ITEM, item);
fragment.setArguments(args);
return fragment;
}
public DeliveryDisplayFromDispenserFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
item = getArguments().getString(ITEM);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view =
inflater.inflate(R.layout.myfragment, container, false);
}
}
Layout for Fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
.../...>
// fragment layout
</RelativeLayout>
I have an adapter class which loads items dynamically and shows them in a RecyclerView. My problem is that when I swipe up and down the recycler view the images get mixed and are shown in wrong positions (i.e. in other item's view).
For example, I have an item X and another item Y. Now when I swipe up and down the image which was to be shown in item Y get shown in item X and the same happens with other attributes.
Here is my adapter class:
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsViewHolder> {
private DatabaseReference refDNewsTable= FirebaseDatabase.getInstance().getReference().child("news_feeds");
private StorageReference refStorage = FirebaseStorage.getInstance().getReferenceFromUrl("firebase_url_comes_here");
private Context mContext;
private List<NewsModel> newsList;
public class NewsViewHolder extends RecyclerView.ViewHolder {
public TextView nHeading, nDes,nDaTi;
public ImageView nImg;
public NewsViewHolder(View view) {
super(view);
nHeading = (TextView) view.findViewById(R.id.tv_newsHeadline);
nDes = (TextView) view.findViewById(R.id.tv_nDes);
nImg = (ImageView) view.findViewById(R.id.iv_nImg);
nDaTi=(TextView) view.findViewById(R.id.tv_nDaTi);
}
}
public NewsAdapter(Context mContext, List<NewsModel> newsList) {
this.mContext = mContext;
this.newsList = newsList;
}
#Override
public NewsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.news_model, parent, false);
return new NewsViewHolder(itemView);
}
#Override
public void onBindViewHolder(final NewsViewHolder holder, int position) {
NewsModel news = newsList.get(position);
holder.nHeading.setText(news.getnHeading());
if(news.hasDes()) {
holder.nDes.setText(news.getnDes());
}else{
holder.nDes.setVisibility(View.GONE);
}
if(news.hasImg()){
// Reference to an image file in Firebase Storage
StorageReference imgReference =refStorage.child(news.getnId());
// Load the image using Glide
Glide.with(mContext)
.using(new FirebaseImageLoader())
.load(imgReference)
.into(holder.nImg);
}else{
holder.nImg.setVisibility(View.GONE);
}
holder.nDaTi.setText(news.getnDaTi());
}
public void downloadFile(final NewsViewHolder holder){
try {
final File localFile = File.createTempFile("images", "jpg");
refStorage.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Bitmap bitmap = BitmapFactory.decodeFile(localFile.getAbsolutePath());
holder.nImg.setImageBitmap(bitmap);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
}
});
} catch (IOException e ) {}
}
#Override
public int getItemCount() {
return newsList.size();
}
}
And this is my news_model.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_margin="4dp"
card_view:cardPreventCornerOverlap="true"
card_view:cardElevation="16dp"
android:layout_height="wrap_content"
android:id="#+id/card_view"
android:layout_gravity="center"
card_view:cardCornerRadius="0dp">
<LinearLayout
android:orientation="vertical"
android:background="#color/cBgNews"
android:padding="0dp"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:padding="10dp"
card_view:cardElevation="6dp"
card_view:cardBackgroundColor="#color/cNewsHeadline"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="0dp"
android:id="#+id/card_des"
android:layout_gravity="center"
card_view:cardCornerRadius="0dp">
<TextView
android:text="TextView"
android:textSize="17sp"
android:textStyle="normal"
android:padding="10dp"
android:maxLines="3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/cWhite"
android:gravity="start"
android:layout_margin="0dp"
android:id="#+id/tv_newsHeadline" />
</android.support.v7.widget.CardView>
<LinearLayout
android:orientation="vertical"
android:gravity="center_horizontal"
android:background="#0000"
android:paddingEnd="6dp"
android:paddingStart="6dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_marginBottom="0dp"
android:layout_height="wrap_content"
android:maxHeight="300dp"
app:srcCompat="#mipmap/ic_launcher"
android:scaleType="fitCenter"
android:layout_gravity="center_horizontal"
android:id="#+id/iv_nImg" />
<TextView
android:text="Description..."
android:maxLines="8"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:padding="10dp"
android:textColor="#color/cBlack"
android:id="#+id/tv_nDes" />
<TextView
android:text="Date and Time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="10sp"
android:textColor="#999999"
android:gravity="end"
android:id="#+id/tv_nDaTi" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
NOTE: I am using firebase to receive the content directly and haven't created any kind of database in my app yet. i.e. it loads data every time it needs it directly in adapter class.
I've used SwipeDeck2, I set every thing and it is working, but I have one issue that is I can not set OnClickListener correctly on one of the views in card I have layout as
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root_cv"
style="#style/CardViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:elevation="5dp"
app:cardCornerRadius="7dp"
android:layout_gravity="top">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.team.asl.me_c.ui.DynamicHeightImageView
android:id="#+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="88dp"
android:scaleType="fitCenter"
app:heightRatio="1.0"
android:background="#color/grey_white_1000"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:gravity="center_vertical"
android:padding="16dp"
android:background="#color/indigo_A200"
android:layout_gravity="bottom">
<TextView android:layout_marginTop="-15dp"
android:id="#+id/display_name_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:fontFamily="sans-serif"
android:textStyle="bold"
android:textSize="22sp"/>
<TextView
android:id="#+id/username_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:fontFamily="sans-serif"
android:textSize="16sp"/>
</LinearLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="true">
<ImageButton
android:id="#+id/btnLike"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="top|right"
android:background="#android:color/transparent"
android:src="#drawable/ic_heart_outline_grey" />
<TextView
android:id="#+id/like_tv"
android:layout_width="120dp"
android:background="#drawable/shape_bg_green_rounded_rect"
android:layout_height="56dp"
android:gravity="center"
android:textSize="32sp"
android:text="LIKE"
android:textStyle="bold"
android:alpha="0"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
android:layout_marginLeft="24dp"
android:textColor="#android:color/holo_green_light"/>
<TextView
android:id="#+id/nope_tv"
android:layout_gravity="right"
android:layout_width="120dp"
android:background="#drawable/shape_bg_red_rounded_rect"
android:layout_height="56dp"
android:textSize="32sp"
android:gravity="center"
android:textStyle="bold"
android:text="NOPE"
android:alpha="0"
android:layout_marginTop="32dp"
android:layout_marginBottom="32dp"
android:layout_marginRight="24dp"
android:textColor="#android:color/holo_red_light"/>
</FrameLayout>
</FrameLayout>
</android.support.v7.widget.CardView>
and the adapter as
public class SwipeDeckAdapter extends BaseAdapter {
private List<String> data;
private Context context;
private int countLike = 0;
private ImageButton btnLike;
//private View.OnClickListener onClickListener;
public SwipeDeckAdapter(List<String> data, Context context) {
this.data = data;
this.context = context;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null){
LayoutInflater inflater = LayoutInflater.from(context);
// normally use a viewholder
v = inflater.inflate(R.layout.product_card, parent, false);
}
((TextView) v.findViewById(R.id.display_name_tv)).setText(data.get(position));
btnLike = (ImageButton) v.findViewById(R.id.btnLike);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String item = (String)getItem(position);
Log.e("MainActivity", item);
}
});
btnLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
countLike ++;
Log.e("LIKE_CONT", " is " + countLike);
btnLike.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_heart_red));
Toast.makeText(context, "Clicked at index ", Toast.LENGTH_SHORT).show();
}
});
return v;
}
}
I want to add click listener on btnLike and want to change the image resource in method
btnLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
countLike ++;
Log.e("LIKE_CONT", " is " + countLike);
btnLike.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_heart_red));
Toast.makeText(context, "Clicked at index ", Toast.LENGTH_SHORT).show();
}
});
but result is
means the image resource of btnLike is not changed in current card but as I shuffle cards and see on the other card the image resource of btnLike is changed any suggestions how to see that bit of code so that it can work properly...
Is there a way how to hide some buttons when i click on EditText and keybord shows?
I have this layout
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/InnerRelativeLayout">
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1"
android:id="#+id/table">
<TableRow
android:id="#+id/tariffRow">
<TextView
android:layout_column="1"
android:text="Název"
android:padding="3dip" />
<EditText
android:id="#+id/tariffName"
android:gravity="right"
android:padding="3dip" />
</TableRow>
</TableLayout>
</ScrollView>
<LinearLayout android:id="#+id/InnerRelativeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<Button android:id="#+id/okBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Ok"/>
<Button android:id="#+id/stornoBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Storno" />
</LinearLayout>
Now when the editText is clicked to type some value i need to hide that linearLayout android:id="#+id/InnerRelativeLayout" because otherwise it is still visible above the keyboard.
Need to set a FocusChangeListener to the EditText which triggers whenever focus changes on that EditText as follow:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// hide relative layout
} else {
// show relative layout
}
}
});
It is not actually that simple, here is my solution how I got it working.
First Need to create MyEditText.java
public class MyEditText extends EditText {
private KeyImeChange keyImeChangeListener;
public MyEditText(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public void setKeyImeChangeListener(KeyImeChange keyImeChange){
keyImeChangeListener = keyImeChange;
}
public interface KeyImeChange {
public boolean onKeyIme(int keyCode, KeyEvent keyEvent);
}
#Override
public boolean onKeyPreIme (int keyCode, KeyEvent keyEvent){
if(keyImeChangeListener != null){
return keyImeChangeListener.onKeyIme(keyCode, keyEvent);
}
return false;
}
}
Then layout.xml, change following
<EditText
android:id="#+id/tariffName"
android:gravity="right"
android:padding="3dip" />
Into
<!-- change yourapp -->
<com.yourapp.MyEditText
android:id="#+id/tariffName"
android:gravity="right"
android:padding="3dip" />
Add also android:focusable="true" to your LinearLayout
<LinearLayout android:id="#+id/InnerRelativeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:focusable="true">
Then put into your activity like MainActivity.java,
import fi.hgs.apps.MyEditText.KeyImeChange;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
removeFocus();
MyEditText myEditText = (MyEditText) findViewById(R.id.tariffName);
myEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus) {
showLinearLayout();
} else {
hideLinearLayout();
}
}
});
myEditText.setKeyImeChangeListener(new KeyImeChange() {
#Override
public boolean onKeyIme(int keyCode, KeyEvent event) {
if (KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
removeFocus();
}
return false;
}
});
}
Add also these to do the actual job.
public void removeFocus() {
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.InnerRelativeLayout);
linearLayout.requestFocus();
}
public void showLinearLayout() {
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.InnerRelativeLayout);
linearLayout.setVisibility(View.VISIBLE);
}
public void hideLinearLayout() {
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.InnerRelativeLayout);
linearLayout.setVisibility(View.INVISIBLE);
}