I'm working on a course list app which loads each course title together with the course image in a listview through ArrayAdapter, I want to implement asynctask for loading of images in between listview and ArrayAdapter because the listview is lagging while scrolling, Please Help me.
MainActivity.java
package com.emmakade.okt;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
protected List<Course> data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data = DataProvider.getData();
ArrayAdapter<Course> courseArrayAdapter =
new CourseArrayAdapter(this, 0, data);
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(courseArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Course course = data.get(position);
displayDetail(course);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DETAIL_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
String msg = data.getStringExtra("resultMessage");
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
}
}
class CourseArrayAdapter extends ArrayAdapter<Course>{
Context context;
List<Course> objects;
public CourseArrayAdapter(Context context, int resource, List<Course> objects) {
super(context, resource, objects);
this.context = context;
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Course course = objects.get(position);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.course_item, null);
TextView tv = (TextView) view.findViewById(R.id.tvTitle);
tv.setText(course.getTitle());
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
iv.setImageResource(res);
return view;
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="#+id/imageLogo"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:src="#drawable/academy"/>
<TextView
android:id="#+id/txtOutput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/course_catalog"
android:layout_alignBottom="#+id/imageLogo"
android:layout_toEndOf="#+id/imageLogo"
android:layout_marginStart="20dp"
android:layout_marginBottom="15dp"
android:textSize="28sp" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/list"
android:layout_below="#+id/imageLogo"
android:layout_marginTop="10dp"
android:layout_alignParentStart="true" />
</RelativeLayout>
course_item.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:padding="10dp">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:id="#+id/imageCourse" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvTitle"
android:layout_toEndOf="#+id/imageCourse"
android:layout_marginStart="10dp"
android:textSize="18sp"/>
</RelativeLayout>
enter image description here
I recommend you to use Glide library for asynchronous image loading, caching and displaying.
Add Dependency
implementation 'com.github.bumptech.glide:glide:4.5.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
Use like this in adapter
Glide.with(this).load("url").into(imageView);
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
Glide.with(this).load(res).into(iv);
You can use handler because asynctask will work on another thread but you cant update ui from another thread instead of main thread. Also consider to use glide, picasso like libraries. These libraries caches images efficiently and works with more performence.
There is an example with Handler.
Handler handler = new Handler();
handler.post(() -> {
profilephoto.setImageBitmap(pp);
});
Related
I'm trying to have a dialog where you can click a "next" button to swipe right to the next screen. I am doing that with a ViewPager and adapter:
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.voicedialog);
dialog.setCanceledOnTouchOutside(false);
MyPageAdapter adapter = new MyPageAdapter();
ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(adapter);
However, I get a NullPointerException saying that pager is null. Why is this happening? Here is the Page Adapter class:
public class MyPageAdapter extends PagerAdapter {
public Object instantiateItem(ViewGroup collection, int position) {
int resId = 0;
switch (position) {
case 0:
resId = R.id.voice1;
break;
case 1:
resId = R.id.voice2;
break;
}
return collection.findViewById(resId);
}
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
Here's my layout for the DIALOG:
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Let me know on how to avoid this situation.
PS: Each of the layouts that should be in the view pager look like this, just diff. text:
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/voice2"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="Slide 1!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView2"
android:layout_gravity="center"
android:textSize="50sp" />
</RelativeLayout>
Without Using Enum Class
You should call findViewById on dialog. so for that you have to add dialog before findViewById..
Like this,
ViewPager pager = (ViewPager) dialog.findViewById(R.id.viewpager);
After solving your null pointer exception the other problem's solution here, if you wont use enum class you can use below code...
MainActivity.java
package demo.com.pager;
import android.app.Dialog;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn= (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Dialog dialog = new Dialog(MainActivity.this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.voicedialog);
dialog.setCanceledOnTouchOutside(false);
MyPageAdapter adapter = new MyPageAdapter(MainActivity.this);
ViewPager pager = (ViewPager) dialog.findViewById(R.id.viewpager);
pager.setAdapter(adapter);
dialog.show();
}
});
}
}
activity_main.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"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="demo.com.pager.MainActivity">
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
MyPageAdapter.java
package demo.com.pager;
import android.app.FragmentManager;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by rucha on 26/12/16.
*/
public class MyPageAdapter extends PagerAdapter {
Context mContext;
int resId = 0;
public MyPageAdapter(Context context) {
mContext = context;
}
public Object instantiateItem(ViewGroup collection, int position) {
/* int resId = 0;
switch (position) {
case 0:
resId = R.id.voice1;
break;
case 1:
resId = R.id.voice2;
break;
}
return collection.findViewById(resId);*/
LayoutInflater inflater = LayoutInflater.from(mContext);
switch (position) {
case 0:
resId = R.layout.fragment_blue;
break;
case 1:
resId = R.layout.fragment_pink;
break;
}
ViewGroup layout = (ViewGroup) inflater.inflate(resId, collection, false);
collection.addView(layout);
return layout;
}
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
FragmentBlue.java
package demo.com.pager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import android.support.v4.app.Fragment;
public class FragmentBlue extends Fragment {
private static final String TAG = FragmentBlue.class.getSimpleName();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blue, container, false);
return view;
}
}
fragment_blue.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4ECDC4">
</RelativeLayout>
voicedialog.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Please check and reply.
Using Enum Class
Try this code, This is working if any doubt ask again. Happy to help.
MainActivity.java
package demo.com.dialogdemo;
import android.app.Dialog; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.Window; import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupUIComponents();
setupListeners();
}
private void setupUIComponents() {
button = (Button) findViewById(R.id.button);
}
private void setupListeners() {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Dialog dialogItemDetails = new Dialog(MainActivity.this);
dialogItemDetails.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialogItemDetails.setContentView(R.layout.dialoglayout);
dialogItemDetails.getWindow().setBackgroundDrawable(
new ColorDrawable(Color.TRANSPARENT));
ViewPager viewPager = (ViewPager) dialogItemDetails.findViewById(R.id.viewPagerItemImages);
viewPager.setAdapter(new CustomPagerAdapter(MainActivity.this));
dialogItemDetails.show();
}
});
}
}
activity_main.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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dialog" />
</RelativeLayout>
ModelObject1.java
public enum ModelObject1 {
RED(R.string.red, R.layout.fragment_one),
BLUE(R.string.blue, R.layout.fragment_two);
private int mTitleResId;
private int mLayoutResId;
ModelObject1(int titleResId, int layoutResId) {
mTitleResId = titleResId;
mLayoutResId = layoutResId;
}
public int getTitleResId() {
return mTitleResId;
}
public int getLayoutResId() {
return mLayoutResId;
}
}
CustomPagerAdapter.java
package demo.com.dialogdemo;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by rucha on 26/12/16.
*/
public class CustomPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
ModelObject1 modelObject = ModelObject1.values()[position];
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(modelObject.getLayoutResId(), collection, false);
collection.addView(layout);
return layout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public int getCount() {
return ModelObject1.values().length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public CharSequence getPageTitle(int position) {
ModelObject1 customPagerEnum = ModelObject1.values()[position];
return mContext.getString(customPagerEnum.getTitleResId());
}
}
dailoglayout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtHeaderTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="ITEM IMAGES"
android:textStyle="bold" />
<android.support.v4.view.ViewPager
android:id="#+id/viewPagerItemImages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white" />
</RelativeLayout>
fragmentone.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="one"/>
</LinearLayout>
This is my code which I used to make my data fetched from my data base in form of a list.But it is refreshing at all time when scroll down after a scrolled up for an instant . I need to make the refresh avail only when it is at top.
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.shuan.Project.R;
import com.shuan.Project.Utils.Common;
import com.shuan.Project.adapter.ConnectAdapter;
import com.shuan.Project.asyncTasks.GetHome;
import com.shuan.Project.asyncTasks.GetPost;
import com.shuan.Project.employer.PostViewActivity;
import com.shuan.Project.list.Sample;
import java.util.ArrayList;
import java.util.HashMap;
public class OffersFragment extends Fragment {
private ArrayList<Sample> list;
private ConnectAdapter adapter;
private ListView listView;
private HashMap<String, String> cData;
private Common mApp;
private Context mContext;
private ProgressBar progressBar;
private SwipeRefreshLayout swipe;
public OffersFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mContext=getActivity();
mApp= (Common) mContext.getApplicationContext();
View view = inflater.inflate(R.layout.fragment_employer_home, container, false);
swipe = (SwipeRefreshLayout) view.findViewById(R.id.swipe);
listView = (ListView) view.findViewById(R.id.post);
progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
list = new ArrayList<Sample>();
new GetPost(getActivity(), listView, progressBar, mApp.getPreference().getString(Common.u_id,""),"all", swipe).execute();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView txt = (TextView) view.findViewById(R.id.jId);
TextView txt1= (TextView) view.findViewById(R.id.frm_id);
Intent in=new Intent(getActivity(),PostViewActivity.class);
in.putExtra("jId",txt.getText().toString());
in.putExtra("frmId",txt1.getText().toString());
in.putExtra("apply","no");
startActivity(in);
}
});
swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new GetHome(getActivity(), listView, progressBar, mApp.getPreference().getString(Common.u_id, ""), "all",swipe).execute();
}
});
return view;
}
}
my xml file
<android.support.v4.widget.SwipeRefreshLayout 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:id="#+id/swipe"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.shuan.Project.fragment.ConnectionFragment">
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<ListView
android:id="#+id/post"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"
android:visibility="gone" />
</RelativeLayout>
Change your xml layout so SwipeRefreshLayout only wrap a scrollable view (your case the ListView).
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.shuan.Project.fragment.ConnectionFragment">
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/post"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"
android:visibility="gone" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.enhancedListView.EnhancedListView
android:id="#+id/listaNoticias"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="5dp" >
</com.enhancedListView.EnhancedListView>
</android.support.v4.widget.SwipeRefreshLayout>
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.principal, container, false);
swipeLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeColors(android.R.color.holo_green_dark,
android.R.color.holo_red_dark,
android.R.color.holo_blue_dark,
android.R.color.holo_orange_dark); (...)
#Override
public void onRefresh() {
new myTask().execute();
}
I found my own solution for the question above. We can solve the issue by change the above code like below.
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.shuan.Project.R;
import com.shuan.Project.Utils.Common;
import com.shuan.Project.adapter.ConnectAdapter;
import com.shuan.Project.asyncTasks.GetHome;
import com.shuan.Project.asyncTasks.GetPost;
import com.shuan.Project.employer.PostViewActivity;
import com.shuan.Project.list.Sample;
import java.util.ArrayList;
import java.util.HashMap;
public class OffersFragment extends Fragment implements AbsListView.OnScrollListener {
private ArrayList<Sample> list;
private ConnectAdapter adapter;
private ListView listView;
private HashMap<String, String> cData;
private Common mApp;
private Context mContext;
private ProgressBar progressBar;
private SwipeRefreshLayout swipe;
private int preLast;
public OffersFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mContext=getActivity();
mApp= (Common) mContext.getApplicationContext();
View view = inflater.inflate(R.layout.fragment_employer_home, container, false);
swipe = (SwipeRefreshLayout) view.findViewById(R.id.swipe);
listView = (ListView) view.findViewById(R.id.post);
progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
list = new ArrayList<Sample>();
new GetPost(getActivity(), listView, progressBar, mApp.getPreference().getString(Common.u_id,""),"all", swipe).execute();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView txt = (TextView) view.findViewById(R.id.jId);
TextView txt1= (TextView) view.findViewById(R.id.frm_id);
Intent in=new Intent(getActivity(),PostViewActivity.class);
in.putExtra("jId",txt.getText().toString());
in.putExtra("frmId",txt1.getText().toString());
in.putExtra("apply","no");
startActivity(in);
}
});
listView.setOnScrollListener(this);
swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new GetHome(getActivity(), listView, progressBar, mApp.getPreference().getString(Common.u_id, ""), "all",swipe).execute();
}
});
return view;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == R.id.post) {
if (firstVisibleItem == 0) {
swipe.setEnabled(true);
int lastItem = firstVisibleItem + visibleItemCount;
if (lastItem == totalItemCount) {
if (preLast != lastItem) {
preLast = lastItem;
//Toast.makeText(getActivity(), "In Last", Toast.LENGTH_SHORT).show();
}
}else{
}
} else {
swipe.setEnabled(false);
}
}
}
}
This is a bit old, but in 2019 this is the correct answer: you have to include RecyclerView inside of NestedScrollView in order for SwipeRefreshLayout to behave properly, like this:
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swipeRefreshLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
add this lines of code
note : LinearLayoutManager should be define separately
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mSwipeRefreshLayout.setEnabled
(mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0);
}
});
findFirstCompletelyVisibleItemPosition() == 0 means at the top of recyclerview
I am trying to get a LinearLayout to be added to the main Activity view when a button is pressed.
NOTE before trying this with merge I used LinearLayout with the same results. I read this post which made me thing merge would help.
The XML for the View I want to add looks like this.
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grocery_list_row">
<EditText
android:hint="Price"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:hint="Item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
The java for this View looks like so
package com.example.developer.grocerylist.impl;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.example.developer.grocerylist.R;
/**
* Created by developer on 8/16/2015.
*/
public class GroceryListTableRowImpl extends LinearLayout {
int mRows;
public GroceryListTableRowImpl(Context context) {
this(context, null);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public GroceryListTableRowImpl(Context context, AttributeSet attributeSet, int defStyles) {
super(context, attributeSet, defStyles);
}
public void addRow(){
mRows++;
removeAllViews();
for(int i = 0; i < mRows; i++){
addView(createRow());
}
}
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,true);
return v;
}
}
The main Activity's XML looks like this
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".GroceryList"
android:id="#+id/list_table">
<com.example.developer.grocerylist.impl.GroceryListTableRowImpl
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/grocery_list">
</com.example.developer.grocerylist.impl.GroceryListTableRowImpl>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<DigitalClock
android:textSize="20pt"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="250px"
android:textSize="20pt"
android:paddingBottom="5px"
android:text=""
android:background="#777777"
android:textColor="#ff0000" />
<Button
android:id="#+id/add"
android:text="add" />
</TableRow>
</TableLayout>
Finally the main Activity's java
package com.example.developer.grocerylist.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TextView;
import com.example.developer.grocerylist.R;
import com.example.developer.grocerylist.api.GroceryListTableRow;
import com.example.developer.grocerylist.impl.GroceryListTableRowImpl;
public class GroceryList extends AppCompatActivity implements OnClickListener {
TextView textView = null;
GroceryListTableRowImpl groceryListTableRow = null;
Button add = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grocery_list);
textView = (TextView)findViewById(R.id.textview);
groceryListTableRow = (GroceryListTableRowImpl)findViewById(R.id.grocery_list);
add = (Button)findViewById(R.id.add);
add.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_grocery_list, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
groceryListTableRow.addRow();
}
}
When I boot up the App and click the button I get this
Process: com.example.developer.grocerylist, PID: 2353
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
at android.view.ViewGroup.addView(ViewGroup.java:3786)
at android.view.ViewGroup.addView(ViewGroup.java:3727)
at android.view.ViewGroup.addView(ViewGroup.java:3700)
at com.example.developer.grocerylist.impl.GroceryListTableRowImpl.addRow(GroceryListTableRowImpl.java:34)
at com.example.developer.grocerylist.activities.GroceryList.onClick(GroceryList.java:61)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I know this is a lot to take in. I have been scratching my head on this one. I have never made a compound view before. That might be evident. Any help would be greatly appreciated. Thanks in advance!
UPDATE When debugging when I get to the addView(createRow()) line things fail. It does not seem to be making it into the createRow() method.
As per my observation inside your createRow() method change and try this thing
ViewGroup parent = (ViewGroup)v.Parent;
return parent
since you have used merge there is parent viewgroup, so either return parent view or remove the parent using
parent.RemoveView(v);
return v;
Thanks to #njkz2
What fixed this for me was changing my onCreate() method to this.
private View createRow() {
View v;
LayoutInflater inflater = LayoutInflater.from(getContext());
v = inflater.inflate(R.layout.grocery_list_row,this,false);
return v;
}
Also I changed the class to extend TableLayout instead of LinearLayout to get the desired effect. This is because I was added the compound view (which is a LinearLayout) to my GroceryListTableRowImpl. So GroceryListTableRowImpl needed to be a TableLayout.
I'm doing this tutorial, but I'm having some trouble with understanding how to make this into one activity. (In the tutorial, you would have Main Activity and Display Message Activity, but for my purposes, I need it to be in one activity) I understand how everything works, but I just can't figure out how to make this into one activity. Any help is appreciated!
Here is the tutorial I'm working on: https://developer.android.com/training/basics/firstapp/building-ui.html
And I'll include my code below, but it's probably easier to see where I am in the tutorial (I'm at the step, "Starting Another Activity").
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText android:id="#+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="#string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_send"
android:onClick="sendMessage" />
</LinearLayout>
MainActivity.java
package com.example.helloworld;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.content.Intent;
import android.os.Build;
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
}
If you want to change the layout when a button is pressed and display hello world you can use your fragment PlaceholderFragment inside your MainActivity to display it
sample:
public void sendMessage(View view) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
Fragment:
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView tx = (TextView)rootView.findViewById(R.id.hello_world);
tx.setText(editText.getText().toString());
return rootView;
}
}
In your fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/start_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
I am making A Chat Application on Android.
These are some of the files
I'm trying to get the String(name) that is in the ListView. When I click the name, I want it to go to a new activity ChatBox. How would I get a String that the user clicks on?
I attempted a few times in freindslist.java for method contactOnClick() I'm guessing I just have to fix that somehow to be able to function the way I want it to. Because, It seems as if the contactOnClick() isn't connected right with the ListView.
FriendsList.Java:
package com.example.swagmessenger5;
import android.os.Bundle;
import android.app.ListActivity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ListView;
public class FriendsList extends ListActivity {
ListView listOfContacts;
static String data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_friends_list);
//create string names
String[] names = {"tim", "liz" , "ori" , "john" , "bryan","tim", "liz" , "ori" , "john" , "bryan","tim", "liz" , "ori" , "john" , "bryan" };
//get online status boolean
boolean[] status = {true, false, true, false, true, true, false, true, false, true,true, false, true, false, true };
//they should be intertwined, meaning boolean lined up with string.
MyArrayAdapter adapter = new MyArrayAdapter(this, names, status );
this.setListAdapter(adapter);
}
public void contactOnClick(View view){ //go to chat box with the talker name on top
//View myLayout = findViewById( R.id.lol );
listOfContacts = (ListView) findViewById( R.id.lol ); //need to et rigt text
listOfContacts.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
{
data = (String)arg0.getItemAtPosition(arg2);
}});
Intent intent = new Intent(this, ChatBox.class);
startActivity(intent);
}
//** code to make arrays go forever can keep adding.
/* public static void main(String[] args) {
int[] series = {4,2};
series = addElement(series, 3);
series = addElement(series, 1);
}
static int[] addElement(int[] a, int e) {
a = Arrays.copyOf(a, a.length + 1);
a[a.length - 1] = e;
return a;
} */
public void addfriend(View view){ //go to add friend page
Intent intent = new Intent(this, AddFriend.class);
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.friends_list, menu);
return true;
}
}
This is the layout with the include in it.
activity_friends_list.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/swag_plus"
android:onClick="addfriend" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/button1"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/button1"
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:text="#string/swag_list"
android:textAppearance="?android:attr/textAppearanceLarge" />
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/button1"
layout="#layout/activity_box_in_list_view"
android:onClick="contactOnClick"
android:id="#+id/lol" />
</RelativeLayout>
BoxInListView.java
package com.example.swagmessenger5;
import android.os.Bundle;
import android.app.ListActivity;
import android.view.Menu;
public class BoxInListView extends ListActivity {
//this is the friends list where it will inflate all the friends into the list veiw
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_box_in_list_view);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.box_in_list_view, menu);
return true;
}
}
This is the file where the ListView is made. And this is the file that is being included into the friendslit xml.
activity_box_in_list_view.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageView1"
android:padding="15dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="20sp"
android:textStyle="bold" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="14dp"
android:paddingTop="25dp"/>
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</RelativeLayout>
Here is My ArrayAdapter
the array adapter is inflating in box_in_list_view
MyArrayAdapter.java
package com.example.swagmessenger5;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MyArrayAdapter extends ArrayAdapter<String> {
private Context context;
private String[] names;
private boolean[] status;
public MyArrayAdapter(Context context, String[] names, boolean[] status) {
super(context, R.layout.activity_box_in_list_view, names);
this.context = context;
this.names = names; //names in array
this.status = status; //names in status
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_box_in_list_view, parent, false);
//Text view
TextView nameView = (TextView) rowView.findViewById(R.id.textView1); //set id to text view variable
ImageView onlineView = (ImageView) rowView.findViewById(R.id.imageView1); //set id to image view variable
nameView.setText(names[position]); //set textview(name) of the name in the right position
// Check the status if online or offline
boolean online = status[position];
if (online) //if online is true, the picture will be set to on
onlineView.setImageResource(android.R.drawable.button_onoff_indicator_on);
else //if online is false, the picture will be set to off
onlineView.setImageResource(android.R.drawable.button_onoff_indicator_off);
return rowView;
}
}
Set an OnClickListener for the view inside getView in the adapter. Also, you can set the name to be the tag of the rootview to make things easier. Then you can have code like this in the OnClickListener:
public void onClick(View v){
String name = (String)v.getTag();
doStuffWithName(name);
}