I need help for this load more RecycleView, I create 'Recyclerview', first, limit 5 data and showing, but when I scroll until the end no 'ProgressBar' showing and the next data now showing, I check the 'logcat' no error only warning
this my load more function
private void loadMore() {
arraylist.add(null);
mListadapter.notifyItemInserted(arraylist.size() - 1);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
arraylist.remove(arraylist.size() - 1);
int scrollPosition = arraylist.size();
mListadapter.notifyItemRemoved(scrollPosition);
int currentSize = scrollPosition;
int nextLimit = currentSize + 5;
Log.e("currentSize",""+currentSize);
Log.e("nextLimit",""+nextLimit);
if(nextLimit <= DataNoteImformation.id.length) {
while (currentSize + 1 <= nextLimit) {
DataNote wp2 = new DataNote(
DataNoteImformation.id[currentSize],
DataNoteImformation.branchArray[currentSize],
DataNoteImformation.assetcodeArray[currentSize],
DataNoteImformation.customerArray[currentSize],
DataNoteImformation.licenseplateArray[currentSize]
);
arraylist.add(wp2);
currentSize++;
}
}else {
while (currentSize + 1 <= DataNoteImformation.id.length) {
DataNote wp2 = new DataNote(
DataNoteImformation.id[currentSize],
DataNoteImformation.branchArray[currentSize],
DataNoteImformation.assetcodeArray[currentSize],
DataNoteImformation.customerArray[currentSize],
DataNoteImformation.licenseplateArray[currentSize]
);
arraylist.add(wp2);
currentSize++;
}
}
mListadapter.notifyDataSetChanged();
isLoading = false;
}
}, 2000);
}
and the warning in logcat
W/RecyclerView: Cannot call this method in a scroll callback. Scroll callbacks might be run during a measure & layout pass where you cannot change theRecyclerView data. Any method call that might change the structure of the RecyclerView or the adapter contents should be postponed to the next frame.
and this example data
public class DataNoteImformation {
public static String[] branchArray = {"Depok","Jakarta","Bekasi","Jakarta","Jakarta","Bekasi","Bogor","Jakarta","Bekasi","Jakarta"};
public static String[] assetcodeArray = {"0092","0084","0091","0084","0084","0078","0089","0073","0027","0021"};
public static String[] customerArray = {"Kevin Sanjaya","Indah Permata","Riyan","Puri Setiawan","Herman","Iwan","Ratna","Agus","Danang","Ujang"};
public static String[] licenseplateArray = {"B 9829 SK","B 8294 LK","B 9090 NBA","B 7627 SKA","B 7637 SAK","B 6763 KIK","F 7287 NB","F8792KI","B8273KD","B7728KSI"};
public static String[] id = {"1","2","3","4","5","6","7","8","9","10"};
}
how to fix this.
Related
Im currently working on a little mobile game in which you throw spears at targets, and depending on how many spears you have left at the end of the level you get between one and three Runes (similar to the Star scoring sytem in Angry Birds). The plan is to save the runes and use them to unlock different spear variants in the Main Menu.
At the moment you can see how many runes you got after completeing the level, but the values are not yet being saved.
My question is, how would I go about saving the Runes after each Level? Any ideas? You can see the part of the script Im using for that below. Thanks in advance.
public int totalRunes = 0;
public GameObject rune1;
public GameObject rune2;
public GameObject rune3;
public void RuneCollection()
{
if (currentSpears >= 2)
{
Debug.Log("3 runes collected!");
rune3.SetActive(true);
totalRunes = 3;
}
else if (currentSpears >= 1)
{
Debug.Log("2 runes collected!");
rune2.SetActive(true);
totalRunes = 2;
}
else
{
Debug.Log("1 rune collected!");
rune1.SetActive(true);
totalRunes = 1;
}
}
I would use Unitys PlayerPrefs System.
Example:
Setting Score:
public Text score;
int currentscore = 0;
Increasing Score:
currentscore += 1;
score.text = currentscore.ToString();
Setting HighScore and Loading Menu:
GameManager.SetHighScore(currentscore);
SceneManager.LoadScene("Menu");
Functions to Load/Change PlayerPrefs:
void Start()
{
highscore.text = PlayerPrefs.GetInt("HighScore", 0).ToString();
}
public static void SetHighScore(int score)
{
if (score > PlayerPrefs.GetInt("HighScore", 0))
{
PlayerPrefs.SetInt("HighScore", score);
}
}
Your Code adapted to PlayerPrefs:
public int currentSpears = 0;
public GameObject rune1;
public GameObject rune2;
public GameObject rune3;
void Start()
{
currentSpears = PlayerPrefs.GetInt("CurrentSpears", 0).ToString();
}
public static void IncreaseSpears()
{
int spears = PlayerPrefs.GetInt("CurrentSpears", 0);
PlayerPrefs.SetInt("CurrentSpears", spears++);
}
public void RuneCollection()
{
if (currentSpears >= 2)
{
Debug.Log("3 runes collected!");
rune3.SetActive(true);
totalRunes = 3;
}
else if (currentSpears >= 1)
{
Debug.Log("2 runes collected!");
rune2.SetActive(true);
totalRunes = 2;
}
else
{
Debug.Log("1 rune collected!");
rune1.SetActive(true);
totalRunes = 1;
}
}
You can save your data with PlayerPrefs for some single values or PersistentDataPath for some multiple values such as a class. Find out more with this link, and you can use them as below.
PlayerPrefs:
private int score = 0;
//set value
PlayerPrefs.SetInt("Score", score);
//get value
private int savedScore = PlayerPrefs.GetInt("Score");
PersistentDataPath:
private string savedName;
private int savedHealth;
private string loadedName;
private int loadedHealth;
public void Save(){
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/FileName.dat",
FileMode.Create);
PlayerClass newData = new PlayerClass();
newData.health = savedHealth;
newData.name = savedName;
bf.Serialize(file, newData);
file.Close();
}
public void Load(){
if (File.Exists(Application.persistentDataPath + "/FileName.dat")){
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/FileName.dat", FileMode.Open);
ObjData newData = (ObjData)bf.Deserialize(file);
file.Close();
loadedHealth = newData.health;
loadedName = newData.name;
}
}
[Serializable]
class PlayerClass{
public string name;
public int health;
}
My current data structure is as follows:
public class MyDataTemplate {
long occurenceTime;
int val1;
int val2;
public MyDataTemplate(Long nanoTime, int val1, int val2) {
this.occurenceTime = nanoTime;
this.val1 = val1;
this.val2 = val2;
}
}
List<MyDataTemplate> myData = new ArrayList <MyDataTemplate>();
The occurenceTime(long) above represents the system time which I obtain in Android using System.nanoTime()
If data arrived sequentially by time, I could have very well used the above data structure to store data as and when it arrives:
newOccurence = new MyDataTemplate(System.nanoTime(), 42, 55)
myData.add(newOccurence);
However, since data does not arrive sequentially, I may get a new occurrence earlier than an old occurrence.
My task is to ensure that the myData contains data in ascending order of time, irrespective of when it arrives.
How can I ensure that ?
Froggy Oat...
I have made an attempt which seems to loosely illustrate a potential "solution:"
public class MainActivity extends AppCompatActivity {
public class MyDataTemplate {
long occurenceTime;
int val1;
int val2;
public MyDataTemplate(Long nanoTime, int val1, int val2) {
this.occurenceTime = nanoTime;
this.val1 = val1;
this.val2 = val2;
}
}
class SortByNanoTime implements Comparator<MyDataTemplate> {
public int compare(MyDataTemplate a, MyDataTemplate b) {
if (a.occurenceTime < b.occurenceTime)
return -1;
else if (a.occurenceTime > b.occurenceTime)
return +1;
else
return 0;
}
}
List<MyDataTemplate> myData = new ArrayList<MyDataTemplate>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myData.add(new MyDataTemplate((long) 30000.2341, 2, 3));
myData.add(new MyDataTemplate((long) 234234.234, 3, 4));
myData.add(new MyDataTemplate((long) 11234234.234, 3, 4));
myData.add(new MyDataTemplate((long) 4.234, 3, 4));
Collections.sort(myData, new SortByNanoTime());
for (MyDataTemplate tempVar : myData) {
Log.i("XXX", "" + tempVar.occurenceTime);
}
}
}
You will want to use a priority queue or a tree set - - since your timestamps are nanos, the Comparator is simply a normal Integer compare.
please help guys,, here is my code for my simple gallery android app for external images
I made the loader is in array , and I made swiping action ,,
what I think I have to chose Wither removechild nor enter frame but I can't apply it
coz when publish, things is mixed up and swiping is not working well :(
could you please help me to fix it it's AS3 at Flash 5.5
var pictureArray:Array = new Array;
var loader1 = new Loader();
loader1.load(new URLRequest("1.jpg"));
pictureArray.push(loader1);
var loader2 = new Loader();
loader2.load(new URLRequest("2.jpg"));
pictureArray.push(loader2);
var loader3 = new Loader();
loader3.load(new URLRequest("3.jpg"));
pictureArray.push(loader3);
addChild(pictureArray[0]);
pictureArray[0].x = 0; pictureArray[0].y = 0;
var n:int = 0;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
var currentGalleryItem:Number = 1;
var totalGalleryItems:Number = 3;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, fl_SwipeToGoToNextPreviousFrame);
function fl_SwipeToGoToNextPreviousFrame(event:TransformGestureEvent):void
{
if(event.offsetX == 1)
{
if(currentGalleryItem > 1){
currentGalleryItem--;
slideRight();
removeChild(pictureArray[n]);
n = n+1;
if (n>pictureArray.length - 1)
n=0;
addChild(pictureArray[n]);
pictureArray[n].x = 0; pictureArray[n].y = 0;
}
}
else if(event.offsetX == -1)
{
if(currentGalleryItem < totalGalleryItems){
currentGalleryItem++;
slideLeft();
removeChild(pictureArray[n]);
n = n-1;
if (n<0)
n=pictureArray.length - 1;
addChild(pictureArray[n]);
pictureArray[n].x = 0; pictureArray[n].y = 0;
}
}
}
var slideCounter:Number = 0;
function slideLeft(){
(pictureArray[n]).addEventListener("enterFrame", moveGalleryLeft);
}
function slideRight(){
(pictureArray[n]).addEventListener("enterFrame", moveGalleryRight);
}
function moveGalleryLeft(evt:Event){
(pictureArray[n]).x -= 48;
slideCounter++;
if(slideCounter == 5){
(pictureArray[n]).removeEventListener("enterFrame", moveGalleryLeft);
slideCounter = 0;
}
}
function moveGalleryRight(evt:Event){
(pictureArray[n]).x += 48;
slideCounter++;
if(slideCounter == 5){
(pictureArray[n]).removeEventListener("enterFrame", moveGalleryRight);
slideCounter = 0;
}
}
I would recommend load images on demand, for animation use some tweening engine(in my example It's TweenLite), and dispose previous frames, It's mobile device you should honour memory. Most of other comments in the code, I don't have ability to test in on the device, also It's not complete code, It's only carcass ;)
package {
import com.greensock.TweenLite;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.TransformGestureEvent;
import flash.net.URLRequest;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
public class StackOverflow extends Sprite {
private var _loader:Loader;
private var _images:Array;
private var _position:int;
private var _currentFrame:Sprite;
public function StackOverflow() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function setup():void {
_loader = new Loader();
_images = ["1.jpg", "2.jpg", "3.jpg"];
_currentFrame = new Sprite();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadImage);
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe);
addChild(_currentFrame);
loadImageAtPosition(_position);
}
private function disposeFrame(frame:Sprite):void {
//You can cache loaded bitmaps, or dispose them
removeChild(frame);
var bitmap:Bitmap = frame.getChildAt(0) as Bitmap;
bitmap.bitmapData.dispose();
}
private function loadImageAtPosition(index:int):void {
//By using one loader for all tasks, you will have only last requested image
_loader.load(new URLRequest(_images[index]));
}
private function offsetScreenOn(direction:Number):void {
var offset:int;
var start:int;
if (direction > 0) {
//Direction to the right side
offset = stage.stageWidth;
} else {
//Direction to the left side
offset = -stage.stageWidth;
}
//Starting position for new frame
start = -offset;
//TweenLite is great for such task
if (_currentFrame != null) {
//Remove previous frame
TweenLite.to(_currentFrame, 0.8, {x: offset, onComplete: disposeFrame, onCompleteParams: [_currentFrame]});
}
//Initialise new frame, fill them, decor them...
_currentFrame = new Sprite();
if (_currentFrame != null) {
addChild(_currentFrame);
_currentFrame.x = start;
//Animate in new frame
TweenLite.to(_currentFrame, 0.8, {x: (start + offset)});
}
}
private function onLoadImage(e:Event):void {
if (_currentFrame != null) {
var image:Bitmap = _loader.content as Bitmap;
if (image != null) {
image.smoothing = true;
_currentFrame.addChild(image);
//Resize, displace image for your needs
//Add appear animation if you want
}
}
}
//If you want, you can postpone swipe, while in state of transition
private function onSwipe(e:TransformGestureEvent):void {
//Left to Right swipe
if (e.offsetX == 1) {
if (--_position < 0) {
_position = _images.length;
}
offsetScreenOn(e.offsetX);
loadImageAtPosition(_position);
}
//Right to Left swipe
if (e.offsetX == -1) {
if (++_position >= _images.length) {
_position = 0;
}
offsetScreenOn(e.offsetX);
loadImageAtPosition(_position);
}
}
private function onAdded(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
setup();
}
}
}
check this out
simple android gallery
it a basic implementation of a gallery app, it makes use of the android media provider to actually get images in the device storage and provides an image slider by using a viewPager and a RecyclerView as indicator, I will outline the important parts here, you can use a RecyclerView and a Recycler Adapter to display your images
public class picture_Adapter extends RecyclerView.Adapter<PicHolder> {
private ArrayList<pictureFacer> pictureList;
private Context pictureContx;
private final itemClickListener picListerner;
/**
*
* #param pictureList ArrayList of pictureFacer objects
* #param pictureContx The Activities Context
* #param picListerner An interface for listening to clicks on the RecyclerView's items
*/
public picture_Adapter(ArrayList<pictureFacer> pictureList, Context pictureContx,itemClickListener picListerner) {
this.pictureList = pictureList;
this.pictureContx = pictureContx;
this.picListerner = picListerner;
}
#NonNull
#Override
public PicHolder onCreateViewHolder(#NonNull ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(container.getContext());
View cell = inflater.inflate(R.layout.pic_holder_item, container, false);
return new PicHolder(cell);
}
#Override
public void onBindViewHolder(#NonNull final PicHolder holder, final int position) {
final pictureFacer image = pictureList.get(position);
Glide.with(pictureContx)
.load(image.getPicturePath())
.apply(new RequestOptions().centerCrop())
.into(holder.picture);
setTransitionName(holder.picture, String.valueOf(position) + "_image");
holder.picture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
picListerner.onPicClicked(holder,position, pictureList);
}
});
}
#Override
public int getItemCount() {
return pictureList.size();
}
}
the method below gets all the device images and load the info for each image in a imageFacer object which you can use to populate the recyclerview adapter
see the full post in the link above
public ArrayList<pictureFacer> getAllImagesByFolder(String path){
ArrayList<pictureFacer> images = new ArrayList<>();
Uri allVideosuri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Images.ImageColumns.DATA ,MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE};
Cursor cursor = ImageDisplay.this.getContentResolver().query( allVideosuri, projection, MediaStore.Images.Media.DATA + " like ? ", new String[] {"%"+path+"%"}, null);
try {
cursor.moveToFirst();
do{
pictureFacer pic = new pictureFacer();
pic.setPicturName(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)));
pic.setPicturePath(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)));
pic.setPictureSize(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)));
images.add(pic);
}while(cursor.moveToNext());
cursor.close();
ArrayList<pictureFacer> reSelection = new ArrayList<>();
for(int i = images.size()-1;i > -1;i--){
reSelection.add(images.get(i));
}
images = reSelection;
} catch (Exception e) {
e.printStackTrace();
}
return images;
}
I would like to say thanks first to you all..
I have made a code to generate sprite by using Runnable.
But it only executes the last runnable that I wrote.
Here's the code:
public class LevellingManager {
// ======================== //
// ======================== //
// THE PATH METHOD //
// ======================== //
// ======================== //
public static void path() {
currType = Leveling2.TYPE_DIGGER;
mHandler.post(mStartDigger);
// === NOT EXECUTED === //
generateSprite(Leveling2.TYPE_ROCK, 10, 2000, 2000, LevellingManager.EASY);
// === EXECUTED === //
generateSprite(Leveling2.TYPE_WORM, 8, 3000, 1000, LevellingManager.HARD);
}
The generateSprite() method
public static void generateSprite(int type, int nSprts, int delayPerSprt,
int delayPerBtch, int[] difficulty) {
currType = type;
switch (type) {
case Leveling2.TYPE_ROCK:
System.out.println("Awalnya : " + GameResources2.lastIndexRock);
// ---- Set Generate Data ---- //
currIndex = 1 + GameResources2.lastIndexRock;
currList= GameResources2.listRockToBeAdded;
currLastIndex = GameResources2.lastIndexRock;
currMaxCpcty= GameResources2.MAX_ROCK;
// --- Method to Set the position, speed & delay per sprite ---- //
set(nSprts, delayPerBtch, delayPerSprt, difficulty);
mHandler.postDelayed(mStartRock, currDelay);
GameResources2.lastIndexRock = currLastIndex;
break;
case Leveling2.TYPE_WORM:
// ---- Set Generate Data ---- //
currIndex = 1 + GameResources2.lastIndexWorm;
currList=GameResources2.listWormToBeAdded;
currLastIndex = GameResources2.lastIndexWorm;
currMaxCpcty = GameResources2.MAX_WORM;
// --- Method to Set the position, speed & delay per sprite ---- //
set(nSprts, delayPerBtch, delayPerSprite, difficulty);
mHandler.postDelayed(mStartWorm, currDelay);
GameResources2.lastIndexWorm = currLastIndex;
break;
}
}
Here comes the Runnable code:
public static Runnable mStartRock = new Runnable() {
public void run() {
installAttach(this);
}
};
public static Runnable mStartWorm = new Runnable() {
public void run() {
installAttach(this);
}
};
And here is a method that will be executed inside the Runnable.
installAttach() method:
private static void installAttach(Runnable r) {
System.out.println("Lewat sini, type : " + currType);
currSpriteGen = currList.get(currIndex);
currSpriteGen
.registerEntityModifier(new SequenceEntityModifier(
new MoveModifier(currSpeed,
currSpriteGen.getX(),
currSpriteGen.getX(),
GameResources2.CAMERA_HEIGHT,
GameResources2.POSITION_DIGGER_HEIGHT)));
currSpriteGen.setVisible(true);
if (currSpriteGen.getParent() == null)
GameResources2.scene.attachChild(currSpriteGen);
else
currLastIndex = currIndex;
switchLastIndex();
if (currIndex == currMaxCpcty - 1) {
currNSprts = currNSprts - currIndex;
currIndex = -1;
}
System.out.println("Index : " + currIndex);
System.out.println("Max index : " + currMaxCpcty);
++currIndex;
// --- For looping ---//
if (currIndex < currNSprts) {
mHandler.postDelayed(r, currDelay);
}
}
So when I call the LevellingManager.path() method at onLoadScene(),
only the last generate method that executed.
Please help me.
Thank you.
Apparently there is a place for only one Runnable. I believe I have a workaround for that. Create a class RunnableBatch whose instance will contain an array of Runnables. It will have a method add(Runnable r) that will
1) add the Runnable to the array and
2) create a new Runnable that will contain something like for (Runnable r : runnableArray) {r.run();}
Here is my class it goes in to infinite loop please check where I am going wrong ... I am trying to get id's of image view making it random and then trying to set text view with imageview's description
public class Object {
int ObectIds[];
LinearLayout HUDDisplay;
int HudDisplayText[] = {R.id.HUD_Text_Element1,
R.id.HUD_Text_Element2,
R.id.HUD_Text_Element3,
R.id.HUD_Text_Element4,
R.id.HUD_Text_Element5,
R.id.HUD_Text_Element6,
R.id.HUD_Text_Element7};
TextView[] text;
View v;
Object(Context context,View vs) {
super();
ObectIds = new int[8];
HUDDisplay=(LinearLayout)vs.findViewById(R.id.HUD_Display);
for (int i = 0; i < 8; i++) {
ObectIds[i] = (R.id.imageView1) + i;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
randomize(vs);
setTextView();
}
public void setTextView()
{
for(int i=0;i<8;++i)
{
text[i] =(TextView) HUDDisplay.findViewById(HudDisplayText[i]);
text[i].setText(v.getContentDescription());
}
}
public void randomize(View vs) {
for (int i = 0; i < 8; i++) {
while (true) {
shuffleArray(ObectIds);
v = vs.findViewById(ObectIds[i]);
Log.d("Image", "Image Id's " + v.getId());
if (!v.isClickable()) {
v.setClickable(true);
break;
}
}
}
}
static void shuffleArray(int[] ar) {
Random rnd = new Random();
for (int i = ar.length - 1; i >= 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
Hey man I observed your code & found error in code :
Please compare following code with your code... Constructor
for (int i = 0; i < 8; i++) {
ObectIds[i] = **HudDisplayText[i]**;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
You have a while(true) loop that you break from only if v is not clickable. What happens if v is clickable? Nothing in your code ever sets v to not clickable, and views by default are not clickable.
I notice you're using the Object class. Object is basically the root of which all classes extend. If you call super() in the constructor, it will call the super class constructor, which is Object as well... That might be the problem.
Try looking for tutorials on how to start with Java/Android, since you are also using variables names that are not recommended. E.g. in Java,:
- a Class starts with a Capital
- a variable, starts with lowercase
- a function starts with lowercase:
public class Captial
{
private int anIntegerStartsWithLowerCase;
private void functionsAreLowerCaseAsWell()
{
}
}
Also take a look at your loop... It looks like it is never ending