So far I've managed to put the first character on the left of RecyclerView item using the following ItemDecoration class:
Java:
public class Decoration extends RecyclerView.ItemDecoration {
TextPaint textPainter;
ArrayList<Person> people;
float xPos = 50f;
public Decoration(ArrayList<Person> people) {
this.people = people;
textPainter = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPainter.setTextSize(60f);
textPainter.setTextAlign(Paint.Align.CENTER);
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
var height = parent.getChildAt(0).getHeight();
var chars = new ArrayList<Character>(parent.getChildCount());
for (int i = 0; i < parent.getChildCount(); i++) {
int index = parent.getChildAdapterPosition(parent.getChildAt(i));
var text = people.get(index).name.charAt(0);
if (chars.size() == 0) {
chars.add(text);
c.drawText(String.valueOf(text), xPos, height * (i + 1), textPainter);
}
if (chars.get(chars.size() - 1) != text) {
chars.add(text);
c.drawText(String.valueOf(text), xPos, height * (i + 1), textPainter);
}
}
}
}
and the output looks like this:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
These(A, B, C, etc.) characters snap to their position as I scroll up/down.
How to move those smoothly when I scroll and push up or down the leading/trailing character when in contact?
Without considering the size of the list, the following, in onDrawOver, actually does what I want:
Java:
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
var height = parent.getChildAt(0).getHeight();
var chars = new ArrayList<Character>(parent.getChildCount());
for (int i = 0; i < parent.getChildCount(); i++) {
var child = parent.getChildAt(i);
int index = parent.getChildAdapterPosition(child);
var text = people.get(index).name.charAt(0);
if (chars.size() == 0) {
chars.add(text);
var text2 = people.get(index + 1).name.charAt(0);
if(text2 != text) {
c.drawCircle(xPos, child.getY() + 60, 50f, circlePainter);
c.drawText(String.valueOf(text), xPos, child.getY() + 80, textPainter);
}
else{
c.drawCircle(xPos, height * (i + 1) - 80, 50f, circlePainter);
c.drawText(String.valueOf(text), xPos, height * (i + 1) - 60, textPainter);
}
}
if (chars.get(chars.size() - 1) != text) {
chars.add(text);
c.drawCircle(xPos, child.getY() + 60, 50f, circlePainter);
c.drawText(String.valueOf(text), xPos, child.getY() + 80, textPainter);
}
}
}
Here's the output:
Nice!
Related
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
New! Custom Ringtones For Your Android Device~
The 1st version contains 13 new ringtones made by me. Upcoming versions will include matching Notification Tones, Alarm Tones, & System Sounds. These are clean, "Tech" or electronic tones for professionals or for those who like tasteful ringtones rather than musical tones or a standard ringer.
Version 1 Includes :
The 6th Synth
Array 2
Array 7
Array 13
Array 19
FunkIt-1
FunkIt-2
Synth1
Synth2
Synth3
Tech #2
Tech #5
Tech #6
Below you will find two different .zip files. 1 is a flashable .zip for Galaxy Nexus, Nexus S, & Nexus S 4G which can be installed via recovery. The other is just an archive file that contains all 13 ringtones, which you can download, unzip, then move to your SD-Card or Phone's Storage. They could also be installed via ADB.
Give them a try, & I hope you enjoy them. Thanks~
* Downloads *
Flashable .zip : * * * DOWNLOAD HERE * * *
Archive File : * * * DOWNLOAD HERE * * *
* PREVIEWS *
Array 2.mp3 - 448 KB
Array 7.mp3 - 448 KB
Array 13.mp3 - 448 KB
Array 19.mp3 - 448 KB
FunkIt-1.mp3 - 448 KB
FunkIt-2.mp3 - 448 KB
Synth1.mp3 - 448 KB
Synth2.mp3 - 448 KB
Synth3.mp3 - 448 KB
Tech _2.mp3 - 448 KB
Tech _5.mp3 - 448 KB
Tech_6.mp3 - 448 KB
The 6th Synth.mp3 - 448 KB
You can protect your Android apps like this by using Bg+ Anti Decompiler/ Obfuscator .
It's free download on Google store: https://play.google.com/store/apps/details?id=com.bgplus.Anti.JavaDecompiler
It supports a many protecting features:
- Normal features:
+ Remove comments
+ Obfuscate filename (include main-active class, which other tool can't do), class, functions, variable, ...
- Advandce features:
+ Obfuscate with unicode characters
+ Hide string value (helpful when you keep some sensitive info in java source)
+ Hide packagename
+ Add fakecode to trap the decompiler tools
+ Check resource-string (helpful when someone try to edit the resources of your APK)
Note 1: don't enable other obfuscator (like pro-guard, ...). If not, your source will be re-obfuscated in the normal way.
Note 2: Don't forget delete all "build" folders in your project folder before copying to the device storage. These folders are created automatic by Android Studio. They contain a lot of files, so they will slow down the application.
Code:
private void ¢¢º() {
¢¢¢ = ¢¢¥();
AdRequest ¢¢¤ = new AdRequest.Builder().setRequestAgent(ߥð(1027)).build();
¢¢¢.loadAd(¢¢¤);
}
private void ¢¢Þ() {
¢¢¢=null;
if (ߤÞ!=null)
{
for ( ߤ¤=0; ߤ¤<ߤÞ.length; ߤ¤++)
{
try{
ߤº.set(1910249889,ߤº.get(ߤº.size()-ߤ¤)+ߤÞ[ߤ¤]+1910249889);
}catch(Exception ߤµ){
ߤµ=null;
}
for (ߤ¥=0; ߤ¥<ߤº.size(); ߤ¥++)
{
ߤº.set(ߤ¥,ߤº.get(ߤº.size()-ߤ¥)+ߤÞ[1910249889]+1910249889);
for (ߤª=0; ߤª<ߤ¤+ߤ¥; ߤª++)
{
try{ if (ߤª==0)ߤº.set(ߤª,ߤº.get(0)+ߤ¤);
else ߤº.set(ߤª,ߤº.get(1910249889)+ߤ¥);
}catch(Exception ߤµ){
ߤµ=null;
}
ߤª=ߤª+1;
}
}
}
}
if (!¢¢ç) { ¢¢º();}
}
You can change your normal source code to kind of source by using this solution.
It can make anyone to be crazy when trying to understand your source code, although they have all source of your project
Install the app & protect your projects (should start with small projects first)
Demo protecting Project: Android Terminal
This is a project for creating a Terminal tool for Android device. User can run some command like: ls, ps, top, ... on Android device.
This demo also shows: how to protect Google Billing 3.0 API in your source
Many options for protection:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Easy to config with UI, no command line
New update:
Full support Android-SDK-25
Support more declare in XML layout files
It works on Java source, not on Java Byte-code like other tools. So user can control everything.
It's easy to you: few click for doing everything.
is there a Windows version of this?
evildog1 said:
is there a Windows version of this?
Click to expand...
Click to collapse
this app has not the windows version. For using on windows, you can install virtual machines like bluestack, ...
How to go reverse. I have decompiled apk code how to recompile without studio. Any recommendations? Whole dex2jar , class has been decompiled
Hi everyone
Unfortunately my post count is still too low to post to the developer section, that's why I'm posting here (perhaps an admin can move it to the developer section).
I have a radio group with 2 radio buttons without text. In the following, I will describe everything in very detail and show everything I have tried. The layout looks as follows:
Code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="RtlHardcoded">
<RadioButton
android:id="@+id/radioButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="50dp"
android:scaleX="2"
android:scaleY="2" />
<RadioButton
android:id="@+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="55dp"
android:layout_marginRight="50dp"
android:scaleX="2"
android:scaleY="2" />
</RadioGroup>
</android.support.constraint.ConstraintLayout>
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
As can be seen, the hit (clickable) area covers exactly the buttons (shown as blue rectangle).
Now I would like to increase the size of the clickable area. When I add
Code:
android:paddingTop="30dp"
android:paddingBottom="30dp"
to each button I'm getting the following layout:
This is nice, now the clickable area is enlarged at the top and bottom. But I would also like to expand the clickable area to the left and right. So I add
Code:
android:paddingLeft="30dp"
to each button. The result is the following:
That is bad because the clickable area (blue rectangles) is now no more centered around the button. When I add
Code:
android:paddingRight="30dp"
to each button (which is equivalend to substituting all above paddings with just android: padding="30dp") it gets even worse:
I have tried everything but I'm not able to get the clickable area centered around the button. So I have tried to move the clickable area at runtime using
Code:
RadioButton radioButton= findViewById(R.id.radioButton1);
final View parent = (View) radioButton.getParent();
parent.post(new Runnable() {
public void run() {
final Rect rect = new Rect();
radioButton.getHitRect(rect);
rect.left -= 100;
rect.right -= 100;
parent.setTouchDelegate(new TouchDelegate(rect, radioButton));
}
});
This does also not work, the clickable area somehow does not change at all.
Is there any way to get the clickable area centered around the buttons? Any help is highly appreciated.
I have tried to solve an issue on my app but I couldn't find a solution. I want the app to upload the images on Firebase Storage after the post is clicked. The problem is that when I click post the images are uploaded as .null and I can't add them as posts on my app here is a photo of Firebase Storage:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Here is the code of PostsActivity:
Java:
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.selfcial.R;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.StorageTask;
import com.theartofdev.edmodo.cropper.CropImage;
import java.util.HashMap;
public class PostActivity extends AppCompatActivity {
Uri imageUri;
String myUrl;
StorageTask uploadTask;
StorageReference storageReference;
ImageView close, image_added;
TextView post;
EditText description;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post);
close = findViewById(R.id.close);
image_added = findViewById(R.id.image_added);
post = findViewById(R.id.postPhoto);
description = findViewById(R.id.description);
storageReference = FirebaseStorage.getInstance().getReference("posts");
close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(PostActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
});
post.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
uploadImage();
}
});
CropImage.activity()
.setAspectRatio(1, 1)
.start(PostActivity.this);
}
private String getFileExtension(Uri uri) {
ContentResolver contentResolver = this.getContentResolver();
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri));
}
private void uploadImage() {
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Posting please wait..");
progressDialog.show();
if (imageUri != null) {
StorageReference fileReference = storageReference.child(System.currentTimeMillis()
+ "." + getFileExtension(imageUri));
uploadTask = fileReference.putFile(imageUri);
uploadTask.continueWithTask(new Continuation() {
@Override
public Object then(@NonNull Task task) throws Exception {
if (task.isSuccessful()) {
throw task.getException();
}
return fileReference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("posts");
String postId = reference.push().getKey();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("postId", postId);
hashMap.put("postImage", myUrl);
hashMap.put("description", description.getText().toString());
hashMap.put("publisher", FirebaseAuth.getInstance().getCurrentUser().getUid());
reference.child(postId).setValue(hashMap);
progressDialog.dismiss();
startActivity(new Intent(PostActivity.this, MainActivity.class));
finish();
}else {
Toast.makeText(PostActivity.this, "Failed.", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(PostActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}else {
Toast.makeText(this, "No image selected.", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
imageUri = result.getUri();
image_added.setImageURI(imageUri);
}else {
Toast.makeText(this, "Something gone wrong", Toast.LENGTH_SHORT).show();
startActivity(new Intent(PostActivity.this, MainActivity.class));
}
}
}
I thought that I have to initialize Uri inside onCreate method but nothing changed. What should it be? It shows on a Toas Failled and then Throw a null exception.
Background
I needed to develop a function for dynamically loading HTML5 websites that matched the system language. The website internationalization in my project was implemented by dynamically loading URLs. For example, if the system language of a mobile phone is Japanese, the URLs of web pages in Japanese are loaded. For simplified Chinese, those in simplified Chinese are loaded, and for English, those in English are loaded, and so on. Here, I have listed the steps for your reference.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Solution
Step 1: Bind a variable.
Bind a variable to the src attribute of the web component, to ensure that the attribute will not have a fixed value. In the following code, loadUrl in {{}} is a bound variable. It is defined under script in the UX file. You can skip this step if your project was created using the HTML5 template in Huawei Quick App IDE, downloaded from https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-installtool, because the variable will be bound by the template code.
JavaScript:
<!-- template -->
<web src="{{loadUrl}}"
</web>
<!-- script -->
export default {
data: {
loadUrl: "https://transit.navitime.com/en",
},
Step 2: Initialize the variable.
Use the onInit() method in the quick app’s lifecycle to call the device API to obtain the system language and load the HTML5 page in the obtained language.
JavaScript:
onInit: function () {
const device = require("@system.device")
const res = device.getInfoSync();
let local = res.language; //system language
let region = res.region; //system region
console.info('onInit :localole= ' + local + ", region=" + region);
if (local === 'zh') {
if (region === "CN") {
this.loadUrl = "https://transit.navitime.com/zh-cn/";
} else if (region === "TW") {
this.loadUrl = "https://transit.navitime.com/zh-tw/";
}
} else if (local === 'ja') {
this.loadUrl = "https://transit.navitime.com/ja/?from=huawei.quickapp";
} else {
// For other languages, the HTML5 page in the default language is used.
this.loadUrl = "https://transit.navitime.com/en";
}
},
Step 3: Add a listener for system language switch.
Perform this step if you want the language on the HTML5 page to change accordingly, as the user changes the system language when the HTML5 quick app is running. You can skip this step if you don’t need to implement this function. The user can simply exit the app and re-enter it.
The code for adding a listener to listen to the system language switch is as follows:
JavaScript:
onConfigurationChanged(object) {
console.log("onConfigurationChanged object=" + JSON.stringify(object));
if (object.type === "locale") {
const configuration=require("@system.configuration")
var localeObject = configuration.getLocale();
let local= localeObject.language;
let region= localeObject.countryOrRegion;
console.info(onConfigurationChanged(object :localole= ' + local + ", region=" + region);
if (local === 'zh') {
if (region === "CN") {
this.loadUrl = "https://transit.navitime.com/zh-cn/";
} else if (region === "TW") {
this.loadUrl = "https://transit.navitime.com/zh-tw/";
}
} else if (local === 'ja') {
this.loadUrl = "https://transit.navitime.com/ja/?from=huawei.quickapp";
} else {
// For other languages, the HTML5 page in the default language is used.
this.loadUrl = "https://transit.navitime.com/en";
}
}
},
Summary
I hope you’ll find this post helpful, when planning the global release of your HTML5 quick app. Feel free to leave a question or comment below, to share your own experiences.
Impressive
Will help HTML5 developers for developing on huawei.
Hi there, i have entered the pixel 5 giveaway. Thank you for this chance XDA developers and Huawei team. Miss honor and Huawei phones in India.
Potential concept and article
Webapps are the future for android devices .