I'm building a ProgressBar dynamically at Runtime, and the Progressar is not filled on API 19 only, it works on higher APIs, the green bar that represent the percentage does not appear.
Why it doesn't work on API 19 ?
private ProgressBar drawProgressBar(MatiereProgression mat) {
ProgressBar progress = new ProgressBar(mContext, null, R.style.Widget_AppCompat_ProgressBar_Horizontal);
LinearLayout.LayoutParams progressLayout = new LinearLayout.LayoutParams(0, dpToPx(4));
progressLayout.weight = 11;
progressLayout.gravity = Gravity.CENTER_VERTICAL;
progress.setLayoutParams(progressLayout);
progress.setIndeterminate(false);
progress.setMax(100);
progress.setMinimumHeight(0);
progress.setMinimumWidth(150);
progress.setProgress(mat.mProgress);
progress.setProgressDrawable(ContextCompat.getDrawable(mContext, R.drawable.progressbar));
return progress;
}
I found the bug, it was the last lines, on API 19 you need to care about the line order between "setProgressDrawable" and "setProgress", it worked for me.
progress.setLayoutParams(progressLayout);
progress.setIndeterminate(false);
progress.setMax(100);
progress.setProgressDrawable(ContextCompat.getDrawable(mContext, R.drawable.progressbar));
progress.setMinimumHeight(0);
progress.setMinimumWidth(150);
progress.setProgress(mat.mProgress);
Related
I am currently creating an Android app that I want to support multiple screen sizes/densities. When I set up layouts in xml, everything looks fine across different screen sizes. However, there are rows I need to add programatically.
Whenever I add the rows, I can't seem to get things to look consistent across different devices. I believe using the dp unit when settings up heights, widths in xml, along with wrap_content and match_parent when appropriate, have allowed things to easily translate between different devices.
Programatically, when I try to set a layout height/width, I have been trying to convert the anticipated dp value to a pixel value. I've done so using this:
public static int convertToPixels(int value) {
Resources resources = mContext.getResources();
int x = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,value,resources.getDisplayMetrics());
return x;
}
Overall, the heights look ok, but the widths don't look good. For instance, the width of the row will look such that on a smaller device, the information neatly displays across the row, which is what I want. However,when I try to run the app on a tablet, for instance, the information will only stretch to half of the row, which doesn't look good. I want the sizes to scale and neatly display just like on the smaller device.
If anyone has any idea what my problem might be, I would greatly appreciate it. Below is the source for adding a row using java:
LinearLayout row = new LinearLayout(mContext);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setId(Integer.parseInt(txn.getId().toString()));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, convertToPixels(60));
params.setMargins(0, convertToPixels(1), 0, 0);
row.setLayoutParams(params);
row.setBackgroundColor(mContext.getResources().getColor(R.color.white));
LinearLayout imageLayout = new LinearLayout(mContext);
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(convertToPixels(40), convertToPixels(40));
imageParams.gravity = Gravity.CENTER;
imageLayout.setLayoutParams(imageParams);
ImageView image = new ImageView(mContext);
if (txn.getTransactionStateID() == Constants.TXN_STATUS_OK) {
image.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ok));
} else if (txn.getTransactionStateID() == Constants.TXN_STATUS_SUSPICIOUS) {
image.setImageDrawable(mContext.getResources().getDrawable(R.drawable.alert));
} else if (txn.getTransactionStateID() == Constants.TXN_STATUS_RED_FLAG) {
image.setImageDrawable(mContext.getResources().getDrawable(R.drawable.flag));
}
imageLayout.addView(image);
row.addView(imageLayout);
LinearLayout txnMiddleLayout = new LinearLayout(mContext);
txnMiddleLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams txnTopParams = new LinearLayout.LayoutParams(convertToPixels(400), convertToPixels(60));
txnTopParams.setMargins(convertToPixels(10), 0, 0, 0);
txnMiddleLayout.setLayoutParams(txnTopParams);
TextView txnTopContents = new TextView(mContext);
txnTopContents.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, convertToPixels(30)));
txnTopContents.setText(txn.getTopLineContents());
txnTopContents.setTextColor(Color.BLACK);
// txnTopContents.setTextSize(convertToPixels(16));
TextView txnBottomContents = new TextView(mContext);
txnBottomContents.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, convertToPixels(30)));
txnBottomContents.setText(txn.getBottomLineContents());
// txnBottomContents.setTextSize(convertToPixels(12));
txnMiddleLayout.addView(txnTopContents);
txnMiddleLayout.addView(txnBottomContents);
row.addView(txnMiddleLayout);
LinearLayout txnBottomLayout = new LinearLayout(mContext);
txnBottomLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams txnBottomParams = new LinearLayout.LayoutParams(convertToPixels(120), convertToPixels(60));
txnBottomLayout.setLayoutParams(txnBottomParams);
TextView amount = new TextView(mContext);
amount.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, convertToPixels(30)));
amount.setText(txn.getAmountStr());
amount.setTextColor(Color.BLACK);
// amount.setTextSize(convertToPixels(16));
TextView date = new TextView(mContext);
date.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, convertToPixels(30)));
date.setText(txn.getDateStr());
// date.setTextSize(convertToPixels(12));
txnBottomLayout.addView(amount);
txnBottomLayout.addView(date);
row.addView(txnBottomLayout);
txnList.addView(row);
I eventually found a solution. Instead of trying to set an exact width value, I set the width of the layout or textview to 0, and used layout_weight instead.
https://stackoverflow.com/a/3996104/4056947
for (int i = 0; i < c.getCount(); i++)
{
ChildLayout=new LinearLayout(getActivity());
ChildLayout.setWeightSum(100);
ChildLayout.setOrientation(LinearLayout.HORIZONTAL);
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
ChildLayout.setId(i);
Prd_txt = new TextView(getActivity());
Prd_txt.setId(c.getInt(3));
ProdStr_All.add(c.getString(4));
ProdTxt_All.add(Prd_txt);
Prd_txt.setPadding(8, 0, 0, 0);
edit_phy = new EditText(getActivity());
edit_phyAll.add(edit_phy);
edit_phy.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
edit_phy.setId(Dist_cat[k]);
edit_phy.setGravity(Gravity.RIGHT);
edit_trn = new EditText(getActivity());
edit_trnAll.add(edit_trn);
edit_trn.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
edit_trn.setId(Dist_cat[k]);
edit_trn.setGravity(Gravity.RIGHT);
Total=new TextView((getActivity()));
tot_all.add(Total);
Total.setId(k);
Total.setGravity(Gravity.RIGHT);
Total.setTextSize((global_variables.ConvertPixels(getActivity(), 19)));
LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT,50);
LinearLayout.LayoutParams layoutParams3 = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT,16);
ChildLayout.addView(Prd_txt, 0,layoutParams2);
ChildLayout.addView(edit_phy, 1,layoutParams3);
ChildLayout.addView(edit_trn, 2,layoutParams3);
ChildLayout.addView(Total, 3,layoutParams3);
if(i%2==0)
{
ChildLayout.setBackgroundResource(R.color.colortablelight);
}else
{
ChildLayout.setBackgroundResource(R.color.colortablemedium);
}
MainLayout.addView(ChildLayout,layoutParams);
c.moveToNext();
}
for(int m=0;m<ProdTxt_All.size();m++)
{
ProdTxt_All.get(m).setText(ProdStr_All.get(m));
}
output:
Problem:
I want to divide my linear layout in fixed size of Product weightsum 50 and rest
16 but could not achieve that, Tried to add height and width, but in different resolution it shows differently. So tried for weightsum. How to solve?
#Rashmi S
What is the problem doing that on XML? since its easier to handle especially with UI Designer software or what you called that and its more cleaner from the perspective of maintainability and readability. Thats only my opinion, in case you got some reason to do that, possibly there's an alternative aproach.
By using WRAP_CONTENT and weight at the same time, LinearLayout will calculate and prepare enough space for content before taking care of the weight. That's why sometimes you see this warning when setup views inside design layout with xml.
To ensure the parent view separates childs by weight properly, setup height = 0 (VERTICAL) as well as width = 0 (HORIZONTAL) before weight.
LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT,50);
LinearLayout.LayoutParams layoutParams3 = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT,16);
I have made an Android app that I am trying to port over to a blackberry 10 device. Currently, all of the functions of the app work except for one, where I try and get information about recent calls from the phone. This works fine on android, but does not seem to work on the blackberry 10 simulator I am using. Here is my code for the section:
final TextView time = (TextView) findViewById(R.id.AddNewEditTextTime);
final TextView date = (TextView) findViewById(R.id.AddNewEditTextDate);
final TextView number = (TextView) findViewById(R.id.AddNewEditTextNumber);
// fields to select.
String[] strFields = { android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.TYPE,
android.provider.CallLog.Calls.CACHED_NAME,
android.provider.CallLog.Calls.CACHED_NUMBER_TYPE,
android.provider.CallLog.Calls.DATE};
// only incoming.
String strSelection = android.provider.CallLog.Calls.TYPE + " = "
+ android.provider.CallLog.Calls.INCOMING_TYPE;
// most recent first
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
// get a cursor.
Cursor mCallCursor = getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, // content provider
// URI
strFields, // project (fields to get)
strSelection, // selection
null, // selection args
strOrder // sortorder.
);
if (mCallCursor.moveToFirst()) {
String a = mCallCursor.getString(mCallCursor
.getColumnIndex("date"));
String b = mCallCursor.getString(mCallCursor
.getColumnIndex("number"));
mCallCursor.close();
SimpleDateFormat dateF = new SimpleDateFormat("dd-MMM-yyyy");
SimpleDateFormat timeF = new SimpleDateFormat("HH:mm");
String dateString = dateF.format(new Date(Long
.parseLong(a)));
String timeString = timeF.format(new Date(Long
.parseLong(a)));
time.setText(timeString);
date.setText(dateString);
number.setText(b);
}
The if(mCallCursor.moveToFirst()) statement is never entered on the blackberry 10 device, but works fine on Android. Is there something I'm missing / doing wrong, or is there no way to use the android.provider functions like this on a blackberry 10 device?
Apparently accessing call log is not yet supported
This is not supported, the Android API is not hooked up to retreive this data.
Edit: Usually when there's an equivalent native API, the corresponding API in Android will be supported. The Android API almost always uses the native equivalent for its implementation. AFAIK there isn't a native call logs API.
By bbenninger, at support forums.
// fetch window manager object
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// set layout parameter of window manager
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
30, // width of layout 30 px
200, // height is equal to full screen
WindowManager.LayoutParams.TYPE_PHONE, // Type Ohone, These are non-application windows providing user interaction with the phone (in particular incoming calls).
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
// WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH // this window won't ever get key input focus
PixelFormat.TRANSLUCENT
);
mParams.gravity = Gravity.LEFT | Gravity.TOP;
//mParams.setTitle("Load Average");
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
mWindowManager.addView(touchLayout, mParams);
touchLayout.setOnTouchListener(this);
This is just a snippet of the code. My first issue was receiving touches in the view which this will do, however, the soft keyboard fails to open when touching edit text boxes in other applications while this service is running. I have tried various flags which fix the issue, but I loose the ability to register the touch event to the portion of the screen as displayed above in the code.
I'm out of ideas, does anyone have any idea of where I am going wrong, or an alternative solution for Android 4.2.2+?
try this:
Dialog dialog = new Dialog(this,android.R.style.Theme_DeviceDefault_Dialog_NoActionBar_MinWidth);
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.setContentView(new EditText(this));
dialog.show();
I have implemented a custom scroll view (not list view). Its using Intent Service to hit the server with offset and limit and display the result. For instance. i set offset = 0 and limit = FIRST_BATCH (int FIRST_BATCH = 15) for the first call. Its returning 15 names and details. And the next intent service call. I am using offset = FIRST_BATCH and limit = FIRST_BATCH. Its retuning next 15 names, from 15 to 30. And i am displaying Load More button at the end of 30 names. Here is my problem. Once i hit Load More button, i want to display the next 15 names, with offset = FIRST_BATCH + FIRST_BATCH and limit = FIRST_BATCH. And it will be growing more ..... Here is my implementation ....
private void startName(){
Intent getNameSearch = new Intent(getSherlockActivity(), IntentService.class);
getNameSearch.putExtra("search_offset", 0);
getNameSearch.putExtra("search_limit", FIRST_BATCH);
getNameSearch.setAction(IntentService.ACTION_GET_NAMESEARCH);
getSherlockActivity().startService(getNameSearch);
mCallback.onCreateProgressDialog();
getNameSearch = new Intent(getSherlockActivity(), IntentService.class);
getNameSearch.putExtra("search_offset", FIRST_BATCH);
getNameSearch.putExtra("search_limit", FIRST_BATCH);
getNameSearch.setAction(IntentService.ACTION_GET_NAMESEARCH);
getSherlockActivity().startService(getNameSearch);
mCallback.onCreateProgressDialog();
}
Once the view is displayed. I am loading the LoadMore Button. And once i click the LoadMore button i am calling the intent service again. But i know this is wrong. As the offset will be always 30 everytime. So the name will be displayed from 30 to 45 all the time. I want this to grow. Say, after i click LoadMore button. I want this to be 30 to 45 and Again hit the load More button, it should be 45 to 60 and goes on ...
final Button btnAddMore = (Button) myNameSearch.findViewById(R.id.loadMore);
btnAddMore.setVisibility(View.VISIBLE);
loadMoreButton = false;
btnAddMore.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
loadMoreButton();
}
});
And here is the loadMoreSpinner method
private void loadMoreButton(){
Intent getNameSearch = new Intent(getSherlockActivity(), IntentService.class);
int finalOffset = FIRST_BATCH * 2;
getNameSearch.putExtra("search_offset", finalOffset);
getNameSearch.putExtra("search_limit", FIRST_BATCH);
getNameSearch.setAction(IntentService.ACTION_GET_NAMESEARCH);
getSherlockActivity().startService(getNameSearch);
mCallback.onCreateProgressDialog();
}